diff --git a/official/2.1.6+2.1.beta1/DemoProj/.cvsignore b/official/2.1.6+2.1.beta1/DemoProj/.cvsignore new file mode 100644 index 0000000..9783b61 --- /dev/null +++ b/official/2.1.6+2.1.beta1/DemoProj/.cvsignore @@ -0,0 +1,5 @@ +*.dcu +*.exe +*.hpp +*.obj +*.tds diff --git a/official/2.1.6+2.1.beta1/DemoProj/Demo.cfg b/official/2.1.6+2.1.beta1/DemoProj/Demo.cfg new file mode 100644 index 0000000..6b67b6f --- /dev/null +++ b/official/2.1.6+2.1.beta1/DemoProj/Demo.cfg @@ -0,0 +1,33 @@ +-$A+ +-$B- +-$C+ +-$D+ +-$E- +-$F- +-$G+ +-$H+ +-$I+ +-$J+ +-$K- +-$L+ +-$M- +-$N+ +-$O+ +-$P+ +-$Q- +-$R- +-$S- +-$T- +-$U- +-$V+ +-$W- +-$X+ +-$Y- +-$Z1 +-cg +-AWinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE; +-H+ +-W+ +-M +-$M16384,1048576 +-K$00400000 diff --git a/official/2.1.6+2.1.beta1/DemoProj/Demo.dof b/official/2.1.6+2.1.beta1/DemoProj/Demo.dof new file mode 100644 index 0000000..d8a22f2 --- /dev/null +++ b/official/2.1.6+2.1.beta1/DemoProj/Demo.dof @@ -0,0 +1,29 @@ +[Compiler] +A=1 +B=0 +C=1 +D=1 +E=0 +F=0 +G=1 +H=1 +I=1 +J=1 +K=0 +L=1 +M=0 +N=1 +O=1 +P=1 +Q=0 +R=0 +S=0 +T=0 +U=0 +V=1 +W=0 +X=1 +Y=0 +Z=1 +ShowHints=1 +ShowWarnings=1 diff --git a/official/2.1.6+2.1.beta1/DemoProj/Demo.dpr b/official/2.1.6+2.1.beta1/DemoProj/Demo.dpr new file mode 100644 index 0000000..e91b3df --- /dev/null +++ b/official/2.1.6+2.1.beta1/DemoProj/Demo.dpr @@ -0,0 +1,14 @@ +program Demo; + +uses + Forms, + Demo1 in 'Demo1.pas' {Form1}; + +{$R *.RES} + +begin + Application.Initialize; + Application.CreateForm(TForm1, Form1); + Application.Run; +end. + diff --git a/official/2.1.6+2.1.beta1/DemoProj/Demo.res b/official/2.1.6+2.1.beta1/DemoProj/Demo.res new file mode 100644 index 0000000..a8371ab Binary files /dev/null and b/official/2.1.6+2.1.beta1/DemoProj/Demo.res differ diff --git a/official/2.1.6+2.1.beta1/DemoProj/Demo1.dfm b/official/2.1.6+2.1.beta1/DemoProj/Demo1.dfm new file mode 100644 index 0000000..2ebc239 Binary files /dev/null and b/official/2.1.6+2.1.beta1/DemoProj/Demo1.dfm differ diff --git a/official/2.1.6+2.1.beta1/DemoProj/Demo1.pas b/official/2.1.6+2.1.beta1/DemoProj/Demo1.pas new file mode 100644 index 0000000..5ad5d76 --- /dev/null +++ b/official/2.1.6+2.1.beta1/DemoProj/Demo1.pas @@ -0,0 +1,253 @@ +unit Demo1; + +{ + Toolbar2000 demo project + + $jrsoftware: tb2k/DemoProj/Demo1.pas,v 1.8 2003/07/09 21:16:25 jr Exp $ +} + +interface + +uses + Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, + StdCtrls, ExtCtrls, Menus, ActnList, ImgList, ComCtrls, + TB2Item, TB2ExtItems, TB2Dock, TB2Toolbar, TB2MRU; + +type + TForm1 = class(TForm) + ActionList: TActionList; + actNew: TAction; + actOpen: TAction; + actSave: TAction; + actSaveAs: TAction; + actPageSetup: TAction; + actPrint: TAction; + actExit: TAction; + actUndo: TAction; + actCut: TAction; + actCopy: TAction; + actPaste: TAction; + actDelete: TAction; + actSelectAll: TAction; + actTimeDate: TAction; + actWordWrap: TAction; + actSetFont: TAction; + actFind: TAction; + actFindNext: TAction; + actReplace: TAction; + actHelpTopics: TAction; + actAbout: TAction; + actTestButton: TAction; + actTestEdit: TTBEditAction; + DockTop: TTBDock; + MenuToolbar: TTBToolbar; + ImageList: TTBImageList; + FMenu: TTBSubmenuItem; + FNew: TTBItem; + FOpen: TTBItem; + FSave: TTBItem; + FSaveAs: TTBItem; + FPageSetup: TTBItem; + FPrint: TTBItem; + FExit: TTBItem; + EMenu: TTBSubmenuItem; + EUndo: TTBItem; + ECut: TTBItem; + ECopy: TTBItem; + EPaste: TTBItem; + EDelete: TTBItem; + ESelectAll: TTBItem; + ETimeDate: TTBItem; + EWordWrap: TTBItem; + ESetFont: TTBItem; + SMenu: TTBSubmenuItem; + SFind: TTBItem; + SFindNext: TTBItem; + SReplace: TTBItem; + HMenu: TTBSubmenuItem; + HHelpTopics: TTBItem; + HAbout: TTBItem; + FMRU: TTBMRUListItem; + NBSeparatorItem3: TTBSeparatorItem; + NBSeparatorItem4: TTBSeparatorItem; + TestEdit: TTBEditItem; + MainToolbar: TTBToolbar; + NewButton: TTBItem; + OpenButton: TTBItem; + SaveButton: TTBItem; + DockBottom: TTBDock; + DockLeft: TTBDock; + DockRight: TTBDock; + BottomToolbar: TTBToolbar; + PopupMenuBarButton: TTBItem; + PopupToolbarButton: TTBItem; + Memo1: TMemo; + ContextPopupMenu: TTBPopupMenu; + StatusBar: TStatusBar; + ToolbarPopupMenu: TTBPopupMenu; + MRUList: TTBMRUList; + PrintButton: TTBItem; + CutButton: TTBItem; + CopyButton: TTBItem; + PasteButton: TTBItem; + UndoButton: TTBSubmenuItem; + actPrintPreview: TAction; + TBItem1: TTBItem; + FormatToolbar: TTBToolbar; + BoldItem: TTBItem; + ItalicItem: TTBItem; + UnderlineItem: TTBItem; + TBSeparatorItem1: TTBSeparatorItem; + AlignLeftItem: TTBItem; + CenterItem: TTBItem; + AlignRightItem: TTBItem; + TBSeparatorItem2: TTBSeparatorItem; + BulletsItem: TTBItem; + NBItem34: TTBItem; + NBSeparatorItem6: TTBSeparatorItem; + NBItem35: TTBItem; + NBItem36: TTBItem; + NBItem37: TTBItem; + NBItem38: TTBItem; + NBSeparatorItem7: TTBSeparatorItem; + NBItem39: TTBItem; + ComboBox1: TComboBox; + TBControlItem1: TTBControlItem; + TBSeparatorItem3: TTBSeparatorItem; + TBControlItem2: TTBControlItem; + ComboBox2: TComboBox; + actBold: TAction; + actItalic: TAction; + actUnderline: TAction; + actAlignLeft: TAction; + actCenter: TAction; + actAlignRight: TAction; + TBSeparatorItem4: TTBSeparatorItem; + actRedo: TAction; + RedoButton: TTBSubmenuItem; + TBItem2: TTBItem; + TBItem3: TTBItem; + TBItem4: TTBItem; + ERedo: TTBItem; + VMenu: TTBSubmenuItem; + VToolbars: TTBSubmenuItem; + VTStandard: TTBVisibilityToggleItem; + VTFormatting: TTBVisibilityToggleItem; + VTBottom: TTBVisibilityToggleItem; + VStatusBar: TTBItem; + actBullets: TAction; + procedure FormCreate(Sender: TObject); + procedure ItemClick(Sender: TObject); + procedure PopupMenuBarButtonClick(Sender: TObject); + procedure PopupToolbarButtonClick(Sender: TObject); + procedure MRUListClick(Sender: TObject; const Filename: String); + procedure AlignClick(Sender: TObject); + procedure BulletsItemClick(Sender: TObject); + procedure BoldItemClick(Sender: TObject); + procedure ItalicItemClick(Sender: TObject); + procedure UnderlineItemClick(Sender: TObject); + procedure VStatusBarClick(Sender: TObject); + procedure VMenuClick(Sender: TObject); + private + { Private declarations } + procedure OnHint(Sender: TObject); + public + { Public declarations } + end; + +var + Form1: TForm1; + +implementation + +uses + CommCtrl, TB2Version; + +{$R *.DFM} + +procedure TForm1.FormCreate(Sender: TObject); +begin + Memo1.Text := 'Running on TB2000 version ' + Toolbar2000Version; + Application.OnHint := OnHint; +end; + +procedure TForm1.OnHint(Sender: TObject); +begin + StatusBar.Panels[0].Text := Application.Hint; +end; + +procedure TForm1.ItemClick(Sender: TObject); +begin + if Sender is TComponent then + Application.MessageBox(PChar('You selected:'#13#10#13#10 + + TComponent(Sender).Name), 'OnClick handler', + MB_OK or MB_ICONINFORMATION); +end; + +procedure TForm1.MRUListClick(Sender: TObject; const Filename: String); +begin + Application.MessageBox(PChar(Format('You selected "%s" from the MRU list.', + [Filename])), 'MRUListClick', MB_OK or MB_ICONINFORMATION); +end; + +procedure TForm1.VMenuClick(Sender: TObject); +begin + VStatusBar.Checked := StatusBar.Visible; +end; + +procedure TForm1.VStatusBarClick(Sender: TObject); +begin + { Force the StatusBar to always be at the bottom of the form. Without this + line of code, the status bar sometimes may appear above the bottom dock. + This is not a bug in Toolbar2000, but rather is due to the design of the + VCL's alignment system. } + StatusBar.Top := ClientHeight; + + { Toggle the status bar's visibility } + StatusBar.Visible := not StatusBar.Visible; +end; + +procedure TForm1.AlignClick(Sender: TObject); +begin + AlignLeftItem.Checked := (Sender = actAlignLeft); + CenterItem.Checked := (Sender = actCenter); + AlignRightItem.Checked := (Sender = actAlignRight); +end; + +procedure TForm1.BulletsItemClick(Sender: TObject); +begin + BulletsItem.Checked := not BulletsItem.Checked; +end; + +procedure TForm1.BoldItemClick(Sender: TObject); +begin + BoldItem.Checked := not BoldItem.Checked; +end; + +procedure TForm1.ItalicItemClick(Sender: TObject); +begin + ItalicItem.Checked := not ItalicItem.Checked; +end; + +procedure TForm1.UnderlineItemClick(Sender: TObject); +begin + UnderlineItem.Checked := not UnderlineItem.Checked; +end; + +procedure TForm1.PopupMenuBarButtonClick(Sender: TObject); +var + P: TPoint; +begin + P := Memo1.ClientToScreen(Point(8, 8)); + MenuToolbar.Items.Popup(P.X, P.Y, True); +end; + +procedure TForm1.PopupToolbarButtonClick(Sender: TObject); +var + P: TPoint; +begin + P := Memo1.ClientToScreen(Point(8, 8)); + MainToolbar.Items.Popup(P.X, P.Y, True); +end; + +end. diff --git a/official/2.1.6+2.1.beta1/DemoProj/DemoBCB.bpr b/official/2.1.6+2.1.beta1/DemoProj/DemoBCB.bpr new file mode 100644 index 0000000..9800232 --- /dev/null +++ b/official/2.1.6+2.1.beta1/DemoProj/DemoBCB.bpr @@ -0,0 +1,179 @@ +# --------------------------------------------------------------------------- +!if !$d(BCB) +BCB = $(MAKEDIR)\.. +!endif + +# --------------------------------------------------------------------------- +# IDE SECTION +# --------------------------------------------------------------------------- +# The following section of the project makefile is managed by the BCB IDE. +# It is recommended to use the IDE to change any of the values in this +# section. +# --------------------------------------------------------------------------- + +VERSION = BCB.04.04 +# --------------------------------------------------------------------------- +PROJECT = DemoBCB.exe +OBJFILES = Demo1.obj DemoBCB.obj +RESFILES = DemoBCB.res +RESDEPEN = $(RESFILES) Demo1.dfm +LIBFILES = +LIBRARIES = vcl40.lib +SPARELIBS = vcl40.lib +PACKAGES = +DEFFILE = +# --------------------------------------------------------------------------- +PATHCPP = .; +PATHASM = .; +PATHPAS = .; +PATHRC = .; +DEBUGLIBPATH = $(BCB)\lib\debug +RELEASELIBPATH = $(BCB)\lib\release +USERDEFINES = +SYSDEFINES = _RTLDLL;NO_STRICT +# --------------------------------------------------------------------------- +CFLAG1 = -I$(BCB)\include;$(BCB)\include\vcl -Od -Hc -H=$(BCB)\lib\vcl40.csm -w -Ve -r- \ + -a8 -k -y -v -vi- -c -b- -w-par -w-inl -Vx -tW -tWM \ + -D$(SYSDEFINES);$(USERDEFINES) +PFLAGS = -U$(BCB)\Projects\Lib;$(BCB)\lib\obj;$(BCB)\lib;$(RELEASELIBPATH) \ + -I$(BCB)\include;$(BCB)\include\vcl -$YD -$W -$O- -v -JPHNE -M +RFLAGS = -i$(BCB)\include;$(BCB)\include\vcl +AFLAGS = /i$(BCB)\include /i$(BCB)\include\vcl /mx /w2 /zd +LFLAGS = -L$(BCB)\Projects\Lib;$(BCB)\lib\obj;$(BCB)\lib;$(RELEASELIBPATH) -aa -Tpe -x \ + -Gn -v +# --------------------------------------------------------------------------- +ALLOBJ = c0w32.obj Memmgr.Lib sysinit.obj $(OBJFILES) +ALLRES = $(RESFILES) +ALLLIB = $(LIBFILES) $(LIBRARIES) import32.lib cp32mti.lib +# --------------------------------------------------------------------------- +!ifdef IDEOPTIONS + +[Version Info] +IncludeVerInfo=0 +AutoIncBuild=0 +MajorVer=1 +MinorVer=0 +Release=0 +Build=0 +Debug=0 +PreRelease=0 +Special=0 +Private=0 +DLL=0 +Locale=1033 +CodePage=1252 + +[Version Info Keys] +CompanyName= +FileDescription= +FileVersion=1.0.0.0 +InternalName= +LegalCopyright= +LegalTrademarks= +OriginalFilename= +ProductName= +ProductVersion=1.0.0.0 +Comments= + +[Debugging] +DebugSourceDirs=$(BCB)\source\vcl + +[Parameters] +RunParams= +HostApplication= +RemoteHost= +RemotePath= +RemoteDebug=0 + +[Compiler] +InMemoryExe=0 +ShowInfoMsgs=0 + +!endif + +# --------------------------------------------------------------------------- +# MAKE SECTION +# --------------------------------------------------------------------------- +# This section of the project file is not used by the BCB IDE. It is for +# the benefit of building from the command-line using the MAKE utility. +# --------------------------------------------------------------------------- + +.autodepend +# --------------------------------------------------------------------------- +!if !$d(BCC32) +BCC32 = bcc32 +!endif + +!if !$d(CPP32) +CPP32 = cpp32 +!endif + +!if !$d(DCC32) +DCC32 = dcc32 +!endif + +!if !$d(TASM32) +TASM32 = tasm32 +!endif + +!if !$d(LINKER) +LINKER = ilink32 +!endif + +!if !$d(BRCC32) +BRCC32 = brcc32 +!endif + +# --------------------------------------------------------------------------- +!if $d(PATHCPP) +.PATH.CPP = $(PATHCPP) +.PATH.C = $(PATHCPP) +!endif + +!if $d(PATHPAS) +.PATH.PAS = $(PATHPAS) +!endif + +!if $d(PATHASM) +.PATH.ASM = $(PATHASM) +!endif + +!if $d(PATHRC) +.PATH.RC = $(PATHRC) +!endif +# --------------------------------------------------------------------------- +$(PROJECT): $(OBJFILES) $(RESDEPEN) $(DEFFILE) + $(BCB)\BIN\$(LINKER) @&&! + $(LFLAGS) + + $(ALLOBJ), + + $(PROJECT),, + + $(ALLLIB), + + $(DEFFILE), + + $(ALLRES) +! +# --------------------------------------------------------------------------- +.pas.hpp: + $(BCB)\BIN\$(DCC32) $(PFLAGS) {$< } + +.pas.obj: + $(BCB)\BIN\$(DCC32) $(PFLAGS) {$< } + +.cpp.obj: + $(BCB)\BIN\$(BCC32) $(CFLAG1) -n$(@D) {$< } + +.c.obj: + $(BCB)\BIN\$(BCC32) $(CFLAG1) -n$(@D) {$< } + +.c.i: + $(BCB)\BIN\$(CPP32) $(CFLAG1) -n. {$< } + +.cpp.i: + $(BCB)\BIN\$(CPP32) $(CFLAG1) -n. {$< } + +.asm.obj: + $(BCB)\BIN\$(TASM32) $(AFLAGS) $<, $@ + +.rc.res: + $(BCB)\BIN\$(BRCC32) $(RFLAGS) -fo$@ $< +# --------------------------------------------------------------------------- + diff --git a/official/2.1.6+2.1.beta1/DemoProj/DemoBCB.cpp b/official/2.1.6+2.1.beta1/DemoProj/DemoBCB.cpp new file mode 100644 index 0000000..b4ea3e5 --- /dev/null +++ b/official/2.1.6+2.1.beta1/DemoProj/DemoBCB.cpp @@ -0,0 +1,22 @@ +//--------------------------------------------------------------------------- +#include +#pragma hdrstop +USERES("DemoBCB.res"); +USEFORMNS("Demo1.pas", Demo1, Form1); +//--------------------------------------------------------------------------- +WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) +{ + try + { + Application->Initialize(); + Application->CreateForm(__classid(TForm1), &Form1); + Application->Run(); + } + catch (Exception &exception) + { + Application->ShowException(&exception); + } + return 0; +} +//--------------------------------------------------------------------------- + diff --git a/official/2.1.6+2.1.beta1/DemoProj/DemoBCB.res b/official/2.1.6+2.1.beta1/DemoProj/DemoBCB.res new file mode 100644 index 0000000..32b522d Binary files /dev/null and b/official/2.1.6+2.1.beta1/DemoProj/DemoBCB.res differ diff --git a/official/2.1.6+2.1.beta1/DemoProj/DemoBCB6.bpr b/official/2.1.6+2.1.beta1/DemoProj/DemoBCB6.bpr new file mode 100644 index 0000000..28a1267 --- /dev/null +++ b/official/2.1.6+2.1.beta1/DemoProj/DemoBCB6.bpr @@ -0,0 +1,115 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +[Version Info] +IncludeVerInfo=0 +AutoIncBuild=0 +MajorVer=1 +MinorVer=0 +Release=0 +Build=0 +Debug=0 +PreRelease=0 +Special=0 +Private=0 +DLL=0 +Locale=1033 +CodePage=1252 + +[Version Info Keys] +CompanyName= +FileDescription= +FileVersion=1.0.0.0 +InternalName= +LegalCopyright= +LegalTrademarks= +OriginalFilename= +ProductName= +ProductVersion=1.0.0.0 +Comments= + +[Debugging] +DebugSourceDirs=$(BCB)\source\vcl + +[Parameters] +RunParams= +Launcher= +UseLauncher=0 +DebugCWD= +HostApplication= +RemoteHost= +RemotePath= +RemoteLauncher= +RemoteCWD= +RemoteDebug=0 + +[Compiler] +ShowInfoMsgs=0 +LinkDebugVcl=0 +LinkCGLIB=0 + +[Language] +ActiveLang= +ProjectLang= +RootDir= + + \ No newline at end of file diff --git a/official/2.1.6+2.1.beta1/DemoProj/DemoBCB6.cpp b/official/2.1.6+2.1.beta1/DemoProj/DemoBCB6.cpp new file mode 100644 index 0000000..c762f01 --- /dev/null +++ b/official/2.1.6+2.1.beta1/DemoProj/DemoBCB6.cpp @@ -0,0 +1,34 @@ +//--------------------------------------------------------------------------- + +#include +#pragma hdrstop +//--------------------------------------------------------------------------- +USEFORMNS("Demo1.pas", Demo1, Form1); +//--------------------------------------------------------------------------- +WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) +{ + try + { + Application->Initialize(); + Application->CreateForm(__classid(TForm1), &Form1); + Application->Run(); + } + catch (Exception &exception) + { + Application->ShowException(&exception); + } + catch (...) + { + try + { + throw Exception(""); + } + catch (Exception &exception) + { + Application->ShowException(&exception); + } + } + return 0; +} +//--------------------------------------------------------------------------- + diff --git a/official/2.1.6+2.1.beta1/DemoProj/DemoBCB6.res b/official/2.1.6+2.1.beta1/DemoProj/DemoBCB6.res new file mode 100644 index 0000000..e468bf9 Binary files /dev/null and b/official/2.1.6+2.1.beta1/DemoProj/DemoBCB6.res differ diff --git a/official/2.1.6+2.1.beta1/GPL-LICENSE.txt b/official/2.1.6+2.1.beta1/GPL-LICENSE.txt new file mode 100644 index 0000000..45645b4 --- /dev/null +++ b/official/2.1.6+2.1.beta1/GPL-LICENSE.txt @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/official/2.1.6+2.1.beta1/Glyphs.zip b/official/2.1.6+2.1.beta1/Glyphs.zip new file mode 100644 index 0000000..6070442 Binary files /dev/null and b/official/2.1.6+2.1.beta1/Glyphs.zip differ diff --git a/official/2.1.6+2.1.beta1/LICENSE.txt b/official/2.1.6+2.1.beta1/LICENSE.txt new file mode 100644 index 0000000..0cc17e9 --- /dev/null +++ b/official/2.1.6+2.1.beta1/LICENSE.txt @@ -0,0 +1,17 @@ +All files included in the Toolbar2000 archive are Copyright (C) 1998-2005 +Jordan Russell. + +Use and/or distribution of the files requires compliance with the +"Toolbar2000 License", found in TB2k-LICENSE.txt or at: + + http://www.jrsoftware.org/files/tb2k/TB2k-LICENSE.txt + +Alternatively, at your option, the files may be used and/or distributed under +the terms of the "GNU General Public License", found in GPL-LICENSE.txt or at: + + http://www.jrsoftware.org/files/tb2k/GPL-LICENSE.txt + +NOTE: If you choose the GPL license option, your application as a whole must +also be licensed under the GPL. (Refer to section 2b of the GPL license.) +Therefore, you cannot choose the GPL license option if your application is +proprietary/closed-source. diff --git a/official/2.1.6+2.1.beta1/Lib/D10/TB2Acc.dcu b/official/2.1.6+2.1.beta1/Lib/D10/TB2Acc.dcu new file mode 100644 index 0000000..f063c76 Binary files /dev/null and b/official/2.1.6+2.1.beta1/Lib/D10/TB2Acc.dcu differ diff --git a/official/2.1.6+2.1.beta1/Lib/D10/TB2Anim.dcu b/official/2.1.6+2.1.beta1/Lib/D10/TB2Anim.dcu new file mode 100644 index 0000000..3466cc8 Binary files /dev/null and b/official/2.1.6+2.1.beta1/Lib/D10/TB2Anim.dcu differ diff --git a/official/2.1.6+2.1.beta1/Lib/D10/TB2Common.dcu b/official/2.1.6+2.1.beta1/Lib/D10/TB2Common.dcu new file mode 100644 index 0000000..4737332 Binary files /dev/null and b/official/2.1.6+2.1.beta1/Lib/D10/TB2Common.dcu differ diff --git a/official/2.1.6+2.1.beta1/Lib/D10/TB2Consts.dcu b/official/2.1.6+2.1.beta1/Lib/D10/TB2Consts.dcu new file mode 100644 index 0000000..acde0fe Binary files /dev/null and b/official/2.1.6+2.1.beta1/Lib/D10/TB2Consts.dcu differ diff --git a/official/2.1.6+2.1.beta1/Lib/D10/TB2Dock.dcu b/official/2.1.6+2.1.beta1/Lib/D10/TB2Dock.dcu new file mode 100644 index 0000000..4bcd690 Binary files /dev/null and b/official/2.1.6+2.1.beta1/Lib/D10/TB2Dock.dcu differ diff --git a/official/2.1.6+2.1.beta1/Lib/D10/TB2DsgnConvertOptions.dcu b/official/2.1.6+2.1.beta1/Lib/D10/TB2DsgnConvertOptions.dcu new file mode 100644 index 0000000..2a71935 Binary files /dev/null and b/official/2.1.6+2.1.beta1/Lib/D10/TB2DsgnConvertOptions.dcu differ diff --git a/official/2.1.6+2.1.beta1/Lib/D10/TB2DsgnConverter.dcu b/official/2.1.6+2.1.beta1/Lib/D10/TB2DsgnConverter.dcu new file mode 100644 index 0000000..e9eed85 Binary files /dev/null and b/official/2.1.6+2.1.beta1/Lib/D10/TB2DsgnConverter.dcu differ diff --git a/official/2.1.6+2.1.beta1/Lib/D10/TB2DsgnItemEditor.dcu b/official/2.1.6+2.1.beta1/Lib/D10/TB2DsgnItemEditor.dcu new file mode 100644 index 0000000..a165e44 Binary files /dev/null and b/official/2.1.6+2.1.beta1/Lib/D10/TB2DsgnItemEditor.dcu differ diff --git a/official/2.1.6+2.1.beta1/Lib/D10/TB2ExtItems.dcu b/official/2.1.6+2.1.beta1/Lib/D10/TB2ExtItems.dcu new file mode 100644 index 0000000..833aadc Binary files /dev/null and b/official/2.1.6+2.1.beta1/Lib/D10/TB2ExtItems.dcu differ diff --git a/official/2.1.6+2.1.beta1/Lib/D10/TB2Hook.dcu b/official/2.1.6+2.1.beta1/Lib/D10/TB2Hook.dcu new file mode 100644 index 0000000..93c2411 Binary files /dev/null and b/official/2.1.6+2.1.beta1/Lib/D10/TB2Hook.dcu differ diff --git a/official/2.1.6+2.1.beta1/Lib/D10/TB2Item.dcu b/official/2.1.6+2.1.beta1/Lib/D10/TB2Item.dcu new file mode 100644 index 0000000..8b003a6 Binary files /dev/null and b/official/2.1.6+2.1.beta1/Lib/D10/TB2Item.dcu differ diff --git a/official/2.1.6+2.1.beta1/Lib/D10/TB2MDI.dcu b/official/2.1.6+2.1.beta1/Lib/D10/TB2MDI.dcu new file mode 100644 index 0000000..fb1c506 Binary files /dev/null and b/official/2.1.6+2.1.beta1/Lib/D10/TB2MDI.dcu differ diff --git a/official/2.1.6+2.1.beta1/Lib/D10/TB2MRU.dcu b/official/2.1.6+2.1.beta1/Lib/D10/TB2MRU.dcu new file mode 100644 index 0000000..56fa72d Binary files /dev/null and b/official/2.1.6+2.1.beta1/Lib/D10/TB2MRU.dcu differ diff --git a/official/2.1.6+2.1.beta1/Lib/D10/TB2Reg.dcu b/official/2.1.6+2.1.beta1/Lib/D10/TB2Reg.dcu new file mode 100644 index 0000000..d506163 Binary files /dev/null and b/official/2.1.6+2.1.beta1/Lib/D10/TB2Reg.dcu differ diff --git a/official/2.1.6+2.1.beta1/Lib/D10/TB2ToolWindow.dcu b/official/2.1.6+2.1.beta1/Lib/D10/TB2ToolWindow.dcu new file mode 100644 index 0000000..0c5931f Binary files /dev/null and b/official/2.1.6+2.1.beta1/Lib/D10/TB2ToolWindow.dcu differ diff --git a/official/2.1.6+2.1.beta1/Lib/D10/TB2Toolbar.dcu b/official/2.1.6+2.1.beta1/Lib/D10/TB2Toolbar.dcu new file mode 100644 index 0000000..4cc09f5 Binary files /dev/null and b/official/2.1.6+2.1.beta1/Lib/D10/TB2Toolbar.dcu differ diff --git a/official/2.1.6+2.1.beta1/Lib/D10/TB2Version.dcu b/official/2.1.6+2.1.beta1/Lib/D10/TB2Version.dcu new file mode 100644 index 0000000..ce8118b Binary files /dev/null and b/official/2.1.6+2.1.beta1/Lib/D10/TB2Version.dcu differ diff --git a/official/2.1.6+2.1.beta1/Lib/D10/TBX.dcu b/official/2.1.6+2.1.beta1/Lib/D10/TBX.dcu new file mode 100644 index 0000000..a11edaa Binary files /dev/null and b/official/2.1.6+2.1.beta1/Lib/D10/TBX.dcu differ diff --git a/official/2.1.6+2.1.beta1/Lib/D10/TBXDefaultTheme.dcu b/official/2.1.6+2.1.beta1/Lib/D10/TBXDefaultTheme.dcu new file mode 100644 index 0000000..af13562 Binary files /dev/null and b/official/2.1.6+2.1.beta1/Lib/D10/TBXDefaultTheme.dcu differ diff --git a/official/2.1.6+2.1.beta1/Lib/D10/TBXDkPanels.dcu b/official/2.1.6+2.1.beta1/Lib/D10/TBXDkPanels.dcu new file mode 100644 index 0000000..07d3a88 Binary files /dev/null and b/official/2.1.6+2.1.beta1/Lib/D10/TBXDkPanels.dcu differ diff --git a/official/2.1.6+2.1.beta1/Lib/D10/TBXExtItems.dcu b/official/2.1.6+2.1.beta1/Lib/D10/TBXExtItems.dcu new file mode 100644 index 0000000..f370983 Binary files /dev/null and b/official/2.1.6+2.1.beta1/Lib/D10/TBXExtItems.dcu differ diff --git a/official/2.1.6+2.1.beta1/Lib/D10/TBXLists.dcu b/official/2.1.6+2.1.beta1/Lib/D10/TBXLists.dcu new file mode 100644 index 0000000..567e903 Binary files /dev/null and b/official/2.1.6+2.1.beta1/Lib/D10/TBXLists.dcu differ diff --git a/official/2.1.6+2.1.beta1/Lib/D10/TBXMDI.dcu b/official/2.1.6+2.1.beta1/Lib/D10/TBXMDI.dcu new file mode 100644 index 0000000..86fcec7 Binary files /dev/null and b/official/2.1.6+2.1.beta1/Lib/D10/TBXMDI.dcu differ diff --git a/official/2.1.6+2.1.beta1/Lib/D10/TBXOffice2003Theme.dcu b/official/2.1.6+2.1.beta1/Lib/D10/TBXOffice2003Theme.dcu new file mode 100644 index 0000000..2a851a9 Binary files /dev/null and b/official/2.1.6+2.1.beta1/Lib/D10/TBXOffice2003Theme.dcu differ diff --git a/official/2.1.6+2.1.beta1/Lib/D10/TBXOfficeXPTheme.dcu b/official/2.1.6+2.1.beta1/Lib/D10/TBXOfficeXPTheme.dcu new file mode 100644 index 0000000..617cea9 Binary files /dev/null and b/official/2.1.6+2.1.beta1/Lib/D10/TBXOfficeXPTheme.dcu differ diff --git a/official/2.1.6+2.1.beta1/Lib/D10/TBXReg.dcu b/official/2.1.6+2.1.beta1/Lib/D10/TBXReg.dcu new file mode 100644 index 0000000..fdd1c01 Binary files /dev/null and b/official/2.1.6+2.1.beta1/Lib/D10/TBXReg.dcu differ diff --git a/official/2.1.6+2.1.beta1/Lib/D10/TBXStatusBars.dcu b/official/2.1.6+2.1.beta1/Lib/D10/TBXStatusBars.dcu new file mode 100644 index 0000000..3331b16 Binary files /dev/null and b/official/2.1.6+2.1.beta1/Lib/D10/TBXStatusBars.dcu differ diff --git a/official/2.1.6+2.1.beta1/Lib/D10/TBXStrEdit.dcu b/official/2.1.6+2.1.beta1/Lib/D10/TBXStrEdit.dcu new file mode 100644 index 0000000..fb61538 Binary files /dev/null and b/official/2.1.6+2.1.beta1/Lib/D10/TBXStrEdit.dcu differ diff --git a/official/2.1.6+2.1.beta1/Lib/D10/TBXSwitcher.dcu b/official/2.1.6+2.1.beta1/Lib/D10/TBXSwitcher.dcu new file mode 100644 index 0000000..e13ef97 Binary files /dev/null and b/official/2.1.6+2.1.beta1/Lib/D10/TBXSwitcher.dcu differ diff --git a/official/2.1.6+2.1.beta1/Lib/D10/TBXThemes.dcu b/official/2.1.6+2.1.beta1/Lib/D10/TBXThemes.dcu new file mode 100644 index 0000000..baf5f22 Binary files /dev/null and b/official/2.1.6+2.1.beta1/Lib/D10/TBXThemes.dcu differ diff --git a/official/2.1.6+2.1.beta1/Lib/D10/TBXToolPals.dcu b/official/2.1.6+2.1.beta1/Lib/D10/TBXToolPals.dcu new file mode 100644 index 0000000..bd51f42 Binary files /dev/null and b/official/2.1.6+2.1.beta1/Lib/D10/TBXToolPals.dcu differ diff --git a/official/2.1.6+2.1.beta1/Lib/D10/TBXUtils.dcu b/official/2.1.6+2.1.beta1/Lib/D10/TBXUtils.dcu new file mode 100644 index 0000000..7cf6b55 Binary files /dev/null and b/official/2.1.6+2.1.beta1/Lib/D10/TBXUtils.dcu differ diff --git a/official/2.1.6+2.1.beta1/Lib/D10/TBXUxThemes.dcu b/official/2.1.6+2.1.beta1/Lib/D10/TBXUxThemes.dcu new file mode 100644 index 0000000..b450d1d Binary files /dev/null and b/official/2.1.6+2.1.beta1/Lib/D10/TBXUxThemes.dcu differ diff --git a/official/2.1.6+2.1.beta1/Lib/D10/TBXWhidbeyTheme.dcu b/official/2.1.6+2.1.beta1/Lib/D10/TBXWhidbeyTheme.dcu new file mode 100644 index 0000000..e19ceed Binary files /dev/null and b/official/2.1.6+2.1.beta1/Lib/D10/TBXWhidbeyTheme.dcu differ diff --git a/official/2.1.6+2.1.beta1/Lib/D10/TBX_MDI.res b/official/2.1.6+2.1.beta1/Lib/D10/TBX_MDI.res new file mode 100644 index 0000000..eb371ed Binary files /dev/null and b/official/2.1.6+2.1.beta1/Lib/D10/TBX_MDI.res differ diff --git a/official/2.1.6+2.1.beta1/Lib/D10/rmkThemes.dcu b/official/2.1.6+2.1.beta1/Lib/D10/rmkThemes.dcu new file mode 100644 index 0000000..205de5d Binary files /dev/null and b/official/2.1.6+2.1.beta1/Lib/D10/rmkThemes.dcu differ diff --git a/official/2.1.6+2.1.beta1/Lib/D10/tb2k_d10.dcu b/official/2.1.6+2.1.beta1/Lib/D10/tb2k_d10.dcu new file mode 100644 index 0000000..dac04fb Binary files /dev/null and b/official/2.1.6+2.1.beta1/Lib/D10/tb2k_d10.dcu differ diff --git a/official/2.1.6+2.1.beta1/Lib/D10/tb2kdsgn_d10.dcu b/official/2.1.6+2.1.beta1/Lib/D10/tb2kdsgn_d10.dcu new file mode 100644 index 0000000..6750ee6 Binary files /dev/null and b/official/2.1.6+2.1.beta1/Lib/D10/tb2kdsgn_d10.dcu differ diff --git a/official/2.1.6+2.1.beta1/Lib/D10/tbx_d10.bpl b/official/2.1.6+2.1.beta1/Lib/D10/tbx_d10.bpl new file mode 100644 index 0000000..2ec6b59 Binary files /dev/null and b/official/2.1.6+2.1.beta1/Lib/D10/tbx_d10.bpl differ diff --git a/official/2.1.6+2.1.beta1/Lib/D10/tbx_d10.dcp b/official/2.1.6+2.1.beta1/Lib/D10/tbx_d10.dcp new file mode 100644 index 0000000..c70e4ff Binary files /dev/null and b/official/2.1.6+2.1.beta1/Lib/D10/tbx_d10.dcp differ diff --git a/official/2.1.6+2.1.beta1/Lib/D10/tbx_d10.dcu b/official/2.1.6+2.1.beta1/Lib/D10/tbx_d10.dcu new file mode 100644 index 0000000..7be810d Binary files /dev/null and b/official/2.1.6+2.1.beta1/Lib/D10/tbx_d10.dcu differ diff --git a/official/2.1.6+2.1.beta1/Lib/D10/tbx_glyphs.res b/official/2.1.6+2.1.beta1/Lib/D10/tbx_glyphs.res new file mode 100644 index 0000000..06e6e86 Binary files /dev/null and b/official/2.1.6+2.1.beta1/Lib/D10/tbx_glyphs.res differ diff --git a/official/2.1.6+2.1.beta1/Lib/D10/tbxdsgn_d10.bpl b/official/2.1.6+2.1.beta1/Lib/D10/tbxdsgn_d10.bpl new file mode 100644 index 0000000..363a9bf Binary files /dev/null and b/official/2.1.6+2.1.beta1/Lib/D10/tbxdsgn_d10.bpl differ diff --git a/official/2.1.6+2.1.beta1/Lib/D10/tbxdsgn_d10.dcp b/official/2.1.6+2.1.beta1/Lib/D10/tbxdsgn_d10.dcp new file mode 100644 index 0000000..df18626 Binary files /dev/null and b/official/2.1.6+2.1.beta1/Lib/D10/tbxdsgn_d10.dcp differ diff --git a/official/2.1.6+2.1.beta1/Lib/D10/tbxdsgn_d10.dcu b/official/2.1.6+2.1.beta1/Lib/D10/tbxdsgn_d10.dcu new file mode 100644 index 0000000..7b36605 Binary files /dev/null and b/official/2.1.6+2.1.beta1/Lib/D10/tbxdsgn_d10.dcu differ diff --git a/official/2.1.6+2.1.beta1/Lib/D7/TB2Acc.dcu b/official/2.1.6+2.1.beta1/Lib/D7/TB2Acc.dcu new file mode 100644 index 0000000..78b990b Binary files /dev/null and b/official/2.1.6+2.1.beta1/Lib/D7/TB2Acc.dcu differ diff --git a/official/2.1.6+2.1.beta1/Lib/D7/TB2Anim.dcu b/official/2.1.6+2.1.beta1/Lib/D7/TB2Anim.dcu new file mode 100644 index 0000000..59dcff3 Binary files /dev/null and b/official/2.1.6+2.1.beta1/Lib/D7/TB2Anim.dcu differ diff --git a/official/2.1.6+2.1.beta1/Lib/D7/TB2Common.dcu b/official/2.1.6+2.1.beta1/Lib/D7/TB2Common.dcu new file mode 100644 index 0000000..caf98bb Binary files /dev/null and b/official/2.1.6+2.1.beta1/Lib/D7/TB2Common.dcu differ diff --git a/official/2.1.6+2.1.beta1/Lib/D7/TB2Consts.dcu b/official/2.1.6+2.1.beta1/Lib/D7/TB2Consts.dcu new file mode 100644 index 0000000..fcf50c3 Binary files /dev/null and b/official/2.1.6+2.1.beta1/Lib/D7/TB2Consts.dcu differ diff --git a/official/2.1.6+2.1.beta1/Lib/D7/TB2Dock.dcu b/official/2.1.6+2.1.beta1/Lib/D7/TB2Dock.dcu new file mode 100644 index 0000000..a8fb5eb Binary files /dev/null and b/official/2.1.6+2.1.beta1/Lib/D7/TB2Dock.dcu differ diff --git a/official/2.1.6+2.1.beta1/Lib/D7/TB2DsgnConvertOptions.dcu b/official/2.1.6+2.1.beta1/Lib/D7/TB2DsgnConvertOptions.dcu new file mode 100644 index 0000000..85fe1eb Binary files /dev/null and b/official/2.1.6+2.1.beta1/Lib/D7/TB2DsgnConvertOptions.dcu differ diff --git a/official/2.1.6+2.1.beta1/Lib/D7/TB2DsgnConverter.dcu b/official/2.1.6+2.1.beta1/Lib/D7/TB2DsgnConverter.dcu new file mode 100644 index 0000000..62f72d8 Binary files /dev/null and b/official/2.1.6+2.1.beta1/Lib/D7/TB2DsgnConverter.dcu differ diff --git a/official/2.1.6+2.1.beta1/Lib/D7/TB2DsgnItemEditor.dcu b/official/2.1.6+2.1.beta1/Lib/D7/TB2DsgnItemEditor.dcu new file mode 100644 index 0000000..e4eb18b Binary files /dev/null and b/official/2.1.6+2.1.beta1/Lib/D7/TB2DsgnItemEditor.dcu differ diff --git a/official/2.1.6+2.1.beta1/Lib/D7/TB2DsgnItemEditor.res b/official/2.1.6+2.1.beta1/Lib/D7/TB2DsgnItemEditor.res new file mode 100644 index 0000000..938763e Binary files /dev/null and b/official/2.1.6+2.1.beta1/Lib/D7/TB2DsgnItemEditor.res differ diff --git a/official/2.1.6+2.1.beta1/Lib/D7/TB2ExtItems.dcu b/official/2.1.6+2.1.beta1/Lib/D7/TB2ExtItems.dcu new file mode 100644 index 0000000..9bc1bad Binary files /dev/null and b/official/2.1.6+2.1.beta1/Lib/D7/TB2ExtItems.dcu differ diff --git a/official/2.1.6+2.1.beta1/Lib/D7/TB2Hook.dcu b/official/2.1.6+2.1.beta1/Lib/D7/TB2Hook.dcu new file mode 100644 index 0000000..13bd158 Binary files /dev/null and b/official/2.1.6+2.1.beta1/Lib/D7/TB2Hook.dcu differ diff --git a/official/2.1.6+2.1.beta1/Lib/D7/TB2Item.dcu b/official/2.1.6+2.1.beta1/Lib/D7/TB2Item.dcu new file mode 100644 index 0000000..4dc8e06 Binary files /dev/null and b/official/2.1.6+2.1.beta1/Lib/D7/TB2Item.dcu differ diff --git a/official/2.1.6+2.1.beta1/Lib/D7/TB2MDI.dcu b/official/2.1.6+2.1.beta1/Lib/D7/TB2MDI.dcu new file mode 100644 index 0000000..72611db Binary files /dev/null and b/official/2.1.6+2.1.beta1/Lib/D7/TB2MDI.dcu differ diff --git a/official/2.1.6+2.1.beta1/Lib/D7/TB2MDI.res b/official/2.1.6+2.1.beta1/Lib/D7/TB2MDI.res new file mode 100644 index 0000000..4a62035 Binary files /dev/null and b/official/2.1.6+2.1.beta1/Lib/D7/TB2MDI.res differ diff --git a/official/2.1.6+2.1.beta1/Lib/D7/TB2MRU.dcu b/official/2.1.6+2.1.beta1/Lib/D7/TB2MRU.dcu new file mode 100644 index 0000000..296f026 Binary files /dev/null and b/official/2.1.6+2.1.beta1/Lib/D7/TB2MRU.dcu differ diff --git a/official/2.1.6+2.1.beta1/Lib/D7/TB2Reg.dcu b/official/2.1.6+2.1.beta1/Lib/D7/TB2Reg.dcu new file mode 100644 index 0000000..e57c8be Binary files /dev/null and b/official/2.1.6+2.1.beta1/Lib/D7/TB2Reg.dcu differ diff --git a/official/2.1.6+2.1.beta1/Lib/D7/TB2ResCursors.res b/official/2.1.6+2.1.beta1/Lib/D7/TB2ResCursors.res new file mode 100644 index 0000000..e09ab15 Binary files /dev/null and b/official/2.1.6+2.1.beta1/Lib/D7/TB2ResCursors.res differ diff --git a/official/2.1.6+2.1.beta1/Lib/D7/TB2ToolWindow.dcu b/official/2.1.6+2.1.beta1/Lib/D7/TB2ToolWindow.dcu new file mode 100644 index 0000000..eb56908 Binary files /dev/null and b/official/2.1.6+2.1.beta1/Lib/D7/TB2ToolWindow.dcu differ diff --git a/official/2.1.6+2.1.beta1/Lib/D7/TB2Toolbar.dcu b/official/2.1.6+2.1.beta1/Lib/D7/TB2Toolbar.dcu new file mode 100644 index 0000000..f791781 Binary files /dev/null and b/official/2.1.6+2.1.beta1/Lib/D7/TB2Toolbar.dcu differ diff --git a/official/2.1.6+2.1.beta1/Lib/D7/TB2Version.dcu b/official/2.1.6+2.1.beta1/Lib/D7/TB2Version.dcu new file mode 100644 index 0000000..5c0421e Binary files /dev/null and b/official/2.1.6+2.1.beta1/Lib/D7/TB2Version.dcu differ diff --git a/official/2.1.6+2.1.beta1/Lib/D7/TBX.dcu b/official/2.1.6+2.1.beta1/Lib/D7/TBX.dcu new file mode 100644 index 0000000..287d221 Binary files /dev/null and b/official/2.1.6+2.1.beta1/Lib/D7/TBX.dcu differ diff --git a/official/2.1.6+2.1.beta1/Lib/D7/TBXDefaultTheme.dcu b/official/2.1.6+2.1.beta1/Lib/D7/TBXDefaultTheme.dcu new file mode 100644 index 0000000..52e7a6b Binary files /dev/null and b/official/2.1.6+2.1.beta1/Lib/D7/TBXDefaultTheme.dcu differ diff --git a/official/2.1.6+2.1.beta1/Lib/D7/TBXDkPanels.dcu b/official/2.1.6+2.1.beta1/Lib/D7/TBXDkPanels.dcu new file mode 100644 index 0000000..8462b05 Binary files /dev/null and b/official/2.1.6+2.1.beta1/Lib/D7/TBXDkPanels.dcu differ diff --git a/official/2.1.6+2.1.beta1/Lib/D7/TBXExtItems.dcu b/official/2.1.6+2.1.beta1/Lib/D7/TBXExtItems.dcu new file mode 100644 index 0000000..f3ca108 Binary files /dev/null and b/official/2.1.6+2.1.beta1/Lib/D7/TBXExtItems.dcu differ diff --git a/official/2.1.6+2.1.beta1/Lib/D7/TBXLists.dcu b/official/2.1.6+2.1.beta1/Lib/D7/TBXLists.dcu new file mode 100644 index 0000000..a0df416 Binary files /dev/null and b/official/2.1.6+2.1.beta1/Lib/D7/TBXLists.dcu differ diff --git a/official/2.1.6+2.1.beta1/Lib/D7/TBXMDI.dcu b/official/2.1.6+2.1.beta1/Lib/D7/TBXMDI.dcu new file mode 100644 index 0000000..7b9bfd8 Binary files /dev/null and b/official/2.1.6+2.1.beta1/Lib/D7/TBXMDI.dcu differ diff --git a/official/2.1.6+2.1.beta1/Lib/D7/TBXOffice2003Theme.dcu b/official/2.1.6+2.1.beta1/Lib/D7/TBXOffice2003Theme.dcu new file mode 100644 index 0000000..04f6491 Binary files /dev/null and b/official/2.1.6+2.1.beta1/Lib/D7/TBXOffice2003Theme.dcu differ diff --git a/official/2.1.6+2.1.beta1/Lib/D7/TBXOfficeXPTheme.dcu b/official/2.1.6+2.1.beta1/Lib/D7/TBXOfficeXPTheme.dcu new file mode 100644 index 0000000..677006c Binary files /dev/null and b/official/2.1.6+2.1.beta1/Lib/D7/TBXOfficeXPTheme.dcu differ diff --git a/official/2.1.6+2.1.beta1/Lib/D7/TBXReg.dcu b/official/2.1.6+2.1.beta1/Lib/D7/TBXReg.dcu new file mode 100644 index 0000000..795c97f Binary files /dev/null and b/official/2.1.6+2.1.beta1/Lib/D7/TBXReg.dcu differ diff --git a/official/2.1.6+2.1.beta1/Lib/D7/TBXStatusBars.dcu b/official/2.1.6+2.1.beta1/Lib/D7/TBXStatusBars.dcu new file mode 100644 index 0000000..2726c04 Binary files /dev/null and b/official/2.1.6+2.1.beta1/Lib/D7/TBXStatusBars.dcu differ diff --git a/official/2.1.6+2.1.beta1/Lib/D7/TBXStrEdit.dcu b/official/2.1.6+2.1.beta1/Lib/D7/TBXStrEdit.dcu new file mode 100644 index 0000000..ae7cd12 Binary files /dev/null and b/official/2.1.6+2.1.beta1/Lib/D7/TBXStrEdit.dcu differ diff --git a/official/2.1.6+2.1.beta1/Lib/D7/TBXSwitcher.dcu b/official/2.1.6+2.1.beta1/Lib/D7/TBXSwitcher.dcu new file mode 100644 index 0000000..360330b Binary files /dev/null and b/official/2.1.6+2.1.beta1/Lib/D7/TBXSwitcher.dcu differ diff --git a/official/2.1.6+2.1.beta1/Lib/D7/TBXThemes.dcu b/official/2.1.6+2.1.beta1/Lib/D7/TBXThemes.dcu new file mode 100644 index 0000000..f3c12f0 Binary files /dev/null and b/official/2.1.6+2.1.beta1/Lib/D7/TBXThemes.dcu differ diff --git a/official/2.1.6+2.1.beta1/Lib/D7/TBXToolPals.dcu b/official/2.1.6+2.1.beta1/Lib/D7/TBXToolPals.dcu new file mode 100644 index 0000000..dffc901 Binary files /dev/null and b/official/2.1.6+2.1.beta1/Lib/D7/TBXToolPals.dcu differ diff --git a/official/2.1.6+2.1.beta1/Lib/D7/TBXUtils.dcu b/official/2.1.6+2.1.beta1/Lib/D7/TBXUtils.dcu new file mode 100644 index 0000000..3b0dcff Binary files /dev/null and b/official/2.1.6+2.1.beta1/Lib/D7/TBXUtils.dcu differ diff --git a/official/2.1.6+2.1.beta1/Lib/D7/TBXUxThemes.dcu b/official/2.1.6+2.1.beta1/Lib/D7/TBXUxThemes.dcu new file mode 100644 index 0000000..7e67d8a Binary files /dev/null and b/official/2.1.6+2.1.beta1/Lib/D7/TBXUxThemes.dcu differ diff --git a/official/2.1.6+2.1.beta1/Lib/D7/TBXWhidbeyTheme.dcu b/official/2.1.6+2.1.beta1/Lib/D7/TBXWhidbeyTheme.dcu new file mode 100644 index 0000000..450a77c Binary files /dev/null and b/official/2.1.6+2.1.beta1/Lib/D7/TBXWhidbeyTheme.dcu differ diff --git a/official/2.1.6+2.1.beta1/Lib/D7/TBX_MDI.res b/official/2.1.6+2.1.beta1/Lib/D7/TBX_MDI.res new file mode 100644 index 0000000..eb371ed Binary files /dev/null and b/official/2.1.6+2.1.beta1/Lib/D7/TBX_MDI.res differ diff --git a/official/2.1.6+2.1.beta1/Lib/D7/rmkThemes.dcu b/official/2.1.6+2.1.beta1/Lib/D7/rmkThemes.dcu new file mode 100644 index 0000000..9c449f1 Binary files /dev/null and b/official/2.1.6+2.1.beta1/Lib/D7/rmkThemes.dcu differ diff --git a/official/2.1.6+2.1.beta1/Lib/D7/tb2k_d7.dcu b/official/2.1.6+2.1.beta1/Lib/D7/tb2k_d7.dcu new file mode 100644 index 0000000..a7d8c94 Binary files /dev/null and b/official/2.1.6+2.1.beta1/Lib/D7/tb2k_d7.dcu differ diff --git a/official/2.1.6+2.1.beta1/Lib/D7/tb2kdsgn_d7.dcu b/official/2.1.6+2.1.beta1/Lib/D7/tb2kdsgn_d7.dcu new file mode 100644 index 0000000..3ed9eab Binary files /dev/null and b/official/2.1.6+2.1.beta1/Lib/D7/tb2kdsgn_d7.dcu differ diff --git a/official/2.1.6+2.1.beta1/Lib/D7/tbx_d7.dcu b/official/2.1.6+2.1.beta1/Lib/D7/tbx_d7.dcu new file mode 100644 index 0000000..1b898ee Binary files /dev/null and b/official/2.1.6+2.1.beta1/Lib/D7/tbx_d7.dcu differ diff --git a/official/2.1.6+2.1.beta1/Lib/D7/tbx_glyphs.res b/official/2.1.6+2.1.beta1/Lib/D7/tbx_glyphs.res new file mode 100644 index 0000000..06e6e86 Binary files /dev/null and b/official/2.1.6+2.1.beta1/Lib/D7/tbx_glyphs.res differ diff --git a/official/2.1.6+2.1.beta1/Lib/D7/tbxdsgn_d7.dcu b/official/2.1.6+2.1.beta1/Lib/D7/tbxdsgn_d7.dcu new file mode 100644 index 0000000..2d3bb9a Binary files /dev/null and b/official/2.1.6+2.1.beta1/Lib/D7/tbxdsgn_d7.dcu differ diff --git a/official/2.1.6+2.1.beta1/Packages/tb2k_GroupD10.bdsgroup b/official/2.1.6+2.1.beta1/Packages/tb2k_GroupD10.bdsgroup new file mode 100644 index 0000000..7dbdf85 --- /dev/null +++ b/official/2.1.6+2.1.beta1/Packages/tb2k_GroupD10.bdsgroup @@ -0,0 +1,18 @@ + + + + + + + + + + + D:\Proyectos\Componentes\Tb2k\Packages\tb2k_d10.bdsproj + D:\Proyectos\Componentes\Tb2k\Packages\tb2kdsgn_d10.bdsproj + tb2k_d10.bpl tb2kdsgn_d10.bpl tb2kdsgn_d10.bpl tb2k_d10.bpl + + + + diff --git a/official/2.1.6+2.1.beta1/Packages/tb2k_cb4.bpk b/official/2.1.6+2.1.beta1/Packages/tb2k_cb4.bpk new file mode 100644 index 0000000..c47edd4 --- /dev/null +++ b/official/2.1.6+2.1.beta1/Packages/tb2k_cb4.bpk @@ -0,0 +1,183 @@ +# --------------------------------------------------------------------------- +!if !$d(BCB) +BCB = $(MAKEDIR)\.. +!endif + +# --------------------------------------------------------------------------- +# IDE SECTION +# --------------------------------------------------------------------------- +# The following section of the project makefile is managed by the BCB IDE. +# It is recommended to use the IDE to change any of the values in this +# section. +# --------------------------------------------------------------------------- + +VERSION = BCB.04.04 +# --------------------------------------------------------------------------- +PROJECT = tb2k_cb4.bpl +OBJFILES = ..\Source\TB2Common.obj ..\Source\TB2Consts.obj ..\Source\TB2Dock.obj \ + ..\Source\TB2ExtItems.obj ..\Source\TB2Item.obj ..\Source\TB2Toolbar.obj \ + ..\Source\TB2Version.obj ..\Source\TB2Hook.obj ..\Source\TB2ToolWindow.obj \ + ..\Source\TB2MRU.obj ..\Source\TB2Anim.obj ..\Source\TB2MDI.obj \ + ..\Source\TB2Acc.obj tb2k_cb4.obj +RESFILES = +RESDEPEN = $(RESFILES) +LIBFILES = +LIBRARIES = +SPARELIBS = Vcl40.lib +PACKAGES = vcl40.bpi +DEFFILE = +# --------------------------------------------------------------------------- +PATHCPP = .; +PATHASM = .; +PATHPAS = .;..\Source +PATHRC = .; +DEBUGLIBPATH = $(BCB)\lib\debug +RELEASELIBPATH = $(BCB)\lib\release +USERDEFINES = +SYSDEFINES = _RTLDLL;NO_STRICT;USEPACKAGES +# --------------------------------------------------------------------------- +CFLAG1 = -I..\Source;$(BCB)\include;$(BCB)\include\vcl -Od -Hc -H=$(BCB)\lib\vcl40.csm \ + -w -Ve -r- -a8 -k -y -v -vi- -c -b- -w-par -w-inl -Vx -tWM \ + -D$(SYSDEFINES);$(USERDEFINES) +PFLAGS = -U..\Source;$(BCB)\lib\obj;$(BCB)\lib;$(RELEASELIBPATH) \ + -I..\Source;$(BCB)\include;$(BCB)\include\vcl -$YD -$W -$O- -v -JPHNE -M +RFLAGS = -i..\Source;$(BCB)\include;$(BCB)\include\vcl +AFLAGS = /i$(BCB)\include /i$(BCB)\include\vcl /mx /w2 /zd +LFLAGS = -L..\Source;$(BCB)\lib\obj;$(BCB)\lib;$(RELEASELIBPATH) \ + -D"Toolbar2000 Components (Jordan Russell)" -aa -Tpp -x -Gn -Gl -Gi -v +# --------------------------------------------------------------------------- +ALLOBJ = c0pkg32.obj Memmgr.Lib $(PACKAGES) sysinit.obj $(OBJFILES) +ALLRES = $(RESFILES) +ALLLIB = $(LIBFILES) $(LIBRARIES) import32.lib cp32mti.lib +# --------------------------------------------------------------------------- +!ifdef IDEOPTIONS + +[Version Info] +IncludeVerInfo=0 +AutoIncBuild=0 +MajorVer=1 +MinorVer=0 +Release=0 +Build=0 +Debug=0 +PreRelease=0 +Special=0 +Private=0 +DLL=0 +Locale=1033 +CodePage=1252 + +[Version Info Keys] +CompanyName= +FileDescription= +FileVersion=1.0.0.0 +InternalName= +LegalCopyright= +LegalTrademarks= +OriginalFilename= +ProductName= +ProductVersion=1.0.0.0 +Comments= + +[Debugging] +DebugSourceDirs=$(BCB)\source\vcl + +[Parameters] +RunParams= +HostApplication= +RemoteHost= +RemotePath= +RemoteDebug=0 + +[Compiler] +InMemoryExe=0 +ShowInfoMsgs=0 + +!endif + +# --------------------------------------------------------------------------- +# MAKE SECTION +# --------------------------------------------------------------------------- +# This section of the project file is not used by the BCB IDE. It is for +# the benefit of building from the command-line using the MAKE utility. +# --------------------------------------------------------------------------- + +.autodepend +# --------------------------------------------------------------------------- +!if !$d(BCC32) +BCC32 = bcc32 +!endif + +!if !$d(CPP32) +CPP32 = cpp32 +!endif + +!if !$d(DCC32) +DCC32 = dcc32 +!endif + +!if !$d(TASM32) +TASM32 = tasm32 +!endif + +!if !$d(LINKER) +LINKER = ilink32 +!endif + +!if !$d(BRCC32) +BRCC32 = brcc32 +!endif + +# --------------------------------------------------------------------------- +!if $d(PATHCPP) +.PATH.CPP = $(PATHCPP) +.PATH.C = $(PATHCPP) +!endif + +!if $d(PATHPAS) +.PATH.PAS = $(PATHPAS) +!endif + +!if $d(PATHASM) +.PATH.ASM = $(PATHASM) +!endif + +!if $d(PATHRC) +.PATH.RC = $(PATHRC) +!endif +# --------------------------------------------------------------------------- +$(PROJECT): $(OBJFILES) $(RESDEPEN) $(DEFFILE) + $(BCB)\BIN\$(LINKER) @&&! + $(LFLAGS) + + $(ALLOBJ), + + $(PROJECT),, + + $(ALLLIB), + + $(DEFFILE), + + $(ALLRES) +! +# --------------------------------------------------------------------------- +.pas.hpp: + $(BCB)\BIN\$(DCC32) $(PFLAGS) {$< } + +.pas.obj: + $(BCB)\BIN\$(DCC32) $(PFLAGS) {$< } + +.cpp.obj: + $(BCB)\BIN\$(BCC32) $(CFLAG1) -n$(@D) {$< } + +.c.obj: + $(BCB)\BIN\$(BCC32) $(CFLAG1) -n$(@D) {$< } + +.c.i: + $(BCB)\BIN\$(CPP32) $(CFLAG1) -n. {$< } + +.cpp.i: + $(BCB)\BIN\$(CPP32) $(CFLAG1) -n. {$< } + +.asm.obj: + $(BCB)\BIN\$(TASM32) $(AFLAGS) $<, $@ + +.rc.res: + $(BCB)\BIN\$(BRCC32) $(RFLAGS) -fo$@ $< +# --------------------------------------------------------------------------- + diff --git a/official/2.1.6+2.1.beta1/Packages/tb2k_cb4.cpp b/official/2.1.6+2.1.beta1/Packages/tb2k_cb4.cpp new file mode 100644 index 0000000..65d5caa --- /dev/null +++ b/official/2.1.6+2.1.beta1/Packages/tb2k_cb4.cpp @@ -0,0 +1,29 @@ +// $jrsoftware: tb2k/Packages/tb2k_cb4.cpp,v 1.9 2003/07/04 22:53:21 jr Exp $ +//--------------------------------------------------------------------------- +#include +#pragma hdrstop +USEPACKAGE("vcl40.bpi"); +USEUNIT("..\Source\TB2Common.pas"); +USEUNIT("..\Source\TB2Consts.pas"); +USEUNIT("..\Source\TB2Dock.pas"); +USEUNIT("..\Source\TB2ExtItems.pas"); +USEUNIT("..\Source\TB2Item.pas"); +USEUNIT("..\Source\TB2Toolbar.pas"); +USEUNIT("..\Source\TB2Version.pas"); +USEUNIT("..\Source\TB2Hook.pas"); +USEUNIT("..\Source\TB2ToolWindow.pas"); +USEUNIT("..\Source\TB2MRU.pas"); +USEUNIT("..\Source\TB2Anim.pas"); +USEUNIT("..\Source\TB2MDI.pas"); +USEUNIT("..\Source\TB2Acc.pas"); +//--------------------------------------------------------------------------- +#pragma package(smart_init) +//--------------------------------------------------------------------------- +// Package source. +//--------------------------------------------------------------------------- +int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void*) +{ + return 1; +} +//--------------------------------------------------------------------------- + diff --git a/official/2.1.6+2.1.beta1/Packages/tb2k_cb5.bpk b/official/2.1.6+2.1.beta1/Packages/tb2k_cb5.bpk new file mode 100644 index 0000000..5880bff --- /dev/null +++ b/official/2.1.6+2.1.beta1/Packages/tb2k_cb5.bpk @@ -0,0 +1,96 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +[Version Info] +IncludeVerInfo=0 +AutoIncBuild=0 +MajorVer=1 +MinorVer=0 +Release=0 +Build=0 +Debug=0 +PreRelease=0 +Special=0 +Private=0 +DLL=0 +Locale=1033 +CodePage=1252 + +[Version Info Keys] +CompanyName= +FileDescription= +FileVersion=1.0.0.0 +InternalName= +LegalCopyright= +LegalTrademarks= +OriginalFilename= +ProductName= +ProductVersion=1.0.0.0 +Comments= + +[Debugging] +DebugSourceDirs=$(BCB)\source\vcl + +[Parameters] +RunParams= +HostApplication= +RemoteHost= +RemotePath= +RemoteDebug=0 + +[Compiler] +ShowInfoMsgs=0 +LinkDebugVcl=0 +LinkCGLIB=0 + +[Language] +ActiveLang= +ProjectLang= +RootDir= + + \ No newline at end of file diff --git a/official/2.1.6+2.1.beta1/Packages/tb2k_cb5.cpp b/official/2.1.6+2.1.beta1/Packages/tb2k_cb5.cpp new file mode 100644 index 0000000..33d2c2b --- /dev/null +++ b/official/2.1.6+2.1.beta1/Packages/tb2k_cb5.cpp @@ -0,0 +1,29 @@ +// $jrsoftware: tb2k/Packages/tb2k_cb5.cpp,v 1.9 2003/07/04 22:53:21 jr Exp $ +//--------------------------------------------------------------------------- +#include +#pragma hdrstop +USEPACKAGE("vcl50.bpi"); +USEUNIT("..\Source\TB2Common.pas"); +USEUNIT("..\Source\TB2Consts.pas"); +USEUNIT("..\Source\TB2Dock.pas"); +USEUNIT("..\Source\TB2ExtItems.pas"); +USEUNIT("..\Source\TB2Item.pas"); +USEUNIT("..\Source\TB2Toolbar.pas"); +USEUNIT("..\Source\TB2Version.pas"); +USEUNIT("..\Source\TB2Hook.pas"); +USEUNIT("..\Source\TB2ToolWindow.pas"); +USEUNIT("..\Source\TB2MRU.pas"); +USEUNIT("..\Source\TB2Anim.pas"); +USEUNIT("..\Source\TB2MDI.pas"); +USEUNIT("..\Source\TB2Acc.pas"); +//--------------------------------------------------------------------------- +#pragma package(smart_init) +//--------------------------------------------------------------------------- +// Package source. +//--------------------------------------------------------------------------- +int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void*) +{ + return 1; +} +//--------------------------------------------------------------------------- + diff --git a/official/2.1.6+2.1.beta1/Packages/tb2k_cb6.bpk b/official/2.1.6+2.1.beta1/Packages/tb2k_cb6.bpk new file mode 100644 index 0000000..ac07ad6 --- /dev/null +++ b/official/2.1.6+2.1.beta1/Packages/tb2k_cb6.bpk @@ -0,0 +1,130 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +[Version Info] +IncludeVerInfo=0 +AutoIncBuild=0 +MajorVer=1 +MinorVer=0 +Release=0 +Build=0 +Debug=0 +PreRelease=0 +Special=0 +Private=0 +DLL=0 +Locale=1033 +CodePage=1252 + +[Version Info Keys] +CompanyName= +FileDescription= +FileVersion=1.0.0.0 +InternalName= +LegalCopyright= +LegalTrademarks= +OriginalFilename= +ProductName= +ProductVersion=1.0.0.0 +Comments= + +[Debugging] +DebugSourceDirs=$(BCB)\source\vcl + +[Parameters] +RunParams= +Launcher= +UseLauncher=0 +DebugCWD= +HostApplication= +RemoteHost= +RemotePath= +RemoteLauncher= +RemoteCWD= +RemoteDebug=0 + +[Compiler] +ShowInfoMsgs=0 +LinkDebugVcl=0 +LinkCGLIB=0 + +[Language] +ActiveLang= +ProjectLang= +RootDir= + +[Linker] +LibPrefix= +LibSuffix= +LibVersion= + + \ No newline at end of file diff --git a/official/2.1.6+2.1.beta1/Packages/tb2k_cb6.cpp b/official/2.1.6+2.1.beta1/Packages/tb2k_cb6.cpp new file mode 100644 index 0000000..79fe10f --- /dev/null +++ b/official/2.1.6+2.1.beta1/Packages/tb2k_cb6.cpp @@ -0,0 +1,14 @@ +// $jrsoftware: tb2k/Packages/tb2k_cb6.cpp,v 1.2 2002/11/14 18:07:19 jr Exp $ +//--------------------------------------------------------------------------- +#include +#pragma hdrstop +#pragma package(smart_init) +//--------------------------------------------------------------------------- +// Package source. +//--------------------------------------------------------------------------- +int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void*) +{ + return 1; +} +//--------------------------------------------------------------------------- + diff --git a/official/2.1.6+2.1.beta1/Packages/tb2k_d10.bdsproj b/official/2.1.6+2.1.beta1/Packages/tb2k_d10.bdsproj new file mode 100644 index 0000000..23dbbb1 --- /dev/null +++ b/official/2.1.6+2.1.beta1/Packages/tb2k_d10.bdsproj @@ -0,0 +1,658 @@ + + + + + + + + + + + + tb2k_d10.dpk + + + 7.0 + + + 8 + 0 + 1 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 0 + 1 + 0 + 1 + 1 + 1 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 1 + 0 + 1 + True + True + WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE; + + False + + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + False + False + False + True + True + True + True + True + True + + + + 0 + 0 + False + 1 + False + False + False + 16384 + 1048576 + 1069547520 + Toolbar2000 Components (Jordan Russell) + + + + ..\Lib\D10 + + + + + + + False + + + + + + False + + + True + False + + + + $00000000 + + + + True + False + 1 + 0 + 0 + 0 + False + False + False + False + False + 3082 + 1252 + + + + + 1.0.0.0 + + + + + + 1.0.0.0 + + + + + diff --git a/official/2.1.6+2.1.beta1/Packages/tb2k_d10.dpk b/official/2.1.6+2.1.beta1/Packages/tb2k_d10.dpk new file mode 100644 index 0000000..14fe739 --- /dev/null +++ b/official/2.1.6+2.1.beta1/Packages/tb2k_d10.dpk @@ -0,0 +1,47 @@ +package tb2k_d10; + +{$R *.res} +{$ALIGN 8} +{$ASSERTIONS ON} +{$BOOLEVAL OFF} +{$DEBUGINFO ON} +{$EXTENDEDSYNTAX ON} +{$IMPORTEDDATA ON} +{$IOCHECKS ON} +{$LOCALSYMBOLS ON} +{$LONGSTRINGS ON} +{$OPENSTRINGS ON} +{$OPTIMIZATION ON} +{$OVERFLOWCHECKS OFF} +{$RANGECHECKS OFF} +{$REFERENCEINFO OFF} +{$SAFEDIVIDE OFF} +{$STACKFRAMES OFF} +{$TYPEDADDRESS OFF} +{$VARSTRINGCHECKS ON} +{$WRITEABLECONST ON} +{$MINENUMSIZE 1} +{$IMAGEBASE $3FC00000} +{$DESCRIPTION 'Toolbar2000 Components (Jordan Russell)'} +{$IMPLICITBUILD ON} + +requires + vcl; + +contains + TB2Version in '..\Source\TB2Version.pas', + TB2Toolbar in '..\Source\TB2Toolbar.pas', + TB2Consts in '..\Source\TB2Consts.pas', + TB2Dock in '..\Source\TB2Dock.pas', + TB2ExtItems in '..\Source\TB2ExtItems.pas', + TB2Item in '..\Source\TB2Item.pas', + TB2Common in '..\Source\TB2Common.pas', + TB2Hook in '..\Source\TB2Hook.pas', + TB2ToolWindow in '..\Source\TB2ToolWindow.pas', + TB2MRU in '..\Source\TB2MRU.pas', + TB2Anim in '..\Source\TB2Anim.pas', + TB2MDI in '..\Source\TB2MDI.pas', + TB2Acc in '..\Source\TB2Acc.pas'; + +end. + diff --git a/official/2.1.6+2.1.beta1/Packages/tb2k_d10.res b/official/2.1.6+2.1.beta1/Packages/tb2k_d10.res new file mode 100644 index 0000000..86c94e6 Binary files /dev/null and b/official/2.1.6+2.1.beta1/Packages/tb2k_d10.res differ diff --git a/official/2.1.6+2.1.beta1/Packages/tb2k_d4.dpk b/official/2.1.6+2.1.beta1/Packages/tb2k_d4.dpk new file mode 100644 index 0000000..91b3ccb --- /dev/null +++ b/official/2.1.6+2.1.beta1/Packages/tb2k_d4.dpk @@ -0,0 +1,49 @@ +package tb2k_d4; + +{ $jrsoftware: tb2k/Packages/tb2k_d4.dpk,v 1.10 2003/07/04 22:53:21 jr Exp $ } + +{$R *.RES} +{$ALIGN ON} +{$ASSERTIONS ON} +{$BOOLEVAL OFF} +{$DEBUGINFO ON} +{$EXTENDEDSYNTAX ON} +{$IMPORTEDDATA ON} +{$IOCHECKS ON} +{$LOCALSYMBOLS ON} +{$LONGSTRINGS ON} +{$OPENSTRINGS ON} +{$OPTIMIZATION ON} +{$OVERFLOWCHECKS OFF} +{$RANGECHECKS OFF} +{$REFERENCEINFO OFF} +{$SAFEDIVIDE OFF} +{$STACKFRAMES OFF} +{$TYPEDADDRESS OFF} +{$VARSTRINGCHECKS ON} +{$WRITEABLECONST ON} +{$MINENUMSIZE 1} +{$IMAGEBASE $3FC00000} +{$DESCRIPTION 'Toolbar2000 Components (Jordan Russell)'} +{$IMPLICITBUILD ON} + +requires + vcl40; + +contains + TB2Version in '..\Source\TB2Version.pas', + TB2Toolbar in '..\Source\TB2Toolbar.pas', + TB2Consts in '..\Source\TB2Consts.pas', + TB2Dock in '..\Source\TB2Dock.pas', + TB2ExtItems in '..\Source\TB2ExtItems.pas', + TB2Item in '..\Source\TB2Item.pas', + TB2Common in '..\Source\TB2Common.pas', + TB2Hook in '..\Source\TB2Hook.pas', + TB2ToolWindow in '..\Source\TB2ToolWindow.pas', + TB2MRU in '..\Source\TB2MRU.pas', + TB2Anim in '..\Source\TB2Anim.pas', + TB2MDI in '..\Source\TB2MDI.pas', + TB2Acc in '..\Source\TB2Acc.pas'; + +end. + diff --git a/official/2.1.6+2.1.beta1/Packages/tb2k_d4.res b/official/2.1.6+2.1.beta1/Packages/tb2k_d4.res new file mode 100644 index 0000000..36f26e2 Binary files /dev/null and b/official/2.1.6+2.1.beta1/Packages/tb2k_d4.res differ diff --git a/official/2.1.6+2.1.beta1/Packages/tb2k_d5.dpk b/official/2.1.6+2.1.beta1/Packages/tb2k_d5.dpk new file mode 100644 index 0000000..e2b929d --- /dev/null +++ b/official/2.1.6+2.1.beta1/Packages/tb2k_d5.dpk @@ -0,0 +1,49 @@ +package tb2k_d5; + +{ $jrsoftware: tb2k/Packages/tb2k_d5.dpk,v 1.10 2003/07/04 22:53:21 jr Exp $ } + +{$R *.RES} +{$ALIGN ON} +{$ASSERTIONS ON} +{$BOOLEVAL OFF} +{$DEBUGINFO ON} +{$EXTENDEDSYNTAX ON} +{$IMPORTEDDATA ON} +{$IOCHECKS ON} +{$LOCALSYMBOLS ON} +{$LONGSTRINGS ON} +{$OPENSTRINGS ON} +{$OPTIMIZATION ON} +{$OVERFLOWCHECKS OFF} +{$RANGECHECKS OFF} +{$REFERENCEINFO OFF} +{$SAFEDIVIDE OFF} +{$STACKFRAMES OFF} +{$TYPEDADDRESS OFF} +{$VARSTRINGCHECKS ON} +{$WRITEABLECONST ON} +{$MINENUMSIZE 1} +{$IMAGEBASE $3FC00000} +{$DESCRIPTION 'Toolbar2000 Components (Jordan Russell)'} +{$IMPLICITBUILD ON} + +requires + vcl50; + +contains + TB2Version in '..\Source\TB2Version.pas', + TB2Toolbar in '..\Source\TB2Toolbar.pas', + TB2Consts in '..\Source\TB2Consts.pas', + TB2Dock in '..\Source\TB2Dock.pas', + TB2ExtItems in '..\Source\TB2ExtItems.pas', + TB2Item in '..\Source\TB2Item.pas', + TB2Common in '..\Source\TB2Common.pas', + TB2Hook in '..\Source\TB2Hook.pas', + TB2ToolWindow in '..\Source\TB2ToolWindow.pas', + TB2MRU in '..\Source\TB2MRU.pas', + TB2Anim in '..\Source\TB2Anim.pas', + TB2MDI in '..\Source\TB2MDI.pas', + TB2Acc in '..\Source\TB2Acc.pas'; + +end. + diff --git a/official/2.1.6+2.1.beta1/Packages/tb2k_d5.res b/official/2.1.6+2.1.beta1/Packages/tb2k_d5.res new file mode 100644 index 0000000..36f26e2 Binary files /dev/null and b/official/2.1.6+2.1.beta1/Packages/tb2k_d5.res differ diff --git a/official/2.1.6+2.1.beta1/Packages/tb2k_d6.dpk b/official/2.1.6+2.1.beta1/Packages/tb2k_d6.dpk new file mode 100644 index 0000000..8d6d824 --- /dev/null +++ b/official/2.1.6+2.1.beta1/Packages/tb2k_d6.dpk @@ -0,0 +1,49 @@ +package tb2k_d6; + +{ $jrsoftware: tb2k/Packages/tb2k_d6.dpk,v 1.8 2003/07/04 22:53:21 jr Exp $ } + +{$R *.res} +{$ALIGN 8} +{$ASSERTIONS ON} +{$BOOLEVAL OFF} +{$DEBUGINFO ON} +{$EXTENDEDSYNTAX ON} +{$IMPORTEDDATA ON} +{$IOCHECKS ON} +{$LOCALSYMBOLS ON} +{$LONGSTRINGS ON} +{$OPENSTRINGS ON} +{$OPTIMIZATION ON} +{$OVERFLOWCHECKS OFF} +{$RANGECHECKS OFF} +{$REFERENCEINFO OFF} +{$SAFEDIVIDE OFF} +{$STACKFRAMES OFF} +{$TYPEDADDRESS OFF} +{$VARSTRINGCHECKS ON} +{$WRITEABLECONST ON} +{$MINENUMSIZE 1} +{$IMAGEBASE $3FC00000} +{$DESCRIPTION 'Toolbar2000 Components (Jordan Russell)'} +{$IMPLICITBUILD ON} + +requires + vcl; + +contains + TB2Version in '..\Source\TB2Version.pas', + TB2Toolbar in '..\Source\TB2Toolbar.pas', + TB2Consts in '..\Source\TB2Consts.pas', + TB2Dock in '..\Source\TB2Dock.pas', + TB2ExtItems in '..\Source\TB2ExtItems.pas', + TB2Item in '..\Source\TB2Item.pas', + TB2Common in '..\Source\TB2Common.pas', + TB2Hook in '..\Source\TB2Hook.pas', + TB2ToolWindow in '..\Source\TB2ToolWindow.pas', + TB2MRU in '..\Source\TB2MRU.pas', + TB2Anim in '..\Source\TB2Anim.pas', + TB2MDI in '..\Source\TB2MDI.pas', + TB2Acc in '..\Source\TB2Acc.pas'; + +end. + diff --git a/official/2.1.6+2.1.beta1/Packages/tb2k_d6.res b/official/2.1.6+2.1.beta1/Packages/tb2k_d6.res new file mode 100644 index 0000000..36f26e2 Binary files /dev/null and b/official/2.1.6+2.1.beta1/Packages/tb2k_d6.res differ diff --git a/official/2.1.6+2.1.beta1/Packages/tb2k_d7.cfg b/official/2.1.6+2.1.beta1/Packages/tb2k_d7.cfg new file mode 100644 index 0000000..f733d0f --- /dev/null +++ b/official/2.1.6+2.1.beta1/Packages/tb2k_d7.cfg @@ -0,0 +1,41 @@ +-$A8 +-$B- +-$C+ +-$D+ +-$E- +-$F- +-$G+ +-$H+ +-$I+ +-$J+ +-$K- +-$L+ +-$M- +-$N+ +-$O+ +-$P+ +-$Q- +-$R- +-$S- +-$T- +-$U- +-$V+ +-$W- +-$X+ +-$Y- +-$Z1 +-GD +-cg +-AWinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE; +-H+ +-W+ +-M +-$M16384,1048576 +-K$3FC00000 +-N"..\Lib\D7" +-LE"c:\archivos de programa\borland\delphi7\Projects\Bpl" +-LN"c:\archivos de programa\borland\delphi7\Projects\Bpl" +-Z +-w-UNSAFE_TYPE +-w-UNSAFE_CODE +-w-UNSAFE_CAST diff --git a/official/2.1.6+2.1.beta1/Packages/tb2k_d7.dof b/official/2.1.6+2.1.beta1/Packages/tb2k_d7.dof new file mode 100644 index 0000000..98abb90 --- /dev/null +++ b/official/2.1.6+2.1.beta1/Packages/tb2k_d7.dof @@ -0,0 +1,474 @@ +[FileVersion] +Version=7.0 +[Compiler] +A=8 +B=0 +C=1 +D=1 +E=0 +F=0 +G=1 +H=1 +I=1 +J=1 +K=0 +L=1 +M=0 +N=1 +O=1 +P=1 +Q=0 +R=0 +S=0 +T=0 +U=0 +V=1 +W=0 +X=1 +Y=0 +Z=1 +ShowHints=1 +ShowWarnings=1 +UnitAliases=WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE; +NamespacePrefix= +SymbolDeprecated=1 +SymbolLibrary=1 +SymbolPlatform=1 +UnitLibrary=1 +UnitPlatform=1 +UnitDeprecated=1 +HResultCompat=1 +HidingMember=1 +HiddenVirtual=1 +Garbage=1 +BoundsError=1 +ZeroNilCompat=1 +StringConstTruncated=1 +ForLoopVarVarPar=1 +TypedConstVarPar=1 +AsgToTypedConst=1 +CaseLabelRange=1 +ForVariable=1 +ConstructingAbstract=1 +ComparisonFalse=1 +ComparisonTrue=1 +ComparingSignedUnsigned=1 +CombiningSignedUnsigned=1 +UnsupportedConstruct=1 +FileOpen=1 +FileOpenUnitSrc=1 +BadGlobalSymbol=1 +DuplicateConstructorDestructor=1 +InvalidDirective=1 +PackageNoLink=1 +PackageThreadVar=1 +ImplicitImport=1 +HPPEMITIgnored=1 +NoRetVal=1 +UseBeforeDef=1 +ForLoopVarUndef=1 +UnitNameMismatch=1 +NoCFGFileFound=1 +MessageDirective=1 +ImplicitVariants=1 +UnicodeToLocale=1 +LocaleToUnicode=1 +ImagebaseMultiple=1 +SuspiciousTypecast=1 +PrivatePropAccessor=1 +UnsafeType=0 +UnsafeCode=0 +UnsafeCast=0 +[Linker] +MapFile=3 +OutputObjs=0 +ConsoleApp=1 +DebugInfo=0 +RemoteSymbols=0 +MinStackSize=16384 +MaxStackSize=1048576 +ImageBase=1069547520 +ExeDescription=Toolbar2000 Components (Jordan Russell) +[Directories] +OutputDir= +UnitOutputDir=..\Lib\D7 +PackageDLLOutputDir= +PackageDCPOutputDir= +SearchPath= +Packages=vcl;rtl;vclx;indy;inet;xmlrtl;vclie;inetdbbde;inetdbxpress;dbrtl;dsnap;dsnapcon;vcldb;soaprtl;VclSmp;dbexpress;dbxcds;inetdb;bdertl;vcldbx;webdsnap;websnap;adortl;ibxpress;teeui;teedb;tee;dss;visualclx;visualdbclx;vclactnband;vclshlctrls;dclOfficeXP;CEToolsPkgd7;FR7;FRIBX7;Hydra_Core_D7;Hydra_RO_D7;fqb70;frx7;frxADO7;frxBDE7;frxDB7;frxDBX7;frxe7;frxIBX7;fs7;fsADO7;fsBDE7;fsDB7;fsIBX7;DataAbstract_Core_D7;DataAbstract_IDE_D7;dxComnD7;dxsbD7;dxBarD7;dxBarDBNavD7;dxBarExtDBItemsD7;dxBarExtItemsD7;dxDockingD7;cxEditorsVCLD7;cxLibraryVCLD7;dxThemeD7;cxDataD7;cxExtEditorsVCLD7;cxGridVCLD7;cxPageControlVCLD7;cxSchedulerVCLD7;cxTreeListVCLD7;dxPSCoreD7 +Conditionals= +DebugSourceDirs= +UsePackages=0 +[Parameters] +RunParams= +HostApplication= +Launcher= +UseLauncher=0 +DebugCWD= +[Language] +ActiveLang= +ProjectLang= +RootDir=C:\Archivos de programa\Borland\Delphi7\Bin\ +[Version Info] +IncludeVerInfo=1 +AutoIncBuild=0 +MajorVer=1 +MinorVer=0 +Release=0 +Build=0 +Debug=0 +PreRelease=0 +Special=0 +Private=0 +DLL=0 +Locale=3082 +CodePage=1252 +[Version Info Keys] +CompanyName= +FileDescription= +FileVersion=1.0.0.0 +InternalName= +LegalCopyright= +LegalTrademarks= +OriginalFilename= +ProductName= +ProductVersion=1.0.0.0 +Comments= +[Excluded Packages] +C:\Archivos de programa\Borland\Delphi7\Projects\Bpl\DJclVcl70.bpl=JEDI Code Library VCL package for Delphi 7 +C:\Archivos de programa\Borland\Delphi7\Projects\Bpl\DJcl70.bpl=JEDI Code Library RTL package for Delphi 7 +C:\WINDOWS\system32\fqb70.bpl=FastQueryBuilder 1.01 +C:\Archivos de programa\Borland\Delphi7\Projects\Bpl\dxPSCoreD7.bpl=ExpressPrinting System (core 3.1) by Developer Express Inc. +C:\Archivos de programa\Borland\Delphi7\Projects\Bpl\dxComnD7.bpl=ExpressCommonLibrary by Developer Express Inc. +C:\Archivos de programa\Borland\Delphi7\Projects\Bpl\dxBarDBNavD7.bpl=ExpressBars DBNavigator by Developer Express Inc. +c:\archivos de programa\borland\delphi7\Projects\Bpl\EasyResizeD7.bpl=EasyResize for Delphi 7 +c:\archivos de programa\borland\delphi7\Projects\Bpl\RodaxFrameD7.bpl=Frames Acana (D7) +[HistoryLists\hlUnitAliases] +Count=1 +Item0=WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE; +[HistoryLists\hlUnitOutputDirectory] +Count=1 +Item0=..\Lib\D7 +[HistoryLists\hlBPLOutput] +Count=1 +Item0=..\Lib\D7 +[HistoryLists\hlDCPOutput] +Count=1 +Item0=..\Lib\D7 +[Exception Log] +EurekaLog Version=501 +Activate=1 +Activate Handle=1 +Save Log File=1 +Foreground Tab=0 +Freeze Activate=0 +Freeze Timeout=60 +Freeze Message=The application seems to be frozen. +SMTP From=eurekalog@email.com +SMTP Host= +SMTP Port=25 +SMTP UserID= +SMTP Password= +Append to Log=0 +Show TerminateBtn=1 +TerminateBtn Operation=1 +Errors Number=32 +Errors Terminate=3 +Email Address= +Email Object= +Email Send Options=0 +Output Path= +Encrypt Password= +AutoCloseDialogSecs=0 +WebSendMode=0 +SupportULR= +HTMLLayout Count=15 +HTMLLine0="%3Chtml%3E" +HTMLLine1=" %3Chead%3E" +HTMLLine2=" %3C/head%3E" +HTMLLine3=" %3Cbody TopMargin=10 LeftMargin=10%3E" +HTMLLine4=" %3Ctable width="100%%" border="0"%3E" +HTMLLine5=" %3Ctr%3E" +HTMLLine6=" %3Ctd nowrap%3E" +HTMLLine7=" %3Cfont face="Lucida Console, Courier" size="2"%3E" +HTMLLine8=" %3C%%HTML_TAG%%%3E" +HTMLLine9=" %3C/font%3E" +HTMLLine10=" %3C/td%3E" +HTMLLine11=" %3C/tr%3E" +HTMLLine12=" %3C/table%3E" +HTMLLine13=" %3C/body%3E" +HTMLLine14="%3C/html%3E" +AutoCrashOperation=1 +AutoCrashNumber=10 +AutoCrashMinutes=1 +WebURL= +WebUserID= +WebPassword= +WebPort=0 +AttachedFiles= +Count=0 +EMail Message Line Count=0 +loNoDuplicateErrors=0 +loAppendReproduceText=0 +loDeleteLogAtVersionChange=0 +loAddComputerNameInLogFileName=0 +loSaveModulesSection=1 +loSaveCPUSection=1 +soAppStartDate=1 +soAppName=1 +soAppVersionNumber=1 +soAppParameters=1 +soAppCompilationDate=1 +soExcDate=1 +soExcAddress=1 +soExcModule=1 +soExcType=1 +soExcMessage=1 +soActCtlsFormClass=1 +soActCtlsFormText=1 +soActCtlsControlClass=1 +soActCtlsControlText=1 +soCmpName=1 +soCmpUser=1 +soCmpTotalMemory=1 +soCmpFreeMemory=1 +soCmpTotalDisk=1 +soCmpFreeDisk=1 +soCmpSysUpTime=1 +soCmpProcessor=1 +soCmpDisplayMode=1 +soOSType=1 +soOSBuildN=1 +soOSUpdate=1 +soOSLanguage=1 +soNetIP=1 +soNetSubmask=1 +soNetGateway=1 +soNetDNS1=1 +soNetDNS2=1 +soNetDHCP=1 +sndShowSendDialog=1 +sndShowSuccessFailureMsg=0 +sndSendEntireLog=0 +sndSendXMLLogCopy=0 +sndSendScreenshot=1 +sndUseOnlyActiveWindow=0 +sndSendLastHTMLPage=1 +sndSendInSeparatedThread=0 +sndAddDateInFileName=0 +sndCompressAllFiles=0 +edoShowExceptionDialog=1 +edoSendEmailChecked=1 +edoAttachScreenshotChecked=1 +edoShowCopyToClipOption=1 +edoShowDetailsButton=1 +edoShowInDetailedMode=0 +edoShowInTopMostMode=0 +edoUseEurekaLogLookAndFeel=0 +csoShowDLLs=1 +csoShowBPLs=1 +csoShowBorlandThreads=1 +csoShowWindowsThreads=1 +csoShowProcedureOffset=0 +boActivateCrashDetection=0 +boPauseBorlandThreads=0 +boDoNotPauseMainThread=0 +boPauseWindowsThreads=0 +boUseMainModuleOptions=1 +boCopyLogInCaseOfError=1 +boSaveCompressedCopyInCaseOfError=0 +Count mtInformationMsgCaption=1 +mtInformationMsgCaption0="Information." +Count mtQuestionMsgCaption=1 +mtQuestionMsgCaption0="Question." +Count mtDialog_Caption=1 +mtDialog_Caption0="Error." +Count mtDialog_ErrorMsgCaption=2 +mtDialog_ErrorMsgCaption0="An error has occurred during program execution." +mtDialog_ErrorMsgCaption1="Please read the following information for further details." +Count mtDialog_GeneralCaption=1 +mtDialog_GeneralCaption0="General" +Count mtDialog_GeneralHeader=1 +mtDialog_GeneralHeader0="General Information" +Count mtDialog_CallStackCaption=1 +mtDialog_CallStackCaption0="Call Stack" +Count mtDialog_CallStackHeader=1 +mtDialog_CallStackHeader0="Call Stack Information" +Count mtDialog_ModulesCaption=1 +mtDialog_ModulesCaption0="Modules" +Count mtDialog_ModulesHeader=1 +mtDialog_ModulesHeader0="Modules Information" +Count mtDialog_CPUCaption=1 +mtDialog_CPUCaption0="CPU" +Count mtDialog_CPUHeader=1 +mtDialog_CPUHeader0="CPU Information" +Count mtDialog_CustomDataCaption=1 +mtDialog_CustomDataCaption0="Other" +Count mtDialog_CustomDataHeader=1 +mtDialog_CustomDataHeader0="Other Information" +Count mtDialog_OKButtonCaption=1 +mtDialog_OKButtonCaption0="&OK" +Count mtDialog_TerminateButtonCaption=1 +mtDialog_TerminateButtonCaption0="&Terminate" +Count mtDialog_RestartButtonCaption=1 +mtDialog_RestartButtonCaption0="&Restart" +Count mtDialog_DetailsButtonCaption=1 +mtDialog_DetailsButtonCaption0="&Details" +Count mtDialog_SendMessage=1 +mtDialog_SendMessage0="&Send this error via Internet" +Count mtDialog_ScreenshotMessage=1 +mtDialog_ScreenshotMessage0="&Attach a Screenshot image" +Count mtDialog_CopyMessage=1 +mtDialog_CopyMessage0="&Copy to Clipboard" +Count mtDialog_SupportMessage=1 +mtDialog_SupportMessage0="Go to the Support Page" +Count mtLog_AppHeader=1 +mtLog_AppHeader0="Application" +Count mtLog_AppStartDate=1 +mtLog_AppStartDate0="Start Date" +Count mtLog_AppName=1 +mtLog_AppName0="Name/Description" +Count mtLog_AppVersionNumber=1 +mtLog_AppVersionNumber0="Version Number" +Count mtLog_AppParameters=1 +mtLog_AppParameters0="Parameters" +Count mtLog_AppCompilationDate=1 +mtLog_AppCompilationDate0="Compilation Date" +Count mtLog_ExcHeader=1 +mtLog_ExcHeader0="Exception" +Count mtLog_ExcDate=1 +mtLog_ExcDate0="Date" +Count mtLog_ExcAddress=1 +mtLog_ExcAddress0="Address" +Count mtLog_ExcModule=1 +mtLog_ExcModule0="Module" +Count mtLog_ExcType=1 +mtLog_ExcType0="Type" +Count mtLog_ExcMessage=1 +mtLog_ExcMessage0="Message" +Count mtLog_ActCtrlsHeader=1 +mtLog_ActCtrlsHeader0="Active Controls" +Count mtLog_ActCtrlsFormClass=1 +mtLog_ActCtrlsFormClass0="Form Class" +Count mtLog_ActCtrlsFormText=1 +mtLog_ActCtrlsFormText0="Form Text" +Count mtLog_ActCtrlsControlClass=1 +mtLog_ActCtrlsControlClass0="Control Class" +Count mtLog_ActCtrlsControlText=1 +mtLog_ActCtrlsControlText0="Control Text" +Count mtLog_CmpHeader=1 +mtLog_CmpHeader0="Computer" +Count mtLog_CmpName=1 +mtLog_CmpName0="Name" +Count mtLog_CmpUser=1 +mtLog_CmpUser0="User" +Count mtLog_CmpTotalMemory=1 +mtLog_CmpTotalMemory0="Total Memory" +Count mtLog_CmpFreeMemory=1 +mtLog_CmpFreeMemory0="Free Memory" +Count mtLog_CmpTotalDisk=1 +mtLog_CmpTotalDisk0="Total Disk" +Count mtLog_CmpFreeDisk=1 +mtLog_CmpFreeDisk0="Free Disk" +Count mtLog_CmpSystemUpTime=1 +mtLog_CmpSystemUpTime0="System Up Time" +Count mtLog_CmpProcessor=1 +mtLog_CmpProcessor0="Processor" +Count mtLog_CmpDisplayMode=1 +mtLog_CmpDisplayMode0="Display Mode" +Count mtLog_OSHeader=1 +mtLog_OSHeader0="Operating System" +Count mtLog_OSType=1 +mtLog_OSType0="Type" +Count mtLog_OSBuildN=1 +mtLog_OSBuildN0="Build #" +Count mtLog_OSUpdate=1 +mtLog_OSUpdate0="Update" +Count mtLog_OSLanguage=1 +mtLog_OSLanguage0="Language" +Count mtLog_NetHeader=1 +mtLog_NetHeader0="Network" +Count mtLog_NetIP=1 +mtLog_NetIP0="IP Address" +Count mtLog_NetSubmask=1 +mtLog_NetSubmask0="Submask" +Count mtLog_NetGateway=1 +mtLog_NetGateway0="Gateway" +Count mtLog_NetDNS1=1 +mtLog_NetDNS10="DNS 1" +Count mtLog_NetDNS2=1 +mtLog_NetDNS20="DNS 2" +Count mtLog_NetDHCP=1 +mtLog_NetDHCP0="DHCP" +Count mtLog_CustInfoHeader=1 +mtLog_CustInfoHeader0="Custom Information" +Count mtCallStack_Address=1 +mtCallStack_Address0="Address" +Count mtCallStack_Name=1 +mtCallStack_Name0="Module" +Count mtCallStack_Unit=1 +mtCallStack_Unit0="Unit" +Count mtCallStack_Class=1 +mtCallStack_Class0="Class" +Count mtCallStack_Procedure=1 +mtCallStack_Procedure0="Procedure/Method" +Count mtCallStack_Line=1 +mtCallStack_Line0="Line" +Count mtCallStack_MainThread=1 +mtCallStack_MainThread0="Main" +Count mtCallStack_ExceptionThread=1 +mtCallStack_ExceptionThread0="Exception Thread" +Count mtCallStack_RunningThread=1 +mtCallStack_RunningThread0="Running Thread" +Count mtCallStack_CallingThread=1 +mtCallStack_CallingThread0="Calling Thread" +Count mtCallStack_ThreadID=1 +mtCallStack_ThreadID0="ID" +Count mtCallStack_ThreadPriority=1 +mtCallStack_ThreadPriority0="Priority" +Count mtCallStack_ThreadClass=1 +mtCallStack_ThreadClass0="Class" +Count mtSendDialog_Caption=1 +mtSendDialog_Caption0="Send." +Count mtSendDialog_Message=1 +mtSendDialog_Message0="Message" +Count mtSendDialog_Resolving=1 +mtSendDialog_Resolving0="Resolving DNS..." +Count mtSendDialog_Connecting=1 +mtSendDialog_Connecting0="Connecting with server..." +Count mtSendDialog_Connected=1 +mtSendDialog_Connected0="Connected with server." +Count mtSendDialog_Sending=1 +mtSendDialog_Sending0="Sending message..." +Count mtReproduceDialog_Caption=1 +mtReproduceDialog_Caption0="Request" +Count mtReproduceDialog_Request=1 +mtReproduceDialog_Request0="Please describe the steps to reproduce the error:" +Count mtReproduceDialog_OKButtonCaption=1 +mtReproduceDialog_OKButtonCaption0="&OK" +Count mtModules_Handle=1 +mtModules_Handle0="Handle" +Count mtModules_Name=1 +mtModules_Name0="Name" +Count mtModules_Description=1 +mtModules_Description0="Description" +Count mtModules_Version=1 +mtModules_Version0="Version" +Count mtModules_Size=1 +mtModules_Size0="Size" +Count mtModules_LastModified=1 +mtModules_LastModified0="Modified" +Count mtModules_Path=1 +mtModules_Path0="Path" +Count mtCPU_Registers=1 +mtCPU_Registers0="Registers" +Count mtCPU_Stack=1 +mtCPU_Stack0="Stack" +Count mtCPU_MemoryDump=1 +mtCPU_MemoryDump0="Memory Dump" +Count mtSend_SuccessMsg=1 +mtSend_SuccessMsg0="The message was sent successfully." +Count mtSend_FailureMsg=1 +mtSend_FailureMsg0="Sorry, sending the message didn't work." + + diff --git a/official/2.1.6+2.1.beta1/Packages/tb2k_d7.dpk b/official/2.1.6+2.1.beta1/Packages/tb2k_d7.dpk new file mode 100644 index 0000000..2bcceff --- /dev/null +++ b/official/2.1.6+2.1.beta1/Packages/tb2k_d7.dpk @@ -0,0 +1,47 @@ +package tb2k_d7; + +{$R *.res} +{$ALIGN 8} +{$ASSERTIONS ON} +{$BOOLEVAL OFF} +{$DEBUGINFO ON} +{$EXTENDEDSYNTAX ON} +{$IMPORTEDDATA ON} +{$IOCHECKS ON} +{$LOCALSYMBOLS ON} +{$LONGSTRINGS ON} +{$OPENSTRINGS ON} +{$OPTIMIZATION ON} +{$OVERFLOWCHECKS OFF} +{$RANGECHECKS OFF} +{$REFERENCEINFO OFF} +{$SAFEDIVIDE OFF} +{$STACKFRAMES OFF} +{$TYPEDADDRESS OFF} +{$VARSTRINGCHECKS ON} +{$WRITEABLECONST ON} +{$MINENUMSIZE 1} +{$IMAGEBASE $3FC00000} +{$DESCRIPTION 'Toolbar2000 Components (Jordan Russell)'} +{$IMPLICITBUILD OFF} + +requires + vcl; + +contains + TB2Version in '..\Source\TB2Version.pas', + TB2Toolbar in '..\Source\TB2Toolbar.pas', + TB2Consts in '..\Source\TB2Consts.pas', + TB2Dock in '..\Source\TB2Dock.pas', + TB2ExtItems in '..\Source\TB2ExtItems.pas', + TB2Item in '..\Source\TB2Item.pas', + TB2Common in '..\Source\TB2Common.pas', + TB2Hook in '..\Source\TB2Hook.pas', + TB2ToolWindow in '..\Source\TB2ToolWindow.pas', + TB2MRU in '..\Source\TB2MRU.pas', + TB2Anim in '..\Source\TB2Anim.pas', + TB2MDI in '..\Source\TB2MDI.pas', + TB2Acc in '..\Source\TB2Acc.pas'; + +end. + diff --git a/official/2.1.6+2.1.beta1/Packages/tb2k_d7.drc b/official/2.1.6+2.1.beta1/Packages/tb2k_d7.drc new file mode 100644 index 0000000..c13138c --- /dev/null +++ b/official/2.1.6+2.1.beta1/Packages/tb2k_d7.drc @@ -0,0 +1,34 @@ +/* VER150 + Generated by the Borland Delphi Pascal Compiler + because -GD or --drc was supplied to the compiler. + + This file contains compiler-generated resources that + were bound to the executable. + If this file is empty, then no compiler-generated + resources were bound to the produced executable. +*/ + +#define TB2Consts_STBToolbarIndexOutOfBounds 65520 +#define TB2Consts_STBToolbarItemReinserted 65521 +#define TB2Consts_STBViewerNotFound 65522 +#define TB2Consts_STBChevronItemMoreButtonsHint 65523 +#define TB2Consts_STBMRUListItemDefCaption 65524 +#define TB2Consts_STBMDIWindowItemDefCaption 65525 +#define TB2Consts_STBDockParentNotAllowed 65526 +#define TB2Consts_STBDockCannotChangePosition 65527 +#define TB2Consts_STBToolwinNameNotSet 65528 +#define TB2Consts_STBToolwinDockedToNameNotSet 65529 +STRINGTABLE +BEGIN + TB2Consts_STBToolbarIndexOutOfBounds, "Toolbar item index out of range" + TB2Consts_STBToolbarItemReinserted, "Toolbar item already inserted" + TB2Consts_STBViewerNotFound, "An item viewer associated the specified item could not be found" + TB2Consts_STBChevronItemMoreButtonsHint, "More Buttons|" + TB2Consts_STBMRUListItemDefCaption, "(MRU List)" + TB2Consts_STBMDIWindowItemDefCaption, "(Window List)" + TB2Consts_STBDockParentNotAllowed, "A TTBDock control cannot be placed inside a tool window or another TTBDock" + TB2Consts_STBDockCannotChangePosition, "Cannot change Position of a TTBDock if it already contains controls" + TB2Consts_STBToolwinNameNotSet, "Cannot save dockable window's position because Name property is not set" + TB2Consts_STBToolwinDockedToNameNotSet, "Cannot save dockable window's position because DockedTo's Name property not set" +END + diff --git a/official/2.1.6+2.1.beta1/Packages/tb2k_d7.res b/official/2.1.6+2.1.beta1/Packages/tb2k_d7.res new file mode 100644 index 0000000..ec5f233 Binary files /dev/null and b/official/2.1.6+2.1.beta1/Packages/tb2k_d7.res differ diff --git a/official/2.1.6+2.1.beta1/Packages/tb2k_d9.dpk b/official/2.1.6+2.1.beta1/Packages/tb2k_d9.dpk new file mode 100644 index 0000000..bd72e12 --- /dev/null +++ b/official/2.1.6+2.1.beta1/Packages/tb2k_d9.dpk @@ -0,0 +1,49 @@ +package tb2k_d9; + +{ $jrsoftware: tb2k/Packages/tb2k_d9.dpk,v 1.1 2004/12/05 23:26:27 jr Exp $ } + +{$R *.res} +{$ALIGN 8} +{$ASSERTIONS ON} +{$BOOLEVAL OFF} +{$DEBUGINFO ON} +{$EXTENDEDSYNTAX ON} +{$IMPORTEDDATA ON} +{$IOCHECKS ON} +{$LOCALSYMBOLS ON} +{$LONGSTRINGS ON} +{$OPENSTRINGS ON} +{$OPTIMIZATION ON} +{$OVERFLOWCHECKS OFF} +{$RANGECHECKS OFF} +{$REFERENCEINFO OFF} +{$SAFEDIVIDE OFF} +{$STACKFRAMES OFF} +{$TYPEDADDRESS OFF} +{$VARSTRINGCHECKS ON} +{$WRITEABLECONST ON} +{$MINENUMSIZE 1} +{$IMAGEBASE $3FC00000} +{$DESCRIPTION 'Toolbar2000 Components (Jordan Russell)'} +{$IMPLICITBUILD ON} + +requires + vcl; + +contains + TB2Version in '..\Source\TB2Version.pas', + TB2Toolbar in '..\Source\TB2Toolbar.pas', + TB2Consts in '..\Source\TB2Consts.pas', + TB2Dock in '..\Source\TB2Dock.pas', + TB2ExtItems in '..\Source\TB2ExtItems.pas', + TB2Item in '..\Source\TB2Item.pas', + TB2Common in '..\Source\TB2Common.pas', + TB2Hook in '..\Source\TB2Hook.pas', + TB2ToolWindow in '..\Source\TB2ToolWindow.pas', + TB2MRU in '..\Source\TB2MRU.pas', + TB2Anim in '..\Source\TB2Anim.pas', + TB2MDI in '..\Source\TB2MDI.pas', + TB2Acc in '..\Source\TB2Acc.pas'; + +end. + diff --git a/official/2.1.6+2.1.beta1/Packages/tb2k_d9.res b/official/2.1.6+2.1.beta1/Packages/tb2k_d9.res new file mode 100644 index 0000000..36f26e2 Binary files /dev/null and b/official/2.1.6+2.1.beta1/Packages/tb2k_d9.res differ diff --git a/official/2.1.6+2.1.beta1/Packages/tb2kdsgn_cb4.bpk b/official/2.1.6+2.1.beta1/Packages/tb2kdsgn_cb4.bpk new file mode 100644 index 0000000..09ac25a --- /dev/null +++ b/official/2.1.6+2.1.beta1/Packages/tb2kdsgn_cb4.bpk @@ -0,0 +1,183 @@ +# --------------------------------------------------------------------------- +!if !$d(BCB) +BCB = $(MAKEDIR)\.. +!endif + +# --------------------------------------------------------------------------- +# IDE SECTION +# --------------------------------------------------------------------------- +# The following section of the project makefile is managed by the BCB IDE. +# It is recommended to use the IDE to change any of the values in this +# section. +# --------------------------------------------------------------------------- + +VERSION = BCB.04.04 +# --------------------------------------------------------------------------- +PROJECT = tb2kdsgn_cb4.bpl +OBJFILES = ..\Source\TB2DsgnConverter.obj \ + ..\Source\TB2DsgnItemEditor.obj ..\Source\TB2Reg.obj \ + ..\Source\TB2DsgnConvertOptions.obj tb2kdsgn_cb4.obj +RESFILES = ..\Source\TB2Reg.dcr +RESDEPEN = $(RESFILES) ..\Source\TB2DsgnConverter.dfm ..\Source\TB2DsgnItemEditor.dfm \ + ..\Source\TB2DsgnConvertOptions.dfm +LIBFILES = +LIBRARIES = +SPARELIBS = Vcl40.lib +PACKAGES = vcl40.bpi dclstd40.bpi tb2k_cb4.bpi +DEFFILE = +# --------------------------------------------------------------------------- +PATHCPP = .; +PATHASM = .; +PATHPAS = .;..\Source +PATHRC = .; +DEBUGLIBPATH = $(BCB)\lib\debug +RELEASELIBPATH = $(BCB)\lib\release +USERDEFINES = +SYSDEFINES = _RTLDLL;NO_STRICT;USEPACKAGES +# --------------------------------------------------------------------------- +CFLAG1 = -I..\Source;$(BCB)\include;$(BCB)\include\vcl -Od -Hc -H=$(BCB)\lib\vcl40.csm \ + -w -Ve -r- -a8 -k -y -v -vi- -c -b- -w-par -w-inl -Vx -tWM \ + -D$(SYSDEFINES);$(USERDEFINES) +PFLAGS = -U..\Source;$(BCB)\Projects\Lib;$(BCB)\lib\obj;$(BCB)\lib;$(RELEASELIBPATH) \ + -I..\Source;$(BCB)\include;$(BCB)\include\vcl -$YD -$W -$O- -v -JPHNE -M \ + -LUdclstd40 +RFLAGS = -i..\Source;$(BCB)\include;$(BCB)\include\vcl +AFLAGS = /i$(BCB)\include /i$(BCB)\include\vcl /mx /w2 /zd +LFLAGS = -L..\Source;$(BCB)\Projects\Lib;$(BCB)\lib\obj;$(BCB)\lib;$(RELEASELIBPATH) \ + -D"Toolbar2000 Design Package (Jordan Russell)" -aa -Tpp -Gpd -x -Gn -Gl -Gi -v +# --------------------------------------------------------------------------- +ALLOBJ = c0pkg32.obj Memmgr.Lib $(PACKAGES) sysinit.obj $(OBJFILES) +ALLRES = $(RESFILES) +ALLLIB = $(LIBFILES) $(LIBRARIES) import32.lib cp32mti.lib +# --------------------------------------------------------------------------- +!ifdef IDEOPTIONS + +[Version Info] +IncludeVerInfo=0 +AutoIncBuild=0 +MajorVer=1 +MinorVer=0 +Release=0 +Build=0 +Debug=0 +PreRelease=0 +Special=0 +Private=0 +DLL=0 +Locale=1033 +CodePage=1252 + +[Version Info Keys] +CompanyName= +FileDescription= +FileVersion=1.0.0.0 +InternalName= +LegalCopyright= +LegalTrademarks= +OriginalFilename= +ProductName= +ProductVersion=1.0.0.0 +Comments= + +[Debugging] +DebugSourceDirs=$(BCB)\source\vcl + +[Parameters] +RunParams= +HostApplication= +RemoteHost= +RemotePath= +RemoteDebug=0 + +[Compiler] +InMemoryExe=0 +ShowInfoMsgs=0 + +!endif + +# --------------------------------------------------------------------------- +# MAKE SECTION +# --------------------------------------------------------------------------- +# This section of the project file is not used by the BCB IDE. It is for +# the benefit of building from the command-line using the MAKE utility. +# --------------------------------------------------------------------------- + +.autodepend +# --------------------------------------------------------------------------- +!if !$d(BCC32) +BCC32 = bcc32 +!endif + +!if !$d(CPP32) +CPP32 = cpp32 +!endif + +!if !$d(DCC32) +DCC32 = dcc32 +!endif + +!if !$d(TASM32) +TASM32 = tasm32 +!endif + +!if !$d(LINKER) +LINKER = ilink32 +!endif + +!if !$d(BRCC32) +BRCC32 = brcc32 +!endif + +# --------------------------------------------------------------------------- +!if $d(PATHCPP) +.PATH.CPP = $(PATHCPP) +.PATH.C = $(PATHCPP) +!endif + +!if $d(PATHPAS) +.PATH.PAS = $(PATHPAS) +!endif + +!if $d(PATHASM) +.PATH.ASM = $(PATHASM) +!endif + +!if $d(PATHRC) +.PATH.RC = $(PATHRC) +!endif +# --------------------------------------------------------------------------- +$(PROJECT): $(OBJFILES) $(RESDEPEN) $(DEFFILE) + $(BCB)\BIN\$(LINKER) @&&! + $(LFLAGS) + + $(ALLOBJ), + + $(PROJECT),, + + $(ALLLIB), + + $(DEFFILE), + + $(ALLRES) +! +# --------------------------------------------------------------------------- +.pas.hpp: + $(BCB)\BIN\$(DCC32) $(PFLAGS) {$< } + +.pas.obj: + $(BCB)\BIN\$(DCC32) $(PFLAGS) {$< } + +.cpp.obj: + $(BCB)\BIN\$(BCC32) $(CFLAG1) -n$(@D) {$< } + +.c.obj: + $(BCB)\BIN\$(BCC32) $(CFLAG1) -n$(@D) {$< } + +.c.i: + $(BCB)\BIN\$(CPP32) $(CFLAG1) -n. {$< } + +.cpp.i: + $(BCB)\BIN\$(CPP32) $(CFLAG1) -n. {$< } + +.asm.obj: + $(BCB)\BIN\$(TASM32) $(AFLAGS) $<, $@ + +.rc.res: + $(BCB)\BIN\$(BRCC32) $(RFLAGS) -fo$@ $< +# --------------------------------------------------------------------------- + diff --git a/official/2.1.6+2.1.beta1/Packages/tb2kdsgn_cb4.cpp b/official/2.1.6+2.1.beta1/Packages/tb2kdsgn_cb4.cpp new file mode 100644 index 0000000..08b9d21 --- /dev/null +++ b/official/2.1.6+2.1.beta1/Packages/tb2kdsgn_cb4.cpp @@ -0,0 +1,23 @@ +// $jrsoftware: tb2k/Packages/tb2kdsgn_cb4.cpp,v 1.4 2002/11/14 18:15:59 jr Exp $ +//--------------------------------------------------------------------------- +#include +#pragma hdrstop +USEPACKAGE("vcl40.bpi"); +USEFORMNS("..\Source\TB2DsgnConverter.pas", Tb2dsgnconverter, TBConverterForm); +USEFORMNS("..\Source\TB2DsgnItemEditor.pas", Tb2dsgnitemeditor, TBItemEditForm); +USEFORMNS("..\Source\TB2DsgnConvertOptions.pas", Tb2dsgnconvertoptions, TBConvertOptionsForm); +USEUNIT("..\Source\TB2Reg.pas"); +USERES("..\Source\TB2Reg.dcr"); +USEPACKAGE("dclstd40.bpi"); +USEPACKAGE("tb2k_cb4.bpi"); +//--------------------------------------------------------------------------- +#pragma package(smart_init) +//--------------------------------------------------------------------------- +// Package source. +//--------------------------------------------------------------------------- +int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void*) +{ + return 1; +} +//--------------------------------------------------------------------------- + diff --git a/official/2.1.6+2.1.beta1/Packages/tb2kdsgn_cb5.bpk b/official/2.1.6+2.1.beta1/Packages/tb2kdsgn_cb5.bpk new file mode 100644 index 0000000..2d09d57 --- /dev/null +++ b/official/2.1.6+2.1.beta1/Packages/tb2kdsgn_cb5.bpk @@ -0,0 +1,96 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +[Version Info] +IncludeVerInfo=0 +AutoIncBuild=0 +MajorVer=1 +MinorVer=0 +Release=0 +Build=0 +Debug=0 +PreRelease=0 +Special=0 +Private=0 +DLL=0 +Locale=1033 +CodePage=1252 + +[Version Info Keys] +CompanyName= +FileDescription= +FileVersion=1.0.0.0 +InternalName= +LegalCopyright= +LegalTrademarks= +OriginalFilename= +ProductName= +ProductVersion=1.0.0.0 +Comments= + +[Debugging] +DebugSourceDirs=$(BCB)\source\vcl + +[Parameters] +RunParams= +HostApplication= +RemoteHost= +RemotePath= +RemoteDebug=0 + +[Compiler] +ShowInfoMsgs=0 +LinkDebugVcl=0 +LinkCGLIB=0 + +[Language] +ActiveLang= +ProjectLang= +RootDir= + + \ No newline at end of file diff --git a/official/2.1.6+2.1.beta1/Packages/tb2kdsgn_cb5.cpp b/official/2.1.6+2.1.beta1/Packages/tb2kdsgn_cb5.cpp new file mode 100644 index 0000000..ba1bbd8 --- /dev/null +++ b/official/2.1.6+2.1.beta1/Packages/tb2kdsgn_cb5.cpp @@ -0,0 +1,23 @@ +// $jrsoftware: tb2k/Packages/tb2kdsgn_cb5.cpp,v 1.4 2002/11/14 18:15:59 jr Exp $ +//--------------------------------------------------------------------------- +#include +#pragma hdrstop +USEPACKAGE("vcl50.bpi"); +USEFORMNS("..\Source\TB2DsgnConverter.pas", Tb2dsgnconverter, TBConverterForm); +USEFORMNS("..\Source\TB2DsgnItemEditor.pas", Tb2dsgnitemeditor, TBItemEditForm); +USEFORMNS("..\Source\TB2DsgnConvertOptions.pas", Tb2dsgnconvertoptions, TBConvertOptionsForm); +USEUNIT("..\Source\TB2Reg.pas"); +USERES("..\Source\TB2Reg.dcr"); +USEPACKAGE("dclstd50.bpi"); +USEPACKAGE("tb2k_cb5.bpi"); +//--------------------------------------------------------------------------- +#pragma package(smart_init) +//--------------------------------------------------------------------------- +// Package source. +//--------------------------------------------------------------------------- +int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void*) +{ + return 1; +} +//--------------------------------------------------------------------------- + diff --git a/official/2.1.6+2.1.beta1/Packages/tb2kdsgn_cb6.bpk b/official/2.1.6+2.1.beta1/Packages/tb2kdsgn_cb6.bpk new file mode 100644 index 0000000..70b36a4 --- /dev/null +++ b/official/2.1.6+2.1.beta1/Packages/tb2kdsgn_cb6.bpk @@ -0,0 +1,125 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +[Version Info] +IncludeVerInfo=0 +AutoIncBuild=0 +MajorVer=1 +MinorVer=0 +Release=0 +Build=0 +Debug=0 +PreRelease=0 +Special=0 +Private=0 +DLL=0 +Locale=1033 +CodePage=1252 + +[Version Info Keys] +CompanyName= +FileDescription= +FileVersion=1.0.0.0 +InternalName= +LegalCopyright= +LegalTrademarks= +OriginalFilename= +ProductName= +ProductVersion=1.0.0.0 +Comments= + +[Debugging] +DebugSourceDirs=$(BCB)\source\vcl + +[Parameters] +RunParams= +Launcher= +UseLauncher=0 +DebugCWD= +HostApplication= +RemoteHost= +RemotePath= +RemoteLauncher= +RemoteCWD= +RemoteDebug=0 + +[Compiler] +ShowInfoMsgs=0 +LinkDebugVcl=0 +LinkCGLIB=0 + +[Language] +ActiveLang= +ProjectLang= +RootDir= + +[Linker] +LibPrefix= +LibSuffix= +LibVersion= + + \ No newline at end of file diff --git a/official/2.1.6+2.1.beta1/Packages/tb2kdsgn_cb6.cpp b/official/2.1.6+2.1.beta1/Packages/tb2kdsgn_cb6.cpp new file mode 100644 index 0000000..6fabfa6 --- /dev/null +++ b/official/2.1.6+2.1.beta1/Packages/tb2kdsgn_cb6.cpp @@ -0,0 +1,18 @@ +// $jrsoftware: tb2k/Packages/tb2kdsgn_cb6.cpp,v 1.2 2002/11/14 18:07:19 jr Exp $ +//--------------------------------------------------------------------------- +#include +#pragma hdrstop +USEFORMNS("..\Source\TB2DsgnConverter.pas", Tb2dsgnconverter, TBConverterForm); +USEFORMNS("..\Source\TB2DsgnItemEditor.pas", Tb2dsgnitemeditor, TBItemEditForm); +USEFORMNS("..\Source\TB2DsgnConvertOptions.pas", Tb2dsgnconvertoptions, TBConvertOptionsForm); +//--------------------------------------------------------------------------- +#pragma package(smart_init) +//--------------------------------------------------------------------------- +// Package source. +//--------------------------------------------------------------------------- +int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void*) +{ + return 1; +} +//--------------------------------------------------------------------------- + diff --git a/official/2.1.6+2.1.beta1/Packages/tb2kdsgn_d10.bdsproj b/official/2.1.6+2.1.beta1/Packages/tb2kdsgn_d10.bdsproj new file mode 100644 index 0000000..c5ebc23 --- /dev/null +++ b/official/2.1.6+2.1.beta1/Packages/tb2kdsgn_d10.bdsproj @@ -0,0 +1,175 @@ + + + + + + + + + + + + tb2kdsgn_d10.dpk + + + 7.0 + + + 8 + 0 + 1 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 0 + 1 + 0 + 1 + 1 + 1 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 1 + 0 + 1 + True + True + WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE; + + False + + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + False + False + False + True + True + True + True + True + True + + + + 0 + 0 + False + 1 + False + False + False + 16384 + 1048576 + 1065353216 + Toolbar2000 Design Package (Jordan Russell) + + + + ..\Lib\D10 + + + ..\Lib\D10 + + + + False + + + + + + False + + + True + False + + + + $00000000 + + + + True + False + 1 + 0 + 0 + 0 + False + False + False + False + False + 3082 + 1252 + + + + + 1.0.0.0 + + + + + + 1.0.0.0 + + + + diff --git a/official/2.1.6+2.1.beta1/Packages/tb2kdsgn_d10.dpk b/official/2.1.6+2.1.beta1/Packages/tb2kdsgn_d10.dpk new file mode 100644 index 0000000..941784b --- /dev/null +++ b/official/2.1.6+2.1.beta1/Packages/tb2kdsgn_d10.dpk @@ -0,0 +1,42 @@ +package tb2kdsgn_d10; + +{$R *.res} +{$R '..\Source\TB2Reg.dcr'} +{$ALIGN 8} +{$ASSERTIONS ON} +{$BOOLEVAL OFF} +{$DEBUGINFO ON} +{$EXTENDEDSYNTAX ON} +{$IMPORTEDDATA ON} +{$IOCHECKS ON} +{$LOCALSYMBOLS ON} +{$LONGSTRINGS ON} +{$OPENSTRINGS ON} +{$OPTIMIZATION ON} +{$OVERFLOWCHECKS OFF} +{$RANGECHECKS OFF} +{$REFERENCEINFO OFF} +{$SAFEDIVIDE OFF} +{$STACKFRAMES OFF} +{$TYPEDADDRESS OFF} +{$VARSTRINGCHECKS ON} +{$WRITEABLECONST ON} +{$MINENUMSIZE 1} +{$IMAGEBASE $3F800000} +{$DESCRIPTION 'Toolbar2000 Design Package (Jordan Russell)'} +{$DESIGNONLY} +{$IMPLICITBUILD ON} + +requires + vcl, + dclstd, + tb2k_d10; + +contains + TB2Reg in '..\Source\TB2Reg.pas', + TB2DsgnItemEditor in '..\Source\TB2DsgnItemEditor.pas' {TBToolbarEditForm}, + TB2DsgnConverter in '..\Source\TB2DsgnConverter.pas' {TBConverterForm}, + TB2DsgnConvertOptions in '..\Source\TB2DsgnConvertOptions.pas' {TBConvertOptionsForm}; + +end. + diff --git a/official/2.1.6+2.1.beta1/Packages/tb2kdsgn_d10.res b/official/2.1.6+2.1.beta1/Packages/tb2kdsgn_d10.res new file mode 100644 index 0000000..86c94e6 Binary files /dev/null and b/official/2.1.6+2.1.beta1/Packages/tb2kdsgn_d10.res differ diff --git a/official/2.1.6+2.1.beta1/Packages/tb2kdsgn_d4.dpk b/official/2.1.6+2.1.beta1/Packages/tb2kdsgn_d4.dpk new file mode 100644 index 0000000..7ab3a30 --- /dev/null +++ b/official/2.1.6+2.1.beta1/Packages/tb2kdsgn_d4.dpk @@ -0,0 +1,44 @@ +package tb2kdsgn_d4; + +{ $jrsoftware: tb2k/Packages/tb2kdsgn_d4.dpk,v 1.5 2003/04/17 19:40:26 jr Exp $ } + +{$R *.RES} +{$R '..\Source\TB2Reg.dcr'} +{$ALIGN ON} +{$ASSERTIONS ON} +{$BOOLEVAL OFF} +{$DEBUGINFO ON} +{$EXTENDEDSYNTAX ON} +{$IMPORTEDDATA ON} +{$IOCHECKS ON} +{$LOCALSYMBOLS ON} +{$LONGSTRINGS ON} +{$OPENSTRINGS ON} +{$OPTIMIZATION ON} +{$OVERFLOWCHECKS OFF} +{$RANGECHECKS OFF} +{$REFERENCEINFO OFF} +{$SAFEDIVIDE OFF} +{$STACKFRAMES OFF} +{$TYPEDADDRESS OFF} +{$VARSTRINGCHECKS ON} +{$WRITEABLECONST ON} +{$MINENUMSIZE 1} +{$IMAGEBASE $3F800000} +{$DESCRIPTION 'Toolbar2000 Design Package (Jordan Russell)'} +{$DESIGNONLY} +{$IMPLICITBUILD ON} + +requires + vcl40, + dclstd40, + tb2k_d4; + +contains + TB2Reg in '..\Source\TB2Reg.pas', + TB2DsgnItemEditor in '..\Source\TB2DsgnItemEditor.pas' {TBToolbarEditForm}, + TB2DsgnConverter in '..\Source\TB2DsgnConverter.pas' {TBConverterForm}, + TB2DsgnConvertOptions in '..\Source\TB2DsgnConvertOptions.pas' {TBConvertOptionsForm}; + +end. + diff --git a/official/2.1.6+2.1.beta1/Packages/tb2kdsgn_d4.res b/official/2.1.6+2.1.beta1/Packages/tb2kdsgn_d4.res new file mode 100644 index 0000000..36f26e2 Binary files /dev/null and b/official/2.1.6+2.1.beta1/Packages/tb2kdsgn_d4.res differ diff --git a/official/2.1.6+2.1.beta1/Packages/tb2kdsgn_d5.dpk b/official/2.1.6+2.1.beta1/Packages/tb2kdsgn_d5.dpk new file mode 100644 index 0000000..360fa4a --- /dev/null +++ b/official/2.1.6+2.1.beta1/Packages/tb2kdsgn_d5.dpk @@ -0,0 +1,44 @@ +package tb2kdsgn_d5; + +{ $jrsoftware: tb2k/Packages/tb2kdsgn_d5.dpk,v 1.5 2003/04/17 19:40:26 jr Exp $ } + +{$R *.RES} +{$R '..\Source\TB2Reg.dcr'} +{$ALIGN ON} +{$ASSERTIONS ON} +{$BOOLEVAL OFF} +{$DEBUGINFO ON} +{$EXTENDEDSYNTAX ON} +{$IMPORTEDDATA ON} +{$IOCHECKS ON} +{$LOCALSYMBOLS ON} +{$LONGSTRINGS ON} +{$OPENSTRINGS ON} +{$OPTIMIZATION ON} +{$OVERFLOWCHECKS OFF} +{$RANGECHECKS OFF} +{$REFERENCEINFO OFF} +{$SAFEDIVIDE OFF} +{$STACKFRAMES OFF} +{$TYPEDADDRESS OFF} +{$VARSTRINGCHECKS ON} +{$WRITEABLECONST ON} +{$MINENUMSIZE 1} +{$IMAGEBASE $3F800000} +{$DESCRIPTION 'Toolbar2000 Design Package (Jordan Russell)'} +{$DESIGNONLY} +{$IMPLICITBUILD ON} + +requires + vcl50, + dclstd50, + tb2k_d5; + +contains + TB2Reg in '..\Source\TB2Reg.pas', + TB2DsgnItemEditor in '..\Source\TB2DsgnItemEditor.pas' {TBToolbarEditForm}, + TB2DsgnConverter in '..\Source\TB2DsgnConverter.pas' {TBConverterForm}, + TB2DsgnConvertOptions in '..\Source\TB2DsgnConvertOptions.pas' {TBConvertOptionsForm}; + +end. + diff --git a/official/2.1.6+2.1.beta1/Packages/tb2kdsgn_d5.res b/official/2.1.6+2.1.beta1/Packages/tb2kdsgn_d5.res new file mode 100644 index 0000000..36f26e2 Binary files /dev/null and b/official/2.1.6+2.1.beta1/Packages/tb2kdsgn_d5.res differ diff --git a/official/2.1.6+2.1.beta1/Packages/tb2kdsgn_d6.dpk b/official/2.1.6+2.1.beta1/Packages/tb2kdsgn_d6.dpk new file mode 100644 index 0000000..ef8533d --- /dev/null +++ b/official/2.1.6+2.1.beta1/Packages/tb2kdsgn_d6.dpk @@ -0,0 +1,44 @@ +package tb2kdsgn_d6; + +{ $jrsoftware: tb2k/Packages/tb2kdsgn_d6.dpk,v 1.5 2003/04/17 19:40:26 jr Exp $ } + +{$R *.res} +{$R '..\Source\TB2Reg.dcr'} +{$ALIGN 8} +{$ASSERTIONS ON} +{$BOOLEVAL OFF} +{$DEBUGINFO ON} +{$EXTENDEDSYNTAX ON} +{$IMPORTEDDATA ON} +{$IOCHECKS ON} +{$LOCALSYMBOLS ON} +{$LONGSTRINGS ON} +{$OPENSTRINGS ON} +{$OPTIMIZATION ON} +{$OVERFLOWCHECKS OFF} +{$RANGECHECKS OFF} +{$REFERENCEINFO OFF} +{$SAFEDIVIDE OFF} +{$STACKFRAMES OFF} +{$TYPEDADDRESS OFF} +{$VARSTRINGCHECKS ON} +{$WRITEABLECONST ON} +{$MINENUMSIZE 1} +{$IMAGEBASE $3F800000} +{$DESCRIPTION 'Toolbar2000 Design Package (Jordan Russell)'} +{$DESIGNONLY} +{$IMPLICITBUILD ON} + +requires + vcl, + dclstd, + tb2k_d6; + +contains + TB2Reg in '..\Source\TB2Reg.pas', + TB2DsgnItemEditor in '..\Source\TB2DsgnItemEditor.pas' {TBToolbarEditForm}, + TB2DsgnConverter in '..\Source\TB2DsgnConverter.pas' {TBConverterForm}, + TB2DsgnConvertOptions in '..\Source\TB2DsgnConvertOptions.pas' {TBConvertOptionsForm}; + +end. + diff --git a/official/2.1.6+2.1.beta1/Packages/tb2kdsgn_d6.res b/official/2.1.6+2.1.beta1/Packages/tb2kdsgn_d6.res new file mode 100644 index 0000000..36f26e2 Binary files /dev/null and b/official/2.1.6+2.1.beta1/Packages/tb2kdsgn_d6.res differ diff --git a/official/2.1.6+2.1.beta1/Packages/tb2kdsgn_d7.cfg b/official/2.1.6+2.1.beta1/Packages/tb2kdsgn_d7.cfg new file mode 100644 index 0000000..4d68122 --- /dev/null +++ b/official/2.1.6+2.1.beta1/Packages/tb2kdsgn_d7.cfg @@ -0,0 +1,40 @@ +-$A8 +-$B- +-$C+ +-$D+ +-$E- +-$F- +-$G+ +-$H+ +-$I+ +-$J+ +-$K- +-$L+ +-$M- +-$N+ +-$O+ +-$P+ +-$Q- +-$R- +-$S- +-$T- +-$U- +-$V+ +-$W- +-$X+ +-$Y- +-$Z1 +-GD +-cg +-AWinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE; +-H+ +-W+ +-M +-$M16384,1048576 +-K$3F800000 +-N"..\Lib\D7" +-LE"c:\archivos de programa\borland\delphi7\Projects\Bpl" +-LN"c:\archivos de programa\borland\delphi7\Projects\Bpl" +-w-UNSAFE_TYPE +-w-UNSAFE_CODE +-w-UNSAFE_CAST diff --git a/official/2.1.6+2.1.beta1/Packages/tb2kdsgn_d7.dof b/official/2.1.6+2.1.beta1/Packages/tb2kdsgn_d7.dof new file mode 100644 index 0000000..c932eca --- /dev/null +++ b/official/2.1.6+2.1.beta1/Packages/tb2kdsgn_d7.dof @@ -0,0 +1,473 @@ +[FileVersion] +Version=7.0 +[Compiler] +A=8 +B=0 +C=1 +D=1 +E=0 +F=0 +G=1 +H=1 +I=1 +J=1 +K=0 +L=1 +M=0 +N=1 +O=1 +P=1 +Q=0 +R=0 +S=0 +T=0 +U=0 +V=1 +W=0 +X=1 +Y=0 +Z=1 +ShowHints=1 +ShowWarnings=1 +UnitAliases=WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE; +NamespacePrefix= +SymbolDeprecated=1 +SymbolLibrary=1 +SymbolPlatform=1 +UnitLibrary=1 +UnitPlatform=1 +UnitDeprecated=1 +HResultCompat=1 +HidingMember=1 +HiddenVirtual=1 +Garbage=1 +BoundsError=1 +ZeroNilCompat=1 +StringConstTruncated=1 +ForLoopVarVarPar=1 +TypedConstVarPar=1 +AsgToTypedConst=1 +CaseLabelRange=1 +ForVariable=1 +ConstructingAbstract=1 +ComparisonFalse=1 +ComparisonTrue=1 +ComparingSignedUnsigned=1 +CombiningSignedUnsigned=1 +UnsupportedConstruct=1 +FileOpen=1 +FileOpenUnitSrc=1 +BadGlobalSymbol=1 +DuplicateConstructorDestructor=1 +InvalidDirective=1 +PackageNoLink=1 +PackageThreadVar=1 +ImplicitImport=1 +HPPEMITIgnored=1 +NoRetVal=1 +UseBeforeDef=1 +ForLoopVarUndef=1 +UnitNameMismatch=1 +NoCFGFileFound=1 +MessageDirective=1 +ImplicitVariants=1 +UnicodeToLocale=1 +LocaleToUnicode=1 +ImagebaseMultiple=1 +SuspiciousTypecast=1 +PrivatePropAccessor=1 +UnsafeType=0 +UnsafeCode=0 +UnsafeCast=0 +[Linker] +MapFile=3 +OutputObjs=0 +ConsoleApp=1 +DebugInfo=0 +RemoteSymbols=0 +MinStackSize=16384 +MaxStackSize=1048576 +ImageBase=1065353216 +ExeDescription=Toolbar2000 Design Package (Jordan Russell) +[Directories] +OutputDir= +UnitOutputDir=..\Lib\D7 +PackageDLLOutputDir= +PackageDCPOutputDir= +SearchPath= +Packages=vcl;rtl;vclx;indy;inet;xmlrtl;vclie;inetdbbde;inetdbxpress;dbrtl;dsnap;dsnapcon;vcldb;soaprtl;VclSmp;dbexpress;dbxcds;inetdb;bdertl;vcldbx;webdsnap;websnap;adortl;ibxpress;teeui;teedb;tee;dss;visualclx;visualdbclx;vclactnband;vclshlctrls;dclOfficeXP;CEToolsPkgd7;FR7;FRIBX7;Hydra_Core_D7;Hydra_RO_D7;fqb70;frx7;frxADO7;frxBDE7;frxDB7;frxDBX7;frxe7;frxIBX7;fs7;fsADO7;fsBDE7;fsDB7;fsIBX7;DataAbstract_Core_D7;DataAbstract_IDE_D7;dxComnD7;dxsbD7;dxBarD7;dxBarDBNavD7;dxBarExtDBItemsD7;dxBarExtItemsD7;dxDockingD7;cxEditorsVCLD7;cxLibraryVCLD7;dxThemeD7;cxDataD7;cxExtEditorsVCLD7;cxGridVCLD7;cxPageControlVCLD7;cxSchedulerVCLD7;cxTreeListVCLD7;dxPSCoreD7 +Conditionals= +DebugSourceDirs= +UsePackages=0 +[Parameters] +RunParams= +HostApplication= +Launcher= +UseLauncher=0 +DebugCWD= +[Language] +ActiveLang= +ProjectLang= +RootDir=C:\Archivos de programa\Borland\Delphi7\Bin\ +[Version Info] +IncludeVerInfo=1 +AutoIncBuild=0 +MajorVer=1 +MinorVer=0 +Release=0 +Build=0 +Debug=0 +PreRelease=0 +Special=0 +Private=0 +DLL=0 +Locale=3082 +CodePage=1252 +[Version Info Keys] +CompanyName= +FileDescription= +FileVersion=1.0.0.0 +InternalName= +LegalCopyright= +LegalTrademarks= +OriginalFilename= +ProductName= +ProductVersion=1.0.0.0 +Comments= +[Excluded Packages] +C:\Archivos de programa\Borland\Delphi7\Projects\Bpl\DJclVcl70.bpl=JEDI Code Library VCL package for Delphi 7 +C:\Archivos de programa\Borland\Delphi7\Projects\Bpl\DJcl70.bpl=JEDI Code Library RTL package for Delphi 7 +C:\WINDOWS\system32\fqb70.bpl=FastQueryBuilder 1.01 +C:\Archivos de programa\Borland\Delphi7\Projects\Bpl\dxPSCoreD7.bpl=ExpressPrinting System (core 3.1) by Developer Express Inc. +C:\Archivos de programa\Borland\Delphi7\Projects\Bpl\dxComnD7.bpl=ExpressCommonLibrary by Developer Express Inc. +c:\archivos de programa\borland\delphi7\Projects\Bpl\EasyResizeD7.bpl=EasyResize for Delphi 7 +c:\archivos de programa\borland\delphi7\Projects\Bpl\RodaxFrameD7.bpl=Frames Acana (D7) +[HistoryLists\hlUnitAliases] +Count=1 +Item0=WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE; +[HistoryLists\hlUnitOutputDirectory] +Count=1 +Item0=..\Lib\D7 +[HistoryLists\hlBPLOutput] +Count=1 +Item0=..\Lib\D7 +[HistoryLists\hlDCPOutput] +Count=1 +Item0=..\Lib\D7 +[Exception Log] +EurekaLog Version=501 +Activate=1 +Activate Handle=1 +Save Log File=1 +Foreground Tab=0 +Freeze Activate=0 +Freeze Timeout=60 +Freeze Message=The application seems to be frozen. +SMTP From=eurekalog@email.com +SMTP Host= +SMTP Port=25 +SMTP UserID= +SMTP Password= +Append to Log=0 +Show TerminateBtn=1 +TerminateBtn Operation=1 +Errors Number=32 +Errors Terminate=3 +Email Address= +Email Object= +Email Send Options=0 +Output Path= +Encrypt Password= +AutoCloseDialogSecs=0 +WebSendMode=0 +SupportULR= +HTMLLayout Count=15 +HTMLLine0="%3Chtml%3E" +HTMLLine1=" %3Chead%3E" +HTMLLine2=" %3C/head%3E" +HTMLLine3=" %3Cbody TopMargin=10 LeftMargin=10%3E" +HTMLLine4=" %3Ctable width="100%%" border="0"%3E" +HTMLLine5=" %3Ctr%3E" +HTMLLine6=" %3Ctd nowrap%3E" +HTMLLine7=" %3Cfont face="Lucida Console, Courier" size="2"%3E" +HTMLLine8=" %3C%%HTML_TAG%%%3E" +HTMLLine9=" %3C/font%3E" +HTMLLine10=" %3C/td%3E" +HTMLLine11=" %3C/tr%3E" +HTMLLine12=" %3C/table%3E" +HTMLLine13=" %3C/body%3E" +HTMLLine14="%3C/html%3E" +AutoCrashOperation=1 +AutoCrashNumber=10 +AutoCrashMinutes=1 +WebURL= +WebUserID= +WebPassword= +WebPort=0 +AttachedFiles= +Count=0 +EMail Message Line Count=0 +loNoDuplicateErrors=0 +loAppendReproduceText=0 +loDeleteLogAtVersionChange=0 +loAddComputerNameInLogFileName=0 +loSaveModulesSection=1 +loSaveCPUSection=1 +soAppStartDate=1 +soAppName=1 +soAppVersionNumber=1 +soAppParameters=1 +soAppCompilationDate=1 +soExcDate=1 +soExcAddress=1 +soExcModule=1 +soExcType=1 +soExcMessage=1 +soActCtlsFormClass=1 +soActCtlsFormText=1 +soActCtlsControlClass=1 +soActCtlsControlText=1 +soCmpName=1 +soCmpUser=1 +soCmpTotalMemory=1 +soCmpFreeMemory=1 +soCmpTotalDisk=1 +soCmpFreeDisk=1 +soCmpSysUpTime=1 +soCmpProcessor=1 +soCmpDisplayMode=1 +soOSType=1 +soOSBuildN=1 +soOSUpdate=1 +soOSLanguage=1 +soNetIP=1 +soNetSubmask=1 +soNetGateway=1 +soNetDNS1=1 +soNetDNS2=1 +soNetDHCP=1 +sndShowSendDialog=1 +sndShowSuccessFailureMsg=0 +sndSendEntireLog=0 +sndSendXMLLogCopy=0 +sndSendScreenshot=1 +sndUseOnlyActiveWindow=0 +sndSendLastHTMLPage=1 +sndSendInSeparatedThread=0 +sndAddDateInFileName=0 +sndCompressAllFiles=0 +edoShowExceptionDialog=1 +edoSendEmailChecked=1 +edoAttachScreenshotChecked=1 +edoShowCopyToClipOption=1 +edoShowDetailsButton=1 +edoShowInDetailedMode=0 +edoShowInTopMostMode=0 +edoUseEurekaLogLookAndFeel=0 +csoShowDLLs=1 +csoShowBPLs=1 +csoShowBorlandThreads=1 +csoShowWindowsThreads=1 +csoShowProcedureOffset=0 +boActivateCrashDetection=0 +boPauseBorlandThreads=0 +boDoNotPauseMainThread=0 +boPauseWindowsThreads=0 +boUseMainModuleOptions=1 +boCopyLogInCaseOfError=1 +boSaveCompressedCopyInCaseOfError=0 +Count mtInformationMsgCaption=1 +mtInformationMsgCaption0="Information." +Count mtQuestionMsgCaption=1 +mtQuestionMsgCaption0="Question." +Count mtDialog_Caption=1 +mtDialog_Caption0="Error." +Count mtDialog_ErrorMsgCaption=2 +mtDialog_ErrorMsgCaption0="An error has occurred during program execution." +mtDialog_ErrorMsgCaption1="Please read the following information for further details." +Count mtDialog_GeneralCaption=1 +mtDialog_GeneralCaption0="General" +Count mtDialog_GeneralHeader=1 +mtDialog_GeneralHeader0="General Information" +Count mtDialog_CallStackCaption=1 +mtDialog_CallStackCaption0="Call Stack" +Count mtDialog_CallStackHeader=1 +mtDialog_CallStackHeader0="Call Stack Information" +Count mtDialog_ModulesCaption=1 +mtDialog_ModulesCaption0="Modules" +Count mtDialog_ModulesHeader=1 +mtDialog_ModulesHeader0="Modules Information" +Count mtDialog_CPUCaption=1 +mtDialog_CPUCaption0="CPU" +Count mtDialog_CPUHeader=1 +mtDialog_CPUHeader0="CPU Information" +Count mtDialog_CustomDataCaption=1 +mtDialog_CustomDataCaption0="Other" +Count mtDialog_CustomDataHeader=1 +mtDialog_CustomDataHeader0="Other Information" +Count mtDialog_OKButtonCaption=1 +mtDialog_OKButtonCaption0="&OK" +Count mtDialog_TerminateButtonCaption=1 +mtDialog_TerminateButtonCaption0="&Terminate" +Count mtDialog_RestartButtonCaption=1 +mtDialog_RestartButtonCaption0="&Restart" +Count mtDialog_DetailsButtonCaption=1 +mtDialog_DetailsButtonCaption0="&Details" +Count mtDialog_SendMessage=1 +mtDialog_SendMessage0="&Send this error via Internet" +Count mtDialog_ScreenshotMessage=1 +mtDialog_ScreenshotMessage0="&Attach a Screenshot image" +Count mtDialog_CopyMessage=1 +mtDialog_CopyMessage0="&Copy to Clipboard" +Count mtDialog_SupportMessage=1 +mtDialog_SupportMessage0="Go to the Support Page" +Count mtLog_AppHeader=1 +mtLog_AppHeader0="Application" +Count mtLog_AppStartDate=1 +mtLog_AppStartDate0="Start Date" +Count mtLog_AppName=1 +mtLog_AppName0="Name/Description" +Count mtLog_AppVersionNumber=1 +mtLog_AppVersionNumber0="Version Number" +Count mtLog_AppParameters=1 +mtLog_AppParameters0="Parameters" +Count mtLog_AppCompilationDate=1 +mtLog_AppCompilationDate0="Compilation Date" +Count mtLog_ExcHeader=1 +mtLog_ExcHeader0="Exception" +Count mtLog_ExcDate=1 +mtLog_ExcDate0="Date" +Count mtLog_ExcAddress=1 +mtLog_ExcAddress0="Address" +Count mtLog_ExcModule=1 +mtLog_ExcModule0="Module" +Count mtLog_ExcType=1 +mtLog_ExcType0="Type" +Count mtLog_ExcMessage=1 +mtLog_ExcMessage0="Message" +Count mtLog_ActCtrlsHeader=1 +mtLog_ActCtrlsHeader0="Active Controls" +Count mtLog_ActCtrlsFormClass=1 +mtLog_ActCtrlsFormClass0="Form Class" +Count mtLog_ActCtrlsFormText=1 +mtLog_ActCtrlsFormText0="Form Text" +Count mtLog_ActCtrlsControlClass=1 +mtLog_ActCtrlsControlClass0="Control Class" +Count mtLog_ActCtrlsControlText=1 +mtLog_ActCtrlsControlText0="Control Text" +Count mtLog_CmpHeader=1 +mtLog_CmpHeader0="Computer" +Count mtLog_CmpName=1 +mtLog_CmpName0="Name" +Count mtLog_CmpUser=1 +mtLog_CmpUser0="User" +Count mtLog_CmpTotalMemory=1 +mtLog_CmpTotalMemory0="Total Memory" +Count mtLog_CmpFreeMemory=1 +mtLog_CmpFreeMemory0="Free Memory" +Count mtLog_CmpTotalDisk=1 +mtLog_CmpTotalDisk0="Total Disk" +Count mtLog_CmpFreeDisk=1 +mtLog_CmpFreeDisk0="Free Disk" +Count mtLog_CmpSystemUpTime=1 +mtLog_CmpSystemUpTime0="System Up Time" +Count mtLog_CmpProcessor=1 +mtLog_CmpProcessor0="Processor" +Count mtLog_CmpDisplayMode=1 +mtLog_CmpDisplayMode0="Display Mode" +Count mtLog_OSHeader=1 +mtLog_OSHeader0="Operating System" +Count mtLog_OSType=1 +mtLog_OSType0="Type" +Count mtLog_OSBuildN=1 +mtLog_OSBuildN0="Build #" +Count mtLog_OSUpdate=1 +mtLog_OSUpdate0="Update" +Count mtLog_OSLanguage=1 +mtLog_OSLanguage0="Language" +Count mtLog_NetHeader=1 +mtLog_NetHeader0="Network" +Count mtLog_NetIP=1 +mtLog_NetIP0="IP Address" +Count mtLog_NetSubmask=1 +mtLog_NetSubmask0="Submask" +Count mtLog_NetGateway=1 +mtLog_NetGateway0="Gateway" +Count mtLog_NetDNS1=1 +mtLog_NetDNS10="DNS 1" +Count mtLog_NetDNS2=1 +mtLog_NetDNS20="DNS 2" +Count mtLog_NetDHCP=1 +mtLog_NetDHCP0="DHCP" +Count mtLog_CustInfoHeader=1 +mtLog_CustInfoHeader0="Custom Information" +Count mtCallStack_Address=1 +mtCallStack_Address0="Address" +Count mtCallStack_Name=1 +mtCallStack_Name0="Module" +Count mtCallStack_Unit=1 +mtCallStack_Unit0="Unit" +Count mtCallStack_Class=1 +mtCallStack_Class0="Class" +Count mtCallStack_Procedure=1 +mtCallStack_Procedure0="Procedure/Method" +Count mtCallStack_Line=1 +mtCallStack_Line0="Line" +Count mtCallStack_MainThread=1 +mtCallStack_MainThread0="Main" +Count mtCallStack_ExceptionThread=1 +mtCallStack_ExceptionThread0="Exception Thread" +Count mtCallStack_RunningThread=1 +mtCallStack_RunningThread0="Running Thread" +Count mtCallStack_CallingThread=1 +mtCallStack_CallingThread0="Calling Thread" +Count mtCallStack_ThreadID=1 +mtCallStack_ThreadID0="ID" +Count mtCallStack_ThreadPriority=1 +mtCallStack_ThreadPriority0="Priority" +Count mtCallStack_ThreadClass=1 +mtCallStack_ThreadClass0="Class" +Count mtSendDialog_Caption=1 +mtSendDialog_Caption0="Send." +Count mtSendDialog_Message=1 +mtSendDialog_Message0="Message" +Count mtSendDialog_Resolving=1 +mtSendDialog_Resolving0="Resolving DNS..." +Count mtSendDialog_Connecting=1 +mtSendDialog_Connecting0="Connecting with server..." +Count mtSendDialog_Connected=1 +mtSendDialog_Connected0="Connected with server." +Count mtSendDialog_Sending=1 +mtSendDialog_Sending0="Sending message..." +Count mtReproduceDialog_Caption=1 +mtReproduceDialog_Caption0="Request" +Count mtReproduceDialog_Request=1 +mtReproduceDialog_Request0="Please describe the steps to reproduce the error:" +Count mtReproduceDialog_OKButtonCaption=1 +mtReproduceDialog_OKButtonCaption0="&OK" +Count mtModules_Handle=1 +mtModules_Handle0="Handle" +Count mtModules_Name=1 +mtModules_Name0="Name" +Count mtModules_Description=1 +mtModules_Description0="Description" +Count mtModules_Version=1 +mtModules_Version0="Version" +Count mtModules_Size=1 +mtModules_Size0="Size" +Count mtModules_LastModified=1 +mtModules_LastModified0="Modified" +Count mtModules_Path=1 +mtModules_Path0="Path" +Count mtCPU_Registers=1 +mtCPU_Registers0="Registers" +Count mtCPU_Stack=1 +mtCPU_Stack0="Stack" +Count mtCPU_MemoryDump=1 +mtCPU_MemoryDump0="Memory Dump" +Count mtSend_SuccessMsg=1 +mtSend_SuccessMsg0="The message was sent successfully." +Count mtSend_FailureMsg=1 +mtSend_FailureMsg0="Sorry, sending the message didn't work." + + diff --git a/official/2.1.6+2.1.beta1/Packages/tb2kdsgn_d7.dpk b/official/2.1.6+2.1.beta1/Packages/tb2kdsgn_d7.dpk new file mode 100644 index 0000000..017d0e2 --- /dev/null +++ b/official/2.1.6+2.1.beta1/Packages/tb2kdsgn_d7.dpk @@ -0,0 +1,42 @@ +package tb2kdsgn_d7; + +{$R *.res} +{$R '..\Source\TB2Reg.dcr'} +{$ALIGN 8} +{$ASSERTIONS ON} +{$BOOLEVAL OFF} +{$DEBUGINFO ON} +{$EXTENDEDSYNTAX ON} +{$IMPORTEDDATA ON} +{$IOCHECKS ON} +{$LOCALSYMBOLS ON} +{$LONGSTRINGS ON} +{$OPENSTRINGS ON} +{$OPTIMIZATION ON} +{$OVERFLOWCHECKS OFF} +{$RANGECHECKS OFF} +{$REFERENCEINFO OFF} +{$SAFEDIVIDE OFF} +{$STACKFRAMES OFF} +{$TYPEDADDRESS OFF} +{$VARSTRINGCHECKS ON} +{$WRITEABLECONST ON} +{$MINENUMSIZE 1} +{$IMAGEBASE $3F800000} +{$DESCRIPTION 'Toolbar2000 Design Package (Jordan Russell)'} +{$DESIGNONLY} +{$IMPLICITBUILD ON} + +requires + vcl, + dclstd, + tb2k_d7; + +contains + TB2Reg in '..\Source\TB2Reg.pas', + TB2DsgnItemEditor in '..\Source\TB2DsgnItemEditor.pas' {TBToolbarEditForm}, + TB2DsgnConverter in '..\Source\TB2DsgnConverter.pas' {TBConverterForm}, + TB2DsgnConvertOptions in '..\Source\TB2DsgnConvertOptions.pas' {TBConvertOptionsForm}; + +end. + diff --git a/official/2.1.6+2.1.beta1/Packages/tb2kdsgn_d7.drc b/official/2.1.6+2.1.beta1/Packages/tb2kdsgn_d7.drc new file mode 100644 index 0000000..a5d5271 --- /dev/null +++ b/official/2.1.6+2.1.beta1/Packages/tb2kdsgn_d7.drc @@ -0,0 +1,14 @@ +/* VER150 + Generated by the Borland Delphi Pascal Compiler + because -GD or --drc was supplied to the compiler. + + This file contains compiler-generated resources that + were bound to the executable. + If this file is empty, then no compiler-generated + resources were bound to the produced executable. +*/ + +STRINGTABLE +BEGIN +END + diff --git a/official/2.1.6+2.1.beta1/Packages/tb2kdsgn_d7.res b/official/2.1.6+2.1.beta1/Packages/tb2kdsgn_d7.res new file mode 100644 index 0000000..ec5f233 Binary files /dev/null and b/official/2.1.6+2.1.beta1/Packages/tb2kdsgn_d7.res differ diff --git a/official/2.1.6+2.1.beta1/Packages/tb2kdsgn_d9.dpk b/official/2.1.6+2.1.beta1/Packages/tb2kdsgn_d9.dpk new file mode 100644 index 0000000..6dc3949 --- /dev/null +++ b/official/2.1.6+2.1.beta1/Packages/tb2kdsgn_d9.dpk @@ -0,0 +1,44 @@ +package tb2kdsgn_d9; + +{ $jrsoftware: tb2k/Packages/tb2kdsgn_d9.dpk,v 1.1 2004/12/05 23:26:27 jr Exp $ } + +{$R *.res} +{$R '..\Source\TB2Reg.dcr'} +{$ALIGN 8} +{$ASSERTIONS ON} +{$BOOLEVAL OFF} +{$DEBUGINFO ON} +{$EXTENDEDSYNTAX ON} +{$IMPORTEDDATA ON} +{$IOCHECKS ON} +{$LOCALSYMBOLS ON} +{$LONGSTRINGS ON} +{$OPENSTRINGS ON} +{$OPTIMIZATION ON} +{$OVERFLOWCHECKS OFF} +{$RANGECHECKS OFF} +{$REFERENCEINFO OFF} +{$SAFEDIVIDE OFF} +{$STACKFRAMES OFF} +{$TYPEDADDRESS OFF} +{$VARSTRINGCHECKS ON} +{$WRITEABLECONST ON} +{$MINENUMSIZE 1} +{$IMAGEBASE $3F800000} +{$DESCRIPTION 'Toolbar2000 Design Package (Jordan Russell)'} +{$DESIGNONLY} +{$IMPLICITBUILD ON} + +requires + vcl, + dclstd, + tb2k_d9; + +contains + TB2Reg in '..\Source\TB2Reg.pas', + TB2DsgnItemEditor in '..\Source\TB2DsgnItemEditor.pas' {TBToolbarEditForm}, + TB2DsgnConverter in '..\Source\TB2DsgnConverter.pas' {TBConverterForm}, + TB2DsgnConvertOptions in '..\Source\TB2DsgnConvertOptions.pas' {TBConvertOptionsForm}; + +end. + diff --git a/official/2.1.6+2.1.beta1/Packages/tb2kdsgn_d9.res b/official/2.1.6+2.1.beta1/Packages/tb2kdsgn_d9.res new file mode 100644 index 0000000..36f26e2 Binary files /dev/null and b/official/2.1.6+2.1.beta1/Packages/tb2kdsgn_d9.res differ diff --git a/official/2.1.6+2.1.beta1/README.txt b/official/2.1.6+2.1.beta1/README.txt new file mode 100644 index 0000000..c8c520e --- /dev/null +++ b/official/2.1.6+2.1.beta1/README.txt @@ -0,0 +1,22 @@ +=========================================================================== + Toolbar2000 README +=========================================================================== + +Thank you for downloading Toolbar2000. + +For details on installing and using Toolbar2000, please refer to the +Toolbar2000 help file - tb2k.chm. To open it, double-click it in Windows +Explorer. + +This file is in HTML Help format. If you are using an older version of +Windows that does not come with HTML Help, it can be downloaded at: + + http://msdn.microsoft.com/library/en-us/htmlhelp/html/hwMicrosoftHTMLHelpDownloads.asp + +You will also need Internet Explorer 4.0 or later (5.0 is preferred), +downloadable from: + + http://www.microsoft.com/ie/ + + +- Jordan Russell (www.jrsoftware.org) diff --git a/official/2.1.6+2.1.beta1/Source/.cvsignore b/official/2.1.6+2.1.beta1/Source/.cvsignore new file mode 100644 index 0000000..d0e06ff --- /dev/null +++ b/official/2.1.6+2.1.beta1/Source/.cvsignore @@ -0,0 +1,4 @@ +*.dcu +*.obj +*.hpp +_* diff --git a/official/2.1.6+2.1.beta1/Source/Readme.txt b/official/2.1.6+2.1.beta1/Source/Readme.txt new file mode 100644 index 0000000..489d9b0 --- /dev/null +++ b/official/2.1.6+2.1.beta1/Source/Readme.txt @@ -0,0 +1,2 @@ +This directory contains files required for patching Toolbar 2000 +sources to make them compatible with TBX. \ No newline at end of file diff --git a/official/2.1.6+2.1.beta1/Source/TB2Acc.pas b/official/2.1.6+2.1.beta1/Source/TB2Acc.pas new file mode 100644 index 0000000..15ae9b2 --- /dev/null +++ b/official/2.1.6+2.1.beta1/Source/TB2Acc.pas @@ -0,0 +1,1224 @@ +unit TB2Acc; + +{ + Toolbar2000 + Copyright (C) 1998-2005 by Jordan Russell + All rights reserved. + + The contents of this file are subject to the "Toolbar2000 License"; you may + not use or distribute this file except in compliance with the + "Toolbar2000 License". A copy of the "Toolbar2000 License" may be found in + TB2k-LICENSE.txt or at: + http://www.jrsoftware.org/files/tb2k/TB2k-LICENSE.txt + + Alternatively, the contents of this file may be used under the terms of the + GNU General Public License (the "GPL"), in which case the provisions of the + GPL are applicable instead of those in the "Toolbar2000 License". A copy of + the GPL may be found in GPL-LICENSE.txt or at: + http://www.jrsoftware.org/files/tb2k/GPL-LICENSE.txt + If you wish to allow use of your version of this file only under the terms of + the GPL and not to allow others to use your version of this file under the + "Toolbar2000 License", indicate your decision by deleting the provisions + above and replace them with the notice and other provisions required by the + GPL. If you do not delete the provisions above, a recipient may use your + version of this file under either the "Toolbar2000 License" or the GPL. + + $jrsoftware: tb2k/Source/TB2Acc.pas,v 1.7 2005/01/06 03:56:50 jr Exp $ + + This unit is used internally to implement the IAccessible interface on + TTBView and TTBItemViewer for Microsoft Active Accessibility support. +} + +interface + +{$I TB2Ver.inc} + +uses + Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, + TB2Item; + +type + { Our declaration for IAccessible } + ITBAccessible = interface(IDispatch) + ['{618736E0-3C3D-11CF-810C-00AA00389B71}'] + function get_accParent(out ppdispParent: IDispatch): HRESULT; stdcall; + function get_accChildCount(out pcountChildren: Integer): HRESULT; stdcall; + function get_accChild(varChild: OleVariant; out ppdispChild: IDispatch): HRESULT; stdcall; + function get_accName(varChild: OleVariant; out pszName: WideString): HRESULT; stdcall; + function get_accValue(varChild: OleVariant; out pszValue: WideString): HRESULT; stdcall; + function get_accDescription(varChild: OleVariant; out pszDescription: WideString): HRESULT; stdcall; + function get_accRole(varChild: OleVariant; out pvarRole: OleVariant): HRESULT; stdcall; + function get_accState(varChild: OleVariant; out pvarState: OleVariant): HRESULT; stdcall; + function get_accHelp(varChild: OleVariant; out pszHelp: WideString): HRESULT; stdcall; + function get_accHelpTopic(out pszHelpFile: WideString; varChild: OleVariant; out pidTopic: Integer): HRESULT; stdcall; + function get_accKeyboardShortcut(varChild: OleVariant; out pszKeyboardShortcut: WideString): HRESULT; stdcall; + function get_accFocus(out pvarID: OleVariant): HRESULT; stdcall; + function get_accSelection(out pvarChildren: OleVariant): HRESULT; stdcall; + function get_accDefaultAction(varChild: OleVariant; out pszDefaultAction: WideString): HRESULT; stdcall; + function accSelect(flagsSelect: Integer; varChild: OleVariant): HRESULT; stdcall; + function accLocation(out pxLeft: Integer; out pyTop: Integer; out pcxWidth: Integer; + out pcyHeight: Integer; varChild: OleVariant): HRESULT; stdcall; + function accNavigate(navDir: Integer; varStart: OleVariant; out pvarEnd: OleVariant): HRESULT; stdcall; + function accHitTest(xLeft: Integer; yTop: Integer; out pvarID: OleVariant): HRESULT; stdcall; + function accDoDefaultAction(varChild: OleVariant): HRESULT; stdcall; + function put_accName(varChild: OleVariant; const pszName: WideString): HRESULT; stdcall; + function put_accValue(varChild: OleVariant; const pszValue: WideString): HRESULT; stdcall; + end; + + TTBCustomAccObject = class(TTBBaseAccObject, IUnknown, IDispatch) + private + FPrevious, FNext: TTBCustomAccObject; + public + constructor Create; + destructor Destroy; override; + end; + + TTBViewAccObject = class(TTBCustomAccObject, IUnknown, IDispatch, ITBAccessible) + private + FView: TTBView; + function Check(const varChild: OleVariant; var ErrorCode: HRESULT): Boolean; + { ITBAccessible } + function accDoDefaultAction(varChild: OleVariant): HRESULT; stdcall; + function accHitTest(xLeft: Integer; yTop: Integer; out pvarID: OleVariant): HRESULT; stdcall; + function accLocation(out pxLeft: Integer; out pyTop: Integer; out pcxWidth: Integer; + out pcyHeight: Integer; varChild: OleVariant): HRESULT; stdcall; + function accNavigate(navDir: Integer; varStart: OleVariant; out pvarEnd: OleVariant): HRESULT; stdcall; + function accSelect(flagsSelect: Integer; varChild: OleVariant): HRESULT; stdcall; + function get_accChild(varChild: OleVariant; out ppdispChild: IDispatch): HRESULT; stdcall; + function get_accChildCount(out pcountChildren: Integer): HRESULT; stdcall; + function get_accDefaultAction(varChild: OleVariant; out pszDefaultAction: WideString): HRESULT; stdcall; + function get_accDescription(varChild: OleVariant; out pszDescription: WideString): HRESULT; stdcall; + function get_accFocus(out pvarID: OleVariant): HRESULT; stdcall; + function get_accHelp(varChild: OleVariant; out pszHelp: WideString): HRESULT; stdcall; + function get_accHelpTopic(out pszHelpFile: WideString; varChild: OleVariant; out pidTopic: Integer): HRESULT; stdcall; + function get_accKeyboardShortcut(varChild: OleVariant; out pszKeyboardShortcut: WideString): HRESULT; stdcall; + function get_accName(varChild: OleVariant; out pszName: WideString): HRESULT; stdcall; + function get_accParent(out ppdispParent: IDispatch): HRESULT; stdcall; + function get_accRole(varChild: OleVariant; out pvarRole: OleVariant): HRESULT; stdcall; + function get_accSelection(out pvarChildren: OleVariant): HRESULT; stdcall; + function get_accState(varChild: OleVariant; out pvarState: OleVariant): HRESULT; stdcall; + function get_accValue(varChild: OleVariant; out pszValue: WideString): HRESULT; stdcall; + function put_accName(varChild: OleVariant; const pszName: WideString): HRESULT; stdcall; + function put_accValue(varChild: OleVariant; const pszValue: WideString): HRESULT; stdcall; + public + constructor Create(AView: TTBView); + destructor Destroy; override; + procedure ClientIsDestroying; override; + end; + + TTBItemViewerAccObject = class(TTBCustomAccObject, IUnknown, IDispatch, ITBAccessible) + private + FViewer: TTBItemViewer; + function Check(const varChild: OleVariant; var ErrorCode: HRESULT): Boolean; + function IsActionable: Boolean; + function IsAvailable: Boolean; + function IsFocusable: Boolean; + { ITBAccessible } + function accDoDefaultAction(varChild: OleVariant): HRESULT; stdcall; + function accHitTest(xLeft: Integer; yTop: Integer; out pvarID: OleVariant): HRESULT; stdcall; + function accLocation(out pxLeft: Integer; out pyTop: Integer; out pcxWidth: Integer; + out pcyHeight: Integer; varChild: OleVariant): HRESULT; stdcall; + function accNavigate(navDir: Integer; varStart: OleVariant; out pvarEnd: OleVariant): HRESULT; stdcall; + function accSelect(flagsSelect: Integer; varChild: OleVariant): HRESULT; stdcall; + function get_accChild(varChild: OleVariant; out ppdispChild: IDispatch): HRESULT; stdcall; + function get_accChildCount(out pcountChildren: Integer): HRESULT; stdcall; + function get_accDefaultAction(varChild: OleVariant; out pszDefaultAction: WideString): HRESULT; stdcall; + function get_accDescription(varChild: OleVariant; out pszDescription: WideString): HRESULT; stdcall; + function get_accFocus(out pvarID: OleVariant): HRESULT; stdcall; + function get_accHelp(varChild: OleVariant; out pszHelp: WideString): HRESULT; stdcall; + function get_accHelpTopic(out pszHelpFile: WideString; varChild: OleVariant; out pidTopic: Integer): HRESULT; stdcall; + function get_accKeyboardShortcut(varChild: OleVariant; out pszKeyboardShortcut: WideString): HRESULT; stdcall; + function get_accName(varChild: OleVariant; out pszName: WideString): HRESULT; stdcall; + function get_accParent(out ppdispParent: IDispatch): HRESULT; stdcall; + function get_accRole(varChild: OleVariant; out pvarRole: OleVariant): HRESULT; stdcall; + function get_accSelection(out pvarChildren: OleVariant): HRESULT; stdcall; + function get_accState(varChild: OleVariant; out pvarState: OleVariant): HRESULT; stdcall; + function get_accValue(varChild: OleVariant; out pszValue: WideString): HRESULT; stdcall; + function put_accName(varChild: OleVariant; const pszName: WideString): HRESULT; stdcall; + function put_accValue(varChild: OleVariant; const pszValue: WideString): HRESULT; stdcall; + public + constructor Create(AViewer: TTBItemViewer); + destructor Destroy; override; + procedure ClientIsDestroying; override; + procedure HandleAccSelect(const AExecute: Boolean); + end; + +procedure CallNotifyWinEvent(event: DWORD; hwnd: HWND; idObject: DWORD; + idChild: Longint); +function InitializeOleAcc: Boolean; + +var + LresultFromObjectFunc: function(const riid: TGUID; wParam: WPARAM; + pUnk: IUnknown): LRESULT; stdcall; + AccessibleObjectFromWindowFunc: function(hwnd: HWND; dwId: DWORD; + const riid: TGUID; out ppvObject: Pointer): HRESULT; stdcall; + + { For debugging purposes only: } + ViewAccObjectInstances: Integer = 0; + ItemViewerAccObjectInstances: Integer = 0; + +implementation + +uses + {$IFDEF JR_D6} Variants, {$ENDIF} ActiveX, Menus, TB2Common; + +const + { Constants from OleAcc.h } + ROLE_SYSTEM_MENUBAR = $2; + ROLE_SYSTEM_CLIENT = $a; + ROLE_SYSTEM_MENUPOPUP = $b; + ROLE_SYSTEM_MENUITEM = $c; + ROLE_SYSTEM_SEPARATOR = $15; + ROLE_SYSTEM_TOOLBAR = $16; + ROLE_SYSTEM_PUSHBUTTON = $2b; + ROLE_SYSTEM_BUTTONMENU = $39; + + STATE_SYSTEM_HASPOPUP = $40000000; + + NAVDIR_UP = 1; + NAVDIR_DOWN = 2; + NAVDIR_LEFT = 3; + NAVDIR_RIGHT = 4; + NAVDIR_NEXT = 5; + NAVDIR_PREVIOUS = 6; + NAVDIR_FIRSTCHILD = 7; + NAVDIR_LASTCHILD = 8; + + SELFLAG_TAKEFOCUS = 1; + +type + TControlAccess = class(TControl); + TTBViewAccess = class(TTBView); + TTBCustomItemAccess = class(TTBCustomItem); + TTBItemViewerAccess = class(TTBItemViewer); + +var + LastAccObject: TTBCustomAccObject; { last object in the linked list } + LastAccObjectCritSect: TRTLCriticalSection; + + NotifyWinEventInited: BOOL; + NotifyWinEventFunc: procedure(event: DWORD; hwnd: HWND; idObject: DWORD; + idChild: Longint); stdcall; + +procedure CallNotifyWinEvent(event: DWORD; hwnd: HWND; idObject: DWORD; + idChild: Longint); +begin + if not NotifyWinEventInited then begin + NotifyWinEventFunc := GetProcAddress(GetModuleHandle(user32), 'NotifyWinEvent'); + InterlockedExchange(Integer(NotifyWinEventInited), Ord(True)); + end; + if Assigned(NotifyWinEventFunc) then + NotifyWinEventFunc(event, hwnd, idObject, idChild); +end; + +var + OleAccInited: BOOL; + OleAccAvailable: BOOL; + +function InitializeOleAcc: Boolean; +var + M: HMODULE; +begin + if not OleAccInited then begin + M := {$IFDEF JR_D5} SafeLoadLibrary {$ELSE} LoadLibrary {$ENDIF} ('oleacc.dll'); + if M <> 0 then begin + LresultFromObjectFunc := GetProcAddress(M, 'LresultFromObject'); + AccessibleObjectFromWindowFunc := GetProcAddress(M, 'AccessibleObjectFromWindow'); + if Assigned(LresultFromObjectFunc) and + Assigned(AccessibleObjectFromWindowFunc) then + OleAccAvailable := True; + end; + InterlockedExchange(Integer(OleAccInited), Ord(True)); + end; + Result := OleAccAvailable; +end; + +function AccObjectFromWindow(const Wnd: HWND; out ADisp: IDispatch): Boolean; +var + P: Pointer; +begin + if Assigned(AccessibleObjectFromWindowFunc) and + (AccessibleObjectFromWindowFunc(Wnd, OBJID_WINDOW, IDispatch, P) = S_OK) then begin + ADisp := IDispatch(P); + IDispatch(P)._Release; + Result := True; + end + else + Result := False; +end; + +procedure DisconnectAccObjects; +{ This procedure calls CoDisconnectObject() on all acc. objects still + allocated. This is needed to prevent potential AV's when TB2k is compiled + into a DLL, since a DLL may be freed by the application while an MSAA + client still holds acc. object references. } +var + Obj, PrevObj: TTBCustomAccObject; +begin + Obj := LastAccObject; + while Assigned(Obj) do begin + { Make a copy of Obj.FPrevious since CoDisconnectObject may cause Obj + to be freed } + PrevObj := Obj.FPrevious; + { CoDisconnectObject should cause remote MSAA clients to release all + references to the object, thus destroying it (assuming the local + application doesn't have references of its own). } + CoDisconnectObject(Obj, 0); + Obj := PrevObj; + end; +end; + +function GetAltKeyName: String; +{ This silly function is needed since ShortCutToText(VK_MENU) fails on Delphi + and C++Builder versions <= 4 } +var + ScanCode: UINT; + KeyName: array[0..255] of Char; +begin + ScanCode := MapVirtualKey(VK_MENU, 0) shl 16; + if (ScanCode <> 0) and + (GetKeyNameText(ScanCode, KeyName, SizeOf(KeyName)) > 0) then + Result := KeyName + else + Result := 'Alt'; { shouldn't get here, but just in case... } +end; + +{ TTBCustomAccObject } + +constructor TTBCustomAccObject.Create; +begin + inherited Create; + { Add Self to linked list of objects } + EnterCriticalSection(LastAccObjectCritSect); + try + FPrevious := LastAccObject; + if Assigned(FPrevious) then + FPrevious.FNext := Self; + LastAccObject := Self; + finally + LeaveCriticalSection(LastAccObjectCritSect); + end; +end; + +destructor TTBCustomAccObject.Destroy; +begin + { Remove Self from linked list of objects } + EnterCriticalSection(LastAccObjectCritSect); + try + if LastAccObject = Self then + LastAccObject := FPrevious; + if Assigned(FPrevious) then + FPrevious.FNext := FNext; + if Assigned(FNext) then + FNext.FPrevious := FPrevious; + finally + LeaveCriticalSection(LastAccObjectCritSect); + end; + inherited; +end; + +{ TTBViewAccObject } + +constructor TTBViewAccObject.Create(AView: TTBView); +begin + inherited Create; + FView := AView; + InterlockedIncrement(ViewAccObjectInstances); +end; + +destructor TTBViewAccObject.Destroy; +begin + InterlockedDecrement(ViewAccObjectInstances); + if Assigned(FView) then begin + TTBViewAccess(FView).FAccObjectInstance := nil; + FView := nil; + end; + inherited; +end; + +procedure TTBViewAccObject.ClientIsDestroying; +begin + FView := nil; +end; + +function TTBViewAccObject.Check(const varChild: OleVariant; + var ErrorCode: HRESULT): Boolean; +begin + if FView = nil then begin + ErrorCode := E_FAIL; + Result := False; + end + else if (VarType(varChild) <> varInteger) or (varChild <> CHILDID_SELF) then begin + ErrorCode := E_INVALIDARG; + Result := False; + end + else + Result := True; +end; + +function TTBViewAccObject.accDoDefaultAction(varChild: OleVariant): HRESULT; +begin + Result := S_FALSE; +end; + +function TTBViewAccObject.accHitTest(xLeft, yTop: Integer; + out pvarID: OleVariant): HRESULT; +var + ViewWnd, W: HWND; + R: TRect; + P: TPoint; + D: IDispatch; + V: TTBItemViewer; +begin + try + if FView = nil then begin + Result := E_FAIL; + Exit; + end; + ViewWnd := FView.Window.Handle; + GetWindowRect(ViewWnd, R); + P.X := xLeft; + P.Y := yTop; + if PtInRect(R, P) then begin + P := FView.Window.ScreenToClient(P); + W := ChildWindowFromPointEx(ViewWnd, P, CWP_SKIPINVISIBLE); + if (W <> 0) and (W <> ViewWnd) then begin + { Point is inside a child window (most likely belonging to a + TTBControlItem) } + if AccObjectFromWindow(W, D) then begin + pvarID := D; + Result := S_OK; + end + else + Result := E_UNEXPECTED; + end + else begin + V := FView.ViewerFromPoint(P); + if Assigned(V) then + pvarID := V.GetAccObject + else + pvarID := CHILDID_SELF; + Result := S_OK; + end; + end + else + Result := S_FALSE; + except + Result := E_UNEXPECTED; + end; +end; + +function TTBViewAccObject.accLocation(out pxLeft, pyTop, pcxWidth, + pcyHeight: Integer; varChild: OleVariant): HRESULT; +var + R: TRect; +begin + try + if not Check(varChild, Result) then + Exit; + GetWindowRect(FView.Window.Handle, R); + pxLeft := R.Left; + pyTop := R.Top; + pcxWidth := R.Right - R.Left; + pcyHeight := R.Bottom - R.Top; + Result := S_OK; + except + Result := E_UNEXPECTED; + end; +end; + +function TTBViewAccObject.accNavigate(navDir: Integer; varStart: OleVariant; + out pvarEnd: OleVariant): HRESULT; +var + I: Integer; +begin + try + if not Check(varStart, Result) then + Exit; + Result := S_FALSE; + case navDir of + NAVDIR_FIRSTCHILD: begin + for I := 0 to FView.ViewerCount-1 do + if FView.Viewers[I].IsAccessible then begin + pvarEnd := FView.Viewers[I].GetAccObject; + Result := S_OK; + Break; + end; + end; + NAVDIR_LASTCHILD: begin + for I := FView.ViewerCount-1 downto 0 do + if FView.Viewers[I].IsAccessible then begin + pvarEnd := FView.Viewers[I].GetAccObject; + Result := S_OK; + Break; + end; + end; + end; + except + Result := E_UNEXPECTED; + end; +end; + +function TTBViewAccObject.accSelect(flagsSelect: Integer; + varChild: OleVariant): HRESULT; +begin + Result := DISP_E_MEMBERNOTFOUND; +end; + +function TTBViewAccObject.get_accChild(varChild: OleVariant; + out ppdispChild: IDispatch): HRESULT; +var + I, J: Integer; + Viewer: TTBItemViewer; + Ctl: TControl; +begin + try + if FView = nil then begin + Result := E_FAIL; + Exit; + end; + if VarType(varChild) <> varInteger then begin + Result := E_INVALIDARG; + Exit; + end; + I := varChild; + if I = CHILDID_SELF then begin + ppdispChild := Self; + Result := S_OK; + end + else begin + { Convert a one-based child index (I) into a real viewer index (J) } + J := 0; + while J < FView.ViewerCount do begin + if FView.Viewers[J].IsAccessible then begin + if I = 1 then Break; + Dec(I); + end; + Inc(J); + end; + if J >= FView.ViewerCount then begin + { 'I' was either negative or too high } + Result := E_INVALIDARG; + Exit; + end; + Viewer := FView.Viewers[J]; + if Viewer.Item is TTBControlItem then begin + { For windowed controls, return the window's accessible object instead + of the item viewer's } + Ctl := TTBControlItem(Viewer.Item).Control; + if (Ctl is TWinControl) and TWinControl(Ctl).HandleAllocated then begin + if AccObjectFromWindow(TWinControl(Ctl).Handle, ppdispChild) then + Result := S_OK + else + Result := E_UNEXPECTED; + Exit; + end; + end; + ppdispChild := Viewer.GetAccObject; + Result := S_OK; + end; + except + Result := E_UNEXPECTED; + end; +end; + +function TTBViewAccObject.get_accChildCount(out pcountChildren: Integer): HRESULT; +var + Count, I: Integer; +begin + try + if Assigned(FView) then begin + Count := 0; + for I := 0 to FView.ViewerCount-1 do + if FView.Viewers[I].IsAccessible then + Inc(Count); + pCountChildren := Count; + Result := S_OK; + end + else + Result := E_FAIL; + except + Result := E_UNEXPECTED; + end; +end; + +function TTBViewAccObject.get_accDefaultAction(varChild: OleVariant; + out pszDefaultAction: WideString): HRESULT; +begin + Result := S_FALSE; +end; + +function TTBViewAccObject.get_accDescription(varChild: OleVariant; + out pszDescription: WideString): HRESULT; +begin + Result := S_FALSE; +end; + +function TTBViewAccObject.get_accFocus(out pvarID: OleVariant): HRESULT; +begin + Result := S_FALSE; +end; + +function TTBViewAccObject.get_accHelp(varChild: OleVariant; + out pszHelp: WideString): HRESULT; +begin + Result := S_FALSE; +end; + +function TTBViewAccObject.get_accHelpTopic(out pszHelpFile: WideString; + varChild: OleVariant; out pidTopic: Integer): HRESULT; +begin + pidTopic := 0; { Delphi doesn't implicitly clear Integer 'out' parameters } + Result := S_FALSE; +end; + +function TTBViewAccObject.get_accKeyboardShortcut(varChild: OleVariant; + out pszKeyboardShortcut: WideString): HRESULT; +begin + try + if not Check(varChild, Result) then + Exit; + if vsMenuBar in FView.Style then begin + pszKeyboardShortcut := GetAltKeyName; + Result := S_OK; + end + else + Result := S_FALSE; + except + Result := E_UNEXPECTED; + end; +end; + +function TTBViewAccObject.get_accName(varChild: OleVariant; + out pszName: WideString): HRESULT; +var + S: String; +begin + try + if not Check(varChild, Result) then + Exit; + if Assigned(FView.ParentView) and Assigned(FView.ParentView.OpenViewer) then + S := StripAccelChars(TTBItemViewerAccess(FView.ParentView.OpenViewer).GetCaptionText); + if S = '' then + S := TControlAccess(FView.Window).Caption; + pszName := S; + Result := S_OK; + except + Result := E_UNEXPECTED; + end; +end; + +function TTBViewAccObject.get_accParent(out ppdispParent: IDispatch): HRESULT; +begin + try + if Assigned(FView) then begin + if Assigned(FView.ParentView) and Assigned(FView.ParentView.OpenViewer) then begin + ppdispParent := FView.ParentView.OpenViewer.GetAccObject; + Result := S_OK; + end + else begin + if AccObjectFromWindow(FView.Window.Handle, ppdispParent) then + Result := S_OK + else + Result := E_UNEXPECTED; + end; + end + else + Result := E_FAIL; + except + Result := E_UNEXPECTED; + end; +end; + +function TTBViewAccObject.get_accRole(varChild: OleVariant; + out pvarRole: OleVariant): HRESULT; +begin + try + if not Check(varChild, Result) then + Exit; + if FView.IsPopup then + pvarRole := ROLE_SYSTEM_MENUPOPUP + else begin + if vsMenuBar in FView.Style then + pvarRole := ROLE_SYSTEM_MENUBAR + else + pvarRole := ROLE_SYSTEM_TOOLBAR; + end; + Result := S_OK; + except + Result := E_UNEXPECTED; + end; +end; + +function TTBViewAccObject.get_accSelection(out pvarChildren: OleVariant): HRESULT; +begin + Result := S_FALSE; +end; + +function TTBViewAccObject.get_accState(varChild: OleVariant; + out pvarState: OleVariant): HRESULT; +begin + try + if not Check(varChild, Result) then + Exit; + pvarState := 0; + Result := S_OK; + except + Result := E_UNEXPECTED; + end; +end; + +function TTBViewAccObject.get_accValue(varChild: OleVariant; + out pszValue: WideString): HRESULT; +begin + Result := S_FALSE; +end; + +function TTBViewAccObject.put_accName(varChild: OleVariant; + const pszName: WideString): HRESULT; +begin + Result := S_FALSE; +end; + +function TTBViewAccObject.put_accValue(varChild: OleVariant; + const pszValue: WideString): HRESULT; +begin + Result := S_FALSE; +end; + +{ TTBItemViewerAccObject } + +constructor TTBItemViewerAccObject.Create(AViewer: TTBItemViewer); +begin + inherited Create; + FViewer := AViewer; + InterlockedIncrement(ItemViewerAccObjectInstances); +end; + +destructor TTBItemViewerAccObject.Destroy; +begin + InterlockedDecrement(ItemViewerAccObjectInstances); + if Assigned(FViewer) then begin + TTBItemViewerAccess(FViewer).FAccObjectInstance := nil; + FViewer := nil; + end; + inherited; +end; + +procedure TTBItemViewerAccObject.ClientIsDestroying; +begin + FViewer := nil; +end; + +function TTBItemViewerAccObject.Check(const varChild: OleVariant; + var ErrorCode: HRESULT): Boolean; +begin + if FViewer = nil then begin + ErrorCode := E_FAIL; + Result := False; + end + else if (VarType(varChild) <> varInteger) or (varChild <> CHILDID_SELF) then begin + ErrorCode := E_INVALIDARG; + Result := False; + end + else + Result := True; +end; + +function TTBItemViewerAccObject.IsActionable: Boolean; +{ Returns True if 'doDefaultAction' may be performed on the viewer, i.e. if + it's visible/off-edge/clipped, enabled & selectable, and the view is + focusable. } +begin + Result := FViewer.IsAccessible and IsAvailable and IsFocusable; +end; + +function TTBItemViewerAccObject.IsAvailable: Boolean; +{ Returns True if the viewer's item is enabled and selectable } +begin + Result := FViewer.Item.Enabled and + (tbisSelectable in TTBCustomItemAccess(FViewer.Item).ItemStyle); +end; + +function TTBItemViewerAccObject.IsFocusable: Boolean; +{ Returns True if viewers on the view can be 'focused' (i.e. the view's window + doesn't have the csDesigning state, the window is visible and enabled, and + the application is active). } + + function IsWindowAndParentsEnabled(W: HWND): Boolean; + begin + Result := True; + repeat + if not IsWindowEnabled(W) then begin + Result := False; + Break; + end; + W := GetParent(W); + until W = 0; + end; + +var + ViewWnd, ActiveWnd: HWND; +begin + Result := False; + if csDesigning in FViewer.View.Window.ComponentState then + Exit; + ViewWnd := FViewer.View.Window.Handle; + if IsWindowVisible(ViewWnd) and IsWindowAndParentsEnabled(ViewWnd) then begin + if vsModal in FViewer.View.State then + Result := True + else begin + ActiveWnd := GetActiveWindow; + if (ActiveWnd <> 0) and + ((ActiveWnd = ViewWnd) or IsChild(ActiveWnd, ViewWnd)) then + Result := True; + end; + end; +end; + +procedure TTBItemViewerAccObject.HandleAccSelect(const AExecute: Boolean); +begin + if Assigned(FViewer) and + ((AExecute and IsActionable) or (not AExecute and IsFocusable)) then begin + FViewer.View.Selected := FViewer; + FViewer.View.ScrollSelectedIntoView; + if vsModal in FViewer.View.State then begin + if AExecute then + FViewer.View.ExecuteSelected(False); + end + else if (FViewer.View.ParentView = nil) and (GetCapture = 0) then begin + if AExecute then + FViewer.View.EnterToolbarLoop([tbetExecuteSelected, tbetFromMSAA]) + else + FViewer.View.EnterToolbarLoop([tbetFromMSAA]); + end; + end; +end; + +function TTBItemViewerAccObject.accDoDefaultAction(varChild: OleVariant): HRESULT; +begin + try + if not Check(varChild, Result) then + Exit; + { NOTE: This must be kept in synch with get_accDefaultAction } + if IsActionable then begin + Result := S_OK; + if FViewer.View.OpenViewer = FViewer then begin + FViewer.View.CancelChildPopups; + { Like standard menus, cancel the modal loop when a top-level menu + is closed } + if (vsModal in FViewer.View.State) and not FViewer.View.IsPopup then + FViewer.View.EndModal; + end + else begin + FViewer.View.Selected := FViewer; + FViewer.View.ScrollSelectedIntoView; + TTBItemViewerAccess(FViewer).PostAccSelect(True); + end; + end + else + { Note: Standard menus return DISP_E_MEMBERNOTFOUND in this case but + that doesn't make much sense. The member is there but just isn't + currently available. } + Result := E_FAIL; + except + Result := E_UNEXPECTED; + end; +end; + +function TTBItemViewerAccObject.accHitTest(xLeft, yTop: Integer; + out pvarID: OleVariant): HRESULT; +var + P: TPoint; +begin + try + if FViewer = nil then begin + Result := E_FAIL; + Exit; + end; + P := FViewer.View.Window.ScreenToClient(Point(xLeft, yTop)); + if PtInRect(FViewer.BoundsRect, P) then begin + pvarID := CHILDID_SELF; + Result := S_OK; + end + else + Result := S_FALSE; + except + Result := E_UNEXPECTED; + end; +end; + +function TTBItemViewerAccObject.accLocation(out pxLeft, pyTop, pcxWidth, + pcyHeight: Integer; varChild: OleVariant): HRESULT; +var + R: TRect; + P: TPoint; +begin + try + if not Check(varChild, Result) then + Exit; + R := FViewer.BoundsRect; + P := FViewer.View.Window.ClientToScreen(Point(0, 0)); + OffsetRect(R, P.X, P.Y); + pxLeft := R.Left; + pyTop := R.Top; + pcxWidth := R.Right - R.Left; + pcyHeight := R.Bottom - R.Top; + Result := S_OK; + except + Result := E_UNEXPECTED; + end; +end; + +function TTBItemViewerAccObject.accNavigate(navDir: Integer; varStart: OleVariant; + out pvarEnd: OleVariant): HRESULT; +var + I, J: Integer; + View: TTBView; +begin + try + if not Check(varStart, Result) then + Exit; + Result := S_FALSE; + if (navDir = NAVDIR_FIRSTCHILD) or (navDir = NAVDIR_LASTCHILD) then begin + { Return the child view's acc. object } + View := FViewer.View.OpenViewerView; + if Assigned(View) then begin + pvarEnd := View.GetAccObject; + Result := S_OK; + end; + end + else begin + I := FViewer.View.IndexOf(FViewer); + if I >= 0 then begin + case navDir of + NAVDIR_UP, NAVDIR_LEFT, NAVDIR_PREVIOUS: + for J := I-1 downto 0 do + if FViewer.View.Viewers[J].IsAccessible then begin + pvarEnd := FViewer.View.Viewers[J].GetAccObject; + Result := S_OK; + Break; + end; + NAVDIR_DOWN, NAVDIR_RIGHT, NAVDIR_NEXT: + for J := I+1 to FViewer.View.ViewerCount-1 do + if FViewer.View.Viewers[J].IsAccessible then begin + pvarEnd := FViewer.View.Viewers[J].GetAccObject; + Result := S_OK; + Break; + end; + end; + end; + end; + except + Result := E_UNEXPECTED; + end; +end; + +function TTBItemViewerAccObject.accSelect(flagsSelect: Integer; + varChild: OleVariant): HRESULT; +begin + try + if not Check(varChild, Result) then + Exit; + if flagsSelect <> SELFLAG_TAKEFOCUS then begin + Result := E_INVALIDARG; + Exit; + end; + if IsFocusable and (FViewer.Show or FViewer.Clipped) then begin + FViewer.View.Selected := FViewer; + FViewer.View.ScrollSelectedIntoView; + if not(vsModal in FViewer.View.State) and + (FViewer.View.ParentView = nil) then + TTBItemViewerAccess(FViewer).PostAccSelect(False); + end + else + Result := E_FAIL; + { ^ what Office XP returns when you try focusing an off-edge item } + except + Result := E_UNEXPECTED; + end; +end; + +function TTBItemViewerAccObject.get_accChild(varChild: OleVariant; + out ppdispChild: IDispatch): HRESULT; +var + View: TTBView; +begin + try + if FViewer = nil then begin + Result := E_FAIL; + Exit; + end; + Result := E_INVALIDARG; + if VarType(varChild) = varInteger then begin + if varChild = CHILDID_SELF then begin + ppdispChild := Self; + Result := S_OK; + end + else if varChild = 1 then begin + { Return the child view's acc. object } + View := FViewer.View.OpenViewerView; + if Assigned(View) then begin + ppdispChild := View.GetAccObject; + Result := S_OK; + end; + end; + end; + except + Result := E_UNEXPECTED; + end; +end; + +function TTBItemViewerAccObject.get_accChildCount(out pcountChildren: Integer): HRESULT; +begin + try + if FViewer = nil then begin + Result := E_FAIL; + Exit; + end; + { Return 1 if the viewer has a child view } + if FViewer.View.OpenViewer = FViewer then + pCountChildren := 1 + else + pCountChildren := 0; + Result := S_OK; + except + Result := E_UNEXPECTED; + end; +end; + +function TTBItemViewerAccObject.get_accDefaultAction(varChild: OleVariant; + out pszDefaultAction: WideString): HRESULT; +begin + try + if not Check(varChild, Result) then + Exit; + if IsActionable then begin + { I'm not sure if these should be localized, or even if any screen + readers make use of this text... + NOTE: This must be kept in synch with accDoDefaultAction } + if FViewer.View.OpenViewer = FViewer then + pszDefaultAction := 'Close' + else if tbisSubmenu in TTBCustomItemAccess(FViewer.Item).ItemStyle then + pszDefaultAction := 'Open' + else if FViewer.View.IsPopup or (vsMenuBar in FViewer.View.Style) then + pszDefaultAction := 'Execute' + else + pszDefaultAction := 'Press'; + Result := S_OK; + end + else + Result := S_FALSE; + except + Result := E_UNEXPECTED; + end; +end; + +function TTBItemViewerAccObject.get_accDescription(varChild: OleVariant; + out pszDescription: WideString): HRESULT; +begin + Result := S_FALSE; +end; + +function TTBItemViewerAccObject.get_accFocus(out pvarID: OleVariant): HRESULT; +begin + try + if FViewer = nil then begin + Result := E_FAIL; + Exit; + end; + if (vsModal in FViewer.View.State) and + (FViewer.View.Selected = FViewer) then begin + pvarID := CHILDID_SELF; + Result := S_OK; + end + else + Result := S_FALSE; + except + Result := E_UNEXPECTED; + end; +end; + +function TTBItemViewerAccObject.get_accHelp(varChild: OleVariant; + out pszHelp: WideString): HRESULT; +begin + Result := S_FALSE; +end; + +function TTBItemViewerAccObject.get_accHelpTopic(out pszHelpFile: WideString; + varChild: OleVariant; out pidTopic: Integer): HRESULT; +begin + pidTopic := 0; { Delphi doesn't implicitly clear Integer 'out' parameters } + Result := S_FALSE; +end; + +function TTBItemViewerAccObject.get_accKeyboardShortcut(varChild: OleVariant; + out pszKeyboardShortcut: WideString): HRESULT; +var + C: Char; +begin + try + if not Check(varChild, Result) then + Exit; + Result := S_FALSE; + if TTBItemViewerAccess(FViewer).CaptionShown then begin + C := FindAccelChar(TTBItemViewerAccess(FViewer).GetCaptionText); + if C <> #0 then begin + CharLowerBuff(@C, 1); { like standard menus, always use lowercase... } + if FViewer.View.IsPopup then + pszKeyboardShortcut := C + else begin + { Prefix 'Alt+' } + pszKeyboardShortcut := GetAltKeyName + '+' + C; + end; + Result := S_OK; + end; + end; + except + Result := E_UNEXPECTED; + end; +end; + +function TTBItemViewerAccObject.get_accName(varChild: OleVariant; + out pszName: WideString): HRESULT; +var + C, S: String; +begin + try + if not Check(varChild, Result) then + Exit; + C := StripAccelChars(TTBItemViewerAccess(FViewer).GetCaptionText); + if not FViewer.IsToolbarStyle then + S := FViewer.Item.GetShortCutText; + if S = '' then + pszName := C + else + pszName := C + #9 + S; + Result := S_OK; + except + Result := E_UNEXPECTED; + end; +end; + +function TTBItemViewerAccObject.get_accParent(out ppdispParent: IDispatch): HRESULT; +begin + try + if Assigned(FViewer) then begin + ppdispParent := FViewer.View.GetAccObject; + Result := S_OK; + end + else + Result := E_FAIL; + except + Result := E_UNEXPECTED; + end; +end; + +function TTBItemViewerAccObject.get_accRole(varChild: OleVariant; + out pvarRole: OleVariant): HRESULT; +begin + try + if not Check(varChild, Result) then + Exit; + pvarRole := TTBItemViewerAccess(FViewer).GetAccRole; + Result := S_OK; + except + Result := E_UNEXPECTED; + end; +end; + +function TTBItemViewerAccObject.get_accSelection(out pvarChildren: OleVariant): HRESULT; +begin + Result := S_FALSE; +end; + +function TTBItemViewerAccObject.get_accState(varChild: OleVariant; + out pvarState: OleVariant): HRESULT; +var + Flags: Integer; +begin + try + if not Check(varChild, Result) then + Exit; + Flags := 0; + if FViewer.View.Selected = FViewer then begin + Flags := Flags or STATE_SYSTEM_HOTTRACKED; + if vsModal in FViewer.View.State then + Flags := Flags or STATE_SYSTEM_FOCUSED; + if FViewer.View.MouseOverSelected and FViewer.View.Capture then + { ^ based on "IsPushed :=" code in TTBView.DrawItem } + Flags := Flags or STATE_SYSTEM_PRESSED; + end; + if tbisSubmenu in TTBCustomItemAccess(FViewer.Item).ItemStyle then + Flags := Flags or STATE_SYSTEM_HASPOPUP; + if FViewer.Show or FViewer.Clipped then begin + if IsFocusable then + Flags := Flags or STATE_SYSTEM_FOCUSABLE; + end + else begin + { Mark off-edge items as invisible, like Office } + Flags := Flags or STATE_SYSTEM_INVISIBLE; + end; + if not IsAvailable then + Flags := Flags or STATE_SYSTEM_UNAVAILABLE; + if FViewer.Item.Checked then + Flags := Flags or STATE_SYSTEM_CHECKED; + pvarState := Flags; + Result := S_OK; + except + Result := E_UNEXPECTED; + end; +end; + +function TTBItemViewerAccObject.get_accValue(varChild: OleVariant; + out pszValue: WideString): HRESULT; +begin + try + if not Check(varChild, Result) then + Exit; + if TTBItemViewerAccess(FViewer).GetAccValue(pszValue) then + Result := S_OK + else begin + pszValue := ''; + Result := S_FALSE; + end; + except + Result := E_UNEXPECTED; + end; +end; + +function TTBItemViewerAccObject.put_accName(varChild: OleVariant; + const pszName: WideString): HRESULT; +begin + Result := S_FALSE; +end; + +function TTBItemViewerAccObject.put_accValue(varChild: OleVariant; + const pszValue: WideString): HRESULT; +begin + Result := S_FALSE; +end; + +{ Note: This COM initialization code based on code from DBTables } +var + SaveInitProc: Pointer; + NeedToUninitialize: Boolean; + +procedure InitCOM; +begin + if SaveInitProc <> nil then TProcedure(SaveInitProc); + NeedToUninitialize := SUCCEEDED(CoInitialize(nil)); +end; + +initialization + InitializeCriticalSection(LastAccObjectCritSect); + if not IsLibrary then begin + SaveInitProc := InitProc; + InitProc := @InitCOM; + end; +finalization + DisconnectAccObjects; + if NeedToUninitialize then + CoUninitialize; + DeleteCriticalSection(LastAccObjectCritSect); +end. diff --git a/official/2.1.6+2.1.beta1/Source/TB2Anim.pas b/official/2.1.6+2.1.beta1/Source/TB2Anim.pas new file mode 100644 index 0000000..5d618ca --- /dev/null +++ b/official/2.1.6+2.1.beta1/Source/TB2Anim.pas @@ -0,0 +1,293 @@ +unit TB2Anim; + +{ + Toolbar2000 + Copyright (C) 1998-2005 by Jordan Russell + All rights reserved. + + The contents of this file are subject to the "Toolbar2000 License"; you may + not use or distribute this file except in compliance with the + "Toolbar2000 License". A copy of the "Toolbar2000 License" may be found in + TB2k-LICENSE.txt or at: + http://www.jrsoftware.org/files/tb2k/TB2k-LICENSE.txt + + Alternatively, the contents of this file may be used under the terms of the + GNU General Public License (the "GPL"), in which case the provisions of the + GPL are applicable instead of those in the "Toolbar2000 License". A copy of + the GPL may be found in GPL-LICENSE.txt or at: + http://www.jrsoftware.org/files/tb2k/GPL-LICENSE.txt + If you wish to allow use of your version of this file only under the terms of + the GPL and not to allow others to use your version of this file under the + "Toolbar2000 License", indicate your decision by deleting the provisions + above and replace them with the notice and other provisions required by the + GPL. If you do not delete the provisions above, a recipient may use your + version of this file under either the "Toolbar2000 License" or the GPL. + + $jrsoftware: tb2k/Source/TB2Anim.pas,v 1.11 2005/02/16 08:15:58 jr Exp $ +} + +interface + +{$I TB2Ver.inc} +{$Q-} + +uses + Windows, Messages, SysUtils, Classes; + +const + WM_TB2K_STEPANIMATION = WM_USER + $555; + WM_TB2K_ANIMATIONENDED = WM_USER + $556; + +type + TTBAnimationDirection = set of (tbadLeft, tbadRight, tbadDown, tbadUp); + +procedure TBStartAnimation(const AWnd: HWND; const ABlend: Boolean; + const ADirection: TTBAnimationDirection); +procedure TBStepAnimation(const Msg: TMessage); +procedure TBEndAnimation(const Wnd: HWND); + +implementation + +{ Notes to self: + - It originally had the NOMIRRORBITMAP flag on the BitBlt calls, because + Windows 2000's AnimateWindow function has it. But it had to be removed + because on Windows 98 with the Standard VGA or VMware video driver, it + caused no bits to be blitted, even though Windows 98 is supposed to + support NOMIRRORBITMAP according to the documentation. I don't think it's + necessary anyway. +} + +const + DCX_USESTYLE = $10000; + WS_EX_LAYERED = $80000; + NOMIRRORBITMAP = $80000000; + ULW_ALPHA = 2; + +type + PAnimateThreadFuncData = ^TAnimateThreadFuncData; + TAnimateThreadFuncData = record + SequenceID: Integer; + Wnd: HWND; + Time: Integer; + Blending: Boolean; + CurStep: Integer; + DC, BmpDC: HDC; + Bmp: HBITMAP; + ScreenClientRect: TRect; + Size: TPoint; + LastPos: TPoint; + Direction: TTBAnimationDirection; + AnimateThreadAbort: BOOL; + AnimationEnded: BOOL; + StepMessagePending: BOOL; + end; + +var + UpdateLayeredWindowProc: function(Handle: THandle; hdcDest: HDC; + pptDst: PPoint; _psize: PSize; hdcSrc: HDC; pptSrc: PPoint; + crKey: COLORREF; pblend: PBLENDFUNCTION; dwFlags: DWORD): BOOL; stdcall; + +function AnimateThreadFunc(Parameter: Pointer): Integer; +var + StartTime, FrameStartTime, NextFrameStartTime: DWORD; + StartStep, ElapsedTime, I: Integer; + P: TPoint; +begin + Result := 0; + StartTime := GetTickCount; + FrameStartTime := StartTime; + with PAnimateThreadFuncData(Parameter)^ do begin + StartStep := CurStep; + while not AnimateThreadAbort do begin + ElapsedTime := FrameStartTime - StartTime; + if (ElapsedTime < 0) or (ElapsedTime >= Time) then + Break; + I := StartStep + ((255 * ElapsedTime) div Time); + if (I < 0) or (I >= 255) then + Break; + + GetCursorPos(P); + if (P.X <> LastPos.X) or (P.Y <> LastPos.Y) then begin + if PtInRect(ScreenClientRect, P) then + Break; + LastPos := P; + end; + + if I > CurStep then begin + CurStep := I; + if InterlockedExchange(Integer(StepMessagePending), 1) = 0 then + SendNotifyMessage(Wnd, WM_TB2K_STEPANIMATION, 0, SequenceID); + end; + + { Wait until the timer has ticked at least 10 msec } + NextFrameStartTime := GetTickCount; + while NextFrameStartTime - FrameStartTime < 10 do begin + { We don't know the rate of the system timer, so check every 5 msec + to see if it's incremented } + Sleep(5); + NextFrameStartTime := GetTickCount; + end; + FrameStartTime := NextFrameStartTime; + end; + AnimationEnded := True; + SendNotifyMessage(Wnd, WM_TB2K_STEPANIMATION, 0, SequenceID); + end; +end; + +threadvar + AnimateThreadHandle: THandle; + AnimateData: TAnimateThreadFuncData; + AnimationSequenceID: Integer; + +procedure FinalizeAnimation; +begin + with PAnimateThreadFuncData(@AnimateData)^ do begin + if Blending then + SetWindowLong(Wnd, GWL_EXSTYLE, + GetWindowLong(Wnd, GWL_EXSTYLE) and not WS_EX_LAYERED) + else + SetWindowRgn(Wnd, 0, False); + BitBlt(DC, 0, 0, Size.X, Size.Y, BmpDC, 0, 0, SRCCOPY); + DeleteDC(BmpDC); + DeleteObject(Bmp); + ReleaseDC(Wnd, DC); + SendNotifyMessage(Wnd, WM_TB2K_ANIMATIONENDED, 0, 0); + end; +end; + +procedure TBEndAnimation(const Wnd: HWND); +begin + if (AnimateThreadHandle <> 0) and + ((Wnd = 0) or (AnimateData.Wnd = Wnd)) then begin + AnimateData.AnimateThreadAbort := True; + WaitForSingleObject(AnimateThreadHandle, INFINITE); + CloseHandle(AnimateThreadHandle); + AnimateThreadHandle := 0; + + FinalizeAnimation; + end; +end; + +procedure TBStartAnimation(const AWnd: HWND; const ABlend: Boolean; + const ADirection: TTBAnimationDirection); +var + ZeroPt: TPoint; + R: TRect; + ThreadID: DWORD; + Blend: TBlendFunction; + Rgn: HRGN; +begin + TBEndAnimation(0); + + ZeroPt.X := 0; + ZeroPt.Y := 0; + + Inc(AnimationSequenceID); + FillChar(AnimateData, SizeOf(AnimateData), 0); + { Note: The pointer cast avoids GetTls calls for every field access } + with PAnimateThreadFuncData(@AnimateData)^ do begin + SequenceID := AnimationSequenceID; + Wnd := AWnd; + Blending := ABlend and Assigned(UpdateLayeredWindowProc); + Direction := ADirection; + GetCursorPos(LastPos); + GetClientRect(Wnd, ScreenClientRect); + MapWindowPoints(Wnd, 0, ScreenClientRect, 2); + GetWindowRect(Wnd, R); + DC := GetDCEx(Wnd, 0, DCX_WINDOW or DCX_CACHE {or DCX_USESTYLE ?}); + Size.X := R.Right - R.Left; + Size.Y := R.Bottom - R.Top; + Bmp := CreateCompatibleBitmap(DC, Size.X, Size.Y {or $01000000 ?}); + BmpDC := CreateCompatibleDC(DC); + // AnimateWindow calls SetLayout, but I'm not sure that we need to. + //if Assigned(SetLayoutProc) then + // SetLayoutProc(BmpDC, 0); + SelectObject(BmpDC, Bmp); + //SetBoundsRect(BmpDC, nil, DCB_RESET or DCB_ENABLE); + SendMessage(Wnd, WM_PRINT, WPARAM(BmpDC), PRF_NONCLIENT or PRF_CLIENT or + PRF_ERASEBKGND or PRF_CHILDREN); + //GetBoundsRect + if Blending then begin + SetWindowLong(Wnd, GWL_EXSTYLE, GetWindowLong(Wnd, GWL_EXSTYLE) or WS_EX_LAYERED); + Time := 175; { actually more like ~147 because CurStep starts at 40 } + CurStep := 40; + Longint(Blend) := 0; + Blend.BlendOp := AC_SRC_OVER; + Blend.SourceConstantAlpha := CurStep; + UpdateLayeredWindowProc(Wnd, 0, @R.TopLeft, @Size, BmpDC, @ZeroPt, 0, + @Blend, ULW_ALPHA); + end + else begin + Time := 150; + CurStep := 0; + Rgn := CreateRectRgn(0, 0, 0, 0); + if not BOOL(SetWindowRgn(Wnd, Rgn, False)) then + DeleteObject(Rgn); { just in case } + end; + { These are the same flags AnimateWindow uses. SWP_ASYNCWINDOWPOS is + needed or else it doesn't "save bits" properly. + Note: SWP_ASYNCWINDOWPOS seems to have no effect on Windows 95 & NT 4.0, + so bits behind the window are not saved & restored correctly. } + SetWindowPos(Wnd, 0, 0, 0, 0, 0, SWP_NOSIZE or SWP_NOMOVE or + SWP_NOZORDER or SWP_NOACTIVATE or SWP_SHOWWINDOW or SWP_NOREDRAW or + SWP_NOOWNERZORDER or SWP_ASYNCWINDOWPOS); + end; + + AnimateThreadHandle := BeginThread(nil, 0, AnimateThreadFunc, @AnimateData, + CREATE_SUSPENDED, ThreadID); + if AnimateThreadHandle = 0 then begin + { just in case... } + FinalizeAnimation; + Exit; + end; + ResumeThread(AnimateThreadHandle); +end; + +procedure TBStepAnimation(const Msg: TMessage); +var + Rgn: HRGN; + Blend: TBlendFunction; + X, Y: Integer; +begin + if Msg.LParam <> AnimationSequenceID then + { ignore messages dangling in the queue from aborted animation sequences } + Exit; + with PAnimateThreadFuncData(@AnimateData)^ do begin + if not AnimationEnded then begin + if Blending then begin + Longint(Blend) := 0; + Blend.BlendOp := AC_SRC_OVER; + Blend.SourceConstantAlpha := AnimateData.CurStep; + UpdateLayeredWindowProc(Wnd, 0, nil, nil, 0, nil, 0, @Blend, ULW_ALPHA); + end + else begin + if tbadDown in Direction then + Y := MulDiv(Size.Y, AnimateData.CurStep, 255) - Size.Y + else if tbadUp in Direction then + Y := Size.Y - MulDiv(Size.Y, AnimateData.CurStep, 255) + else + Y := 0; + if tbadRight in Direction then + X := MulDiv(Size.X, AnimateData.CurStep, 255) - Size.X + else if tbadLeft in Direction then + X := Size.X - MulDiv(Size.X, AnimateData.CurStep, 255) + else + X := 0; + Rgn := CreateRectRgn(X, Y, X + Size.X, Y + Size.Y); + if not BOOL(SetWindowRgn(Wnd, Rgn, False)) then + DeleteObject(Rgn); { just in case } + BitBlt(DC, X, Y, Size.X, Size.Y, BmpDC, 0, 0, SRCCOPY); + end; + end + else + TBEndAnimation(Wnd); + StepMessagePending := False; + end; +end; + +initialization + UpdateLayeredWindowProc := GetProcAddress(GetModuleHandle(user32), + 'UpdateLayeredWindow'); +finalization + TBEndAnimation(0); +end. diff --git a/official/2.1.6+2.1.beta1/Source/TB2Common.pas b/official/2.1.6+2.1.beta1/Source/TB2Common.pas new file mode 100644 index 0000000..8255781 --- /dev/null +++ b/official/2.1.6+2.1.beta1/Source/TB2Common.pas @@ -0,0 +1,1087 @@ +unit TB2Common; + +{ + Toolbar2000 + Copyright (C) 1998-2005 by Jordan Russell + All rights reserved. + + The contents of this file are subject to the "Toolbar2000 License"; you may + not use or distribute this file except in compliance with the + "Toolbar2000 License". A copy of the "Toolbar2000 License" may be found in + TB2k-LICENSE.txt or at: + http://www.jrsoftware.org/files/tb2k/TB2k-LICENSE.txt + + Alternatively, the contents of this file may be used under the terms of the + GNU General Public License (the "GPL"), in which case the provisions of the + GPL are applicable instead of those in the "Toolbar2000 License". A copy of + the GPL may be found in GPL-LICENSE.txt or at: + http://www.jrsoftware.org/files/tb2k/GPL-LICENSE.txt + If you wish to allow use of your version of this file only under the terms of + the GPL and not to allow others to use your version of this file under the + "Toolbar2000 License", indicate your decision by deleting the provisions + above and replace them with the notice and other provisions required by the + GPL. If you do not delete the provisions above, a recipient may use your + version of this file under either the "Toolbar2000 License" or the GPL. + + $jrsoftware: tb2k/Source/TB2Common.pas,v 1.31 2005/06/29 20:10:10 jr Exp $ +} + +interface + +{$I TB2Ver.inc} + +uses + Windows, Classes, SysUtils, Messages, Controls, Forms; + +type + TListSortExCompare = function(const Item1, Item2, ExtraData: Pointer): Integer; + THandleWMPrintNCPaintProc = procedure(Wnd: HWND; DC: HDC; AppData: Longint); + +function AddToFrontOfList(var List: TList; Item: Pointer): Boolean; +function AddToList(var List: TList; Item: Pointer): Boolean; +function ApplicationIsActive: Boolean; +function AreFlatMenusEnabled: Boolean; +function AreKeyboardCuesEnabled: Boolean; +function CallTrackMouseEvent(const Wnd: HWND; const Flags: DWORD): Boolean; +function CreateHalftoneBrush: HBRUSH; +function CreateNullRegion: HRGN; +function CreateRotatedFont(DC: HDC): HFONT; +function DivRoundUp(const Dividend, Divisor: Integer): Integer; +procedure DrawHalftoneInvertRect(const DC: HDC; const NewRect, OldRect: PRect; + const NewSize, OldSize: TSize); +procedure DrawRotatedText(const DC: HDC; AText: String; const ARect: TRect; + const AFormat: Cardinal); +procedure DrawInvertRect(const DC: HDC; const NewRect, OldRect: PRect; + const NewSize, OldSize: TSize; const Brush: HBRUSH; BrushLast: HBRUSH); +function EscapeAmpersands(const S: String): String; +function FindAccelChar(const S: String): Char; +{$IFNDEF JR_D5} +procedure FreeAndNil(var Obj); +{$ENDIF} +function GetInputLocaleCodePage: UINT; +function GetMenuShowDelay: Integer; +function GetRectOfMonitorContainingPoint(const P: TPoint; const WorkArea: Boolean): TRect; +function GetRectOfMonitorContainingRect(const R: TRect; const WorkArea: Boolean): TRect; +function GetRectOfMonitorContainingWindow(const W: HWND; const WorkArea: Boolean): TRect; +function GetRectOfPrimaryMonitor(const WorkArea: Boolean): TRect; +function GetTextHeight(const DC: HDC): Integer; +function GetTextWidth(const DC: HDC; S: String; const Prefix: Boolean): Integer; +procedure HandleWMPrint(const Wnd: HWND; var Message: TMessage; + const NCPaintFunc: THandleWMPrintNCPaintProc; const AppData: Longint); +procedure HandleWMPrintClient(const Control: TWinControl; + var Message: TMessage); +function IsWindowsXP: Boolean; +procedure ListSortEx(const List: TList; const Compare: TListSortExCompare; + const ExtraData: Pointer); +procedure InitTrackMouseEvent; +function Max(A, B: Integer): Integer; +function Min(A, B: Integer): Integer; +function MethodsEqual(const M1, M2: TMethod): Boolean; +function NeedToPlaySound(const Alias: String): Boolean; +procedure ProcessPaintMessages; +procedure RemoveMessages(const AMin, AMax: Integer); +procedure RemoveFromList(var List: TList; Item: Pointer); +procedure SelectNCUpdateRgn(Wnd: HWND; DC: HDC; Rgn: HRGN); +function StripAccelChars(const S: String): String; +function StripTrailingPunctuation(const S: String): String; +function UsingMultipleMonitors: Boolean; + +const + PopupMenuWindowNCSize = 3; + DT_HIDEPREFIX = $00100000; + +var + TrackMouseEventFunc: function(var EventTrack: TTrackMouseEvent): BOOL; stdcall; + +implementation + +uses + TB2Version; + +function ApplicationIsActive: Boolean; +{ Returns True if the application is in the foreground } +begin + Result := GetActiveWindow <> 0; +end; + +{$IFNDEF JR_D3} +function CopyPalette(Palette: HPALETTE): HPALETTE; +var + PaletteSize: Integer; + LogPal: TMaxLogPalette; +begin + Result := 0; + if Palette = 0 then Exit; + PaletteSize := 0; + if GetObject(Palette, SizeOf(PaletteSize), @PaletteSize) = 0 then Exit; + if PaletteSize = 0 then Exit; + with LogPal do begin + palVersion := $0300; + palNumEntries := PaletteSize; + GetPaletteEntries(Palette, 0, PaletteSize, palPalEntry); + end; + Result := CreatePalette(PLogPalette(@LogPal)^); +end; +{$ENDIF} + +procedure ListSortEx(const List: TList; const Compare: TListSortExCompare; + const ExtraData: Pointer); +{ Similar to TList.Sort, but lets you pass a user-defined ExtraData pointer } + procedure QuickSortEx(L: Integer; const R: Integer); + var + I, J: Integer; + P: Pointer; + begin + repeat + I := L; + J := R; + P := List[(L + R) shr 1]; + repeat + while Compare(List[I], P, ExtraData) < 0 do Inc(I); + while Compare(List[J], P, ExtraData) > 0 do Dec(J); + if I <= J then + begin + List.Exchange(I, J); + Inc(I); + Dec(J); + end; + until I > J; + if L < J then QuickSortEx(L, J); + L := I; + until I >= R; + end; +begin + if List.Count > 1 then + QuickSortEx(0, List.Count-1); +end; + +type + PPrintEnumProcData = ^TPrintEnumProcData; + TPrintEnumProcData = record + PrintChildren: Boolean; + ParentWnd: HWND; + DC: HDC; + PrintFlags: LPARAM; + end; + +function PrintEnumProc(Wnd: HWND; LParam: LPARAM): BOOL; stdcall; +var + R: TRect; + SaveIndex: Integer; +begin + Result := True; { continue enumerating } + with PPrintEnumProcData(LParam)^ do begin + { Skip window if it isn't a child/owned window of ParentWnd or isn't visible } + if (HWND(GetWindowLong(Wnd, GWL_HWNDPARENT)) <> ParentWnd) or + (GetWindowLong(Wnd, GWL_STYLE) and WS_VISIBLE = 0) then + { ^ don't use IsWindowVisible since it returns False if the window's + parent window is not visible } + Exit; + GetWindowRect(Wnd, R); + MapWindowPoints(0, ParentWnd, R, 2); + SaveIndex := SaveDC(DC); + { Like Windows, offset the window origin to the top-left coordinates of + the child/owned window } + MoveWindowOrg(DC, R.Left, R.Top); + { Like Windows, intersect the clipping region with the entire rectangle of + the child/owned window } + OffsetRect(R, -R.Left, -R.Top); + IntersectClipRect(DC, R.Left, R.Top, R.Right, R.Bottom); + { Send a WM_PRINT message to the child/owned window } + SendMessage(Wnd, WM_PRINT, WPARAM(DC), PrintFlags); + { Restore the DC's state, in case the WM_PRINT handler didn't put things + back the way it found them } + RestoreDC(DC, SaveIndex); + end; +end; + +procedure HandleWMPrint(const Wnd: HWND; var Message: TMessage; + const NCPaintFunc: THandleWMPrintNCPaintProc; const AppData: Longint); +{ note: AppData is an application-defined value which is passed to NCPaintFunc } +var + DC: HDC; + SaveIndex, SaveIndex2: Integer; + R: TRect; + P: TPoint; + Data: TPrintEnumProcData; +begin + if (Message.LParam and PRF_CHECKVISIBLE = 0) or IsWindowVisible(Wnd) then begin + DC := HDC(Message.WParam); + SaveIndex2 := SaveDC(DC); + try + if Message.LParam and PRF_NONCLIENT <> 0 then begin + SaveIndex := SaveDC(DC); + if Assigned(NCPaintFunc) then + NCPaintFunc(Wnd, DC, AppData); + RestoreDC(DC, SaveIndex); + end; + { Calculate the difference between the top-left corner of the window + and the top-left corner of its client area } + GetWindowRect(Wnd, R); + P.X := 0; P.Y := 0; + ClientToScreen(Wnd, P); + Dec(P.X, R.Left); Dec(P.Y, R.Top); + if Message.LParam and PRF_CLIENT <> 0 then begin + { Like Windows, the flags PRF_ERASEBKGND, PRF_CHILDREN, and PRF_OWNED + are ignored if PRF_CLIENT isn't also specified } + if Message.LParam and PRF_ERASEBKGND <> 0 then begin + { Send WM_ERASEBKGND } + SaveIndex := SaveDC(DC); + if Message.LParam and PRF_NONCLIENT <> 0 then + MoveWindowOrg(DC, P.X, P.Y); + SendMessage(Wnd, WM_ERASEBKGND, Message.WParam, 0); + RestoreDC(DC, SaveIndex); + end; + { Send WM_PRINTCLIENT } + SaveIndex := SaveDC(DC); + if Message.LParam and PRF_NONCLIENT <> 0 then + MoveWindowOrg(DC, P.X, P.Y); + SendMessage(Wnd, WM_PRINTCLIENT, Message.WParam, 0); + RestoreDC(DC, SaveIndex); + { Like Windows, always offset child/owned windows by the size of the + client area even if PRF_NONCLIENT isn't specified (a bug?) } + MoveWindowOrg(DC, P.X, P.Y); + Data.ParentWnd := Wnd; + Data.DC := DC; + { Send WM_PRINT to child/owned windows } + if Message.LParam and PRF_CHILDREN <> 0 then begin + Data.PrintChildren := True; + Data.PrintFlags := PRF_NONCLIENT or PRF_CLIENT or PRF_ERASEBKGND or + PRF_CHILDREN; { same flags as Windows passes to children } + EnumChildWindows(Wnd, @PrintEnumProc, LPARAM(@Data)); + end; + if Message.LParam and PRF_OWNED <> 0 then begin + Data.PrintChildren := False; + Data.PrintFlags := Message.LParam; + EnumWindows(@PrintEnumProc, LPARAM(@Data)); + end; + end; + finally + RestoreDC(DC, SaveIndex2); + end; + end; + { Windows' WM_PRINT returns 1. I'm not sure why. } + Message.Result := 1; +end; + +type + TWinControlAccess = class(TWinControl); + +procedure HandleWMPrintClient(const Control: TWinControl; var Message: TMessage); +var + Msg: TWMPaint; + SaveIndex: Integer; +begin + Msg.Msg := WM_PAINT; + Msg.DC := HDC(Message.WParam); + Msg.Unused := 0; + Msg.Result := 0; + SaveIndex := SaveDC(HDC(Message.WParam)); + try + TWinControlAccess(Control).PaintHandler(Msg); + finally + RestoreDC(HDC(Message.WParam), SaveIndex); + end; +end; + +function DivRoundUp(const Dividend, Divisor: Integer): Integer; +{ Similar to the 'div' operator, but if there is a remainder it always rounds + the result up one (or down if the result is negative). } +asm + mov ecx, edx + cdq + idiv ecx + test edx, edx + jz @@1 + test eax, eax + jns @@2 + dec eax + jmp @@1 + @@2: + inc eax + @@1: +end; + +function GetTextHeight(const DC: HDC): Integer; +var + TextMetric: TTextMetric; +begin + GetTextMetrics(DC, TextMetric); + Result := TextMetric.tmHeight; +end; + +function StripAccelChars(const S: String): String; +var + I: Integer; +begin + Result := S; + I := 1; + while I <= Length(Result) do begin + if not(Result[I] in LeadBytes) then begin + if Result[I] = '&' then + System.Delete(Result, I, 1); + Inc(I); + end + else + Inc(I, 2); + end; +end; + +function EscapeAmpersands(const S: String): String; +{ Replaces any '&' characters with '&&' } +var + I: Integer; +begin + Result := S; + I := 1; + while I <= Length(Result) do begin + if not(Result[I] in LeadBytes) then begin + if Result[I] = '&' then begin + Inc(I); + Insert('&', Result, I); + end; + Inc(I); + end + else + Inc(I, 2); + end; +end; + +function StripTrailingPunctuation(const S: String): String; +{ Removes any colon (':') or ellipsis ('...') from the end of S and returns + the resulting string } +var + L: Integer; +begin + Result := S; + L := Length(Result); + if (L > 1) and (Result[L] = ':') and (ByteType(Result, L) = mbSingleByte) then + SetLength(Result, L-1) + else if (L > 3) and (Result[L-2] = '.') and (Result[L-1] = '.') and + (Result[L] = '.') and (ByteType(Result, L-2) = mbSingleByte) then + SetLength(Result, L-3); +end; + +function GetTextWidth(const DC: HDC; S: String; const Prefix: Boolean): Integer; +{ Returns the width of the specified string using the font currently selected + into DC. If Prefix is True, it first removes "&" characters as necessary. } +var + Size: TSize; +begin + { This procedure is 10x faster than using DrawText with the DT_CALCRECT flag } + if Prefix then + S := StripAccelChars(S); + GetTextExtentPoint32(DC, PChar(S), Length(S), Size); + Result := Size.cx; +end; + +procedure ProcessPaintMessages; +{ Dispatches all pending WM_PAINT messages. In effect, this is like an + 'UpdateWindow' on all visible windows } +var + Msg: TMsg; +begin + while PeekMessage(Msg, 0, WM_PAINT, WM_PAINT, PM_NOREMOVE) do begin + case Integer(GetMessage(Msg, 0, WM_PAINT, WM_PAINT)) of + -1: Break; { if GetMessage failed } + 0: begin + { Repost WM_QUIT messages } + PostQuitMessage(Msg.WParam); + Break; + end; + end; + DispatchMessage(Msg); + end; +end; + +procedure RemoveMessages(const AMin, AMax: Integer); +{ Removes any messages with the specified ID from the queue } +var + Msg: TMsg; +begin + while PeekMessage(Msg, 0, AMin, AMax, PM_REMOVE) do begin + if Msg.message = WM_QUIT then begin + { Repost WM_QUIT messages } + PostQuitMessage(Msg.WParam); + Break; + end; + end; +end; + +procedure SelectNCUpdateRgn(Wnd: HWND; DC: HDC; Rgn: HRGN); +var + R: TRect; + NewClipRgn: HRGN; +begin + if (Rgn <> 0) and (Rgn <> 1) then begin + GetWindowRect(Wnd, R); + if SelectClipRgn(DC, Rgn) = ERROR then begin + NewClipRgn := CreateRectRgnIndirect(R); + SelectClipRgn(DC, NewClipRgn); + DeleteObject(NewClipRgn); + end; + OffsetClipRgn(DC, -R.Left, -R.Top); + end; +end; + +function AddToList(var List: TList; Item: Pointer): Boolean; +{ Returns True if Item didn't already exist in the list } +begin + if List = nil then + List := TList.Create; + Result := List.IndexOf(Item) = -1; + if Result then + List.Add(Item); +end; + +function AddToFrontOfList(var List: TList; Item: Pointer): Boolean; +{ Returns True if Item didn't already exist in the list } +begin + if List = nil then + List := TList.Create; + Result := List.IndexOf(Item) = -1; + if Result then + List.Insert(0, Item); +end; + +procedure RemoveFromList(var List: TList; Item: Pointer); +begin + if Assigned(List) then begin + List.Remove(Item); + if List.Count = 0 then begin + List.Free; + List := nil; + end; + end; +end; + +var + RegMenuShowDelay: Integer; + RegMenuShowDelayInited: BOOL = False; +function GetMenuShowDelay: Integer; +const + DefaultMenuShowDelay = 400; + function ReadMenuShowDelayFromRegistry: Integer; + var + K: HKEY; + Typ, DataSize: DWORD; + Data: array[0..31] of Char; + Res: Longint; + E: Integer; + begin + Result := DefaultMenuShowDelay; + if RegOpenKeyEx(HKEY_CURRENT_USER, 'Control Panel\Desktop', 0, + KEY_QUERY_VALUE, K) = ERROR_SUCCESS then begin + DataSize := SizeOf(Data); + Res := RegQueryValueEx(K, 'MenuShowDelay', nil, @Typ, @Data, @DataSize); + RegCloseKey(K); + if Res <> ERROR_FILE_NOT_FOUND then begin + if (Res <> ERROR_SUCCESS) or (Typ <> REG_SZ) then + Result := 0 + else begin + Val(Data, Result, E); + if E <> 0 then Result := 0; + end; + end; + end; + end; +begin + if Lo(GetVersion) >= 4 then begin + if not SystemParametersInfo(106{SPI_GETMENUSHOWDELAY}, 0, @Result, 0) then begin + { SPI_GETMENUSHOWDELAY is only supported by Windows NT 4.0 and Windows 98. + On Windows 95, it must use the registry to retrieve this setting. } + if not RegMenuShowDelayInited then begin + RegMenuShowDelay := ReadMenuShowDelayFromRegistry; + InterlockedExchange(Integer(RegMenuShowDelayInited), Ord(True)); + end; + Result := RegMenuShowDelay; + end; + if Result < 0 then Result := 0; + end + else + Result := DefaultMenuShowDelay; +end; + +function AreFlatMenusEnabled: Boolean; +{ Returns True if "flat menus" are enabled. Always returns False on pre-XP + Windows versions. } +const + SPI_GETFLATMENU = $1022; +var + FlatMenusEnabled: BOOL; +begin + { Interestingly, on Windows 2000, SystemParametersInfo(SPI_GETFLATMENU, ...) + succeeds and can return True in pvParam^ if the proper bit is set in + UserPreferencesMask. Since flat menus are not really used on Windows + 2000, call IsWindowsXP first to see if we're running at least XP. } + Result := IsWindowsXP and SystemParametersInfo(SPI_GETFLATMENU, 0, + @FlatMenusEnabled, 0) and FlatMenusEnabled; +end; + +function AreKeyboardCuesEnabled: Boolean; +{ Returns True if "keyboard cues" are enabled. Always returns True on + pre-2000 Windows versions. } +const + SPI_GETKEYBOARDCUES = $100A; +var + CuesEnabled: BOOL; +begin + Result := (Win32MajorVersion < 5) or + not SystemParametersInfo(SPI_GETKEYBOARDCUES, 0, @CuesEnabled, 0) or + CuesEnabled; +end; + +function CreateNullRegion: HRGN; +var + R: TRect; +begin + SetRectEmpty(R); + Result := CreateRectRgnIndirect(R); +end; + +procedure DrawInvertRect(const DC: HDC; const NewRect, OldRect: PRect; + const NewSize, OldSize: TSize; const Brush: HBRUSH; BrushLast: HBRUSH); +{ Draws a dragging outline, hiding the old one if neccessary. This code is + based on MFC sources. + + Either NewRect or OldRect can be nil or empty. } +var + SaveIndex: Integer; + rgnNew, rgnOutside, rgnInside, rgnLast, rgnUpdate: HRGN; + R: TRect; +begin + rgnLast := 0; + rgnUpdate := 0; + + { First, determine the update region and select it } + if NewRect = nil then begin + SetRectEmpty(R); + rgnOutside := CreateRectRgnIndirect(R); + end + else begin + R := NewRect^; + rgnOutside := CreateRectRgnIndirect(R); + InflateRect(R, -NewSize.cx, -NewSize.cy); + IntersectRect(R, R, NewRect^); + end; + rgnInside := CreateRectRgnIndirect(R); + rgnNew := CreateNullRegion; + CombineRgn(rgnNew, rgnOutside, rgnInside, RGN_XOR); + + if BrushLast = 0 then + BrushLast := Brush; + + if OldRect <> nil then begin + { Find difference between new region and old region } + rgnLast := CreateNullRegion; + with OldRect^ do + SetRectRgn(rgnOutside, Left, Top, Right, Bottom); + R := OldRect^; + InflateRect(R, -OldSize.cx, -OldSize.cy); + IntersectRect(R, R, OldRect^); + SetRectRgn(rgnInside, R.Left, R.Top, R.Right, R.Bottom); + CombineRgn(rgnLast, rgnOutside, rgnInside, RGN_XOR); + + { Only diff them if brushes are the same } + if Brush = BrushLast then begin + rgnUpdate := CreateNullRegion; + CombineRgn(rgnUpdate, rgnLast, rgnNew, RGN_XOR); + end; + end; + + { Save the DC state so that the clipping region can be restored } + SaveIndex := SaveDC(DC); + try + if (Brush <> BrushLast) and (OldRect <> nil) then begin + { Brushes are different -- erase old region first } + SelectClipRgn(DC, rgnLast); + GetClipBox(DC, R); + SelectObject(DC, BrushLast); + PatBlt(DC, R.Left, R.Top, R.Right-R.Left, R.Bottom-R.Top, PATINVERT); + end; + + { Draw into the update/new region } + if rgnUpdate <> 0 then + SelectClipRgn(DC, rgnUpdate) + else + SelectClipRgn(DC, rgnNew); + GetClipBox(DC, R); + SelectObject(DC, Brush); + PatBlt(DC, R.Left, R.Top, R.Right-R.Left, R.Bottom-R.Top, PATINVERT); + finally + { Clean up DC } + RestoreDC(DC, SaveIndex); + end; + + { Free regions } + if rgnNew <> 0 then DeleteObject(rgnNew); + if rgnOutside <> 0 then DeleteObject(rgnOutside); + if rgnInside <> 0 then DeleteObject(rgnInside); + if rgnLast <> 0 then DeleteObject(rgnLast); + if rgnUpdate <> 0 then DeleteObject(rgnUpdate); +end; + +function CreateHalftoneBrush: HBRUSH; +const + Patterns: array[Boolean] of Word = ($5555, $AAAA); +var + I: Integer; + GrayPattern: array[0..7] of Word; + GrayBitmap: HBITMAP; +begin + for I := 0 to 7 do + GrayPattern[I] := Patterns[Odd(I)]; + GrayBitmap := CreateBitmap(8, 8, 1, 1, @GrayPattern); + Result := CreatePatternBrush(GrayBitmap); + DeleteObject(GrayBitmap); +end; + +procedure DrawHalftoneInvertRect(const DC: HDC; const NewRect, OldRect: PRect; + const NewSize, OldSize: TSize); +var + Brush: HBRUSH; +begin + Brush := CreateHalftoneBrush; + try + DrawInvertRect(DC, NewRect, OldRect, NewSize, OldSize, Brush, Brush); + finally + DeleteObject(Brush); + end; +end; + +function MethodsEqual(const M1, M2: TMethod): Boolean; +begin + Result := (M1.Code = M2.Code) and (M1.Data = M2.Data); +end; + +function GetRectOfPrimaryMonitor(const WorkArea: Boolean): TRect; +begin + if not WorkArea or not SystemParametersInfo(SPI_GETWORKAREA, 0, @Result, 0) then + Result := Rect(0, 0, Screen.Width, Screen.Height); +end; + +function UsingMultipleMonitors: Boolean; +{ Returns True if the system has more than one display monitor configured. } +var + NumMonitors: Integer; +begin + NumMonitors := GetSystemMetrics(80 {SM_CMONITORS}); + Result := (NumMonitors <> 0) and (NumMonitors <> 1); + { ^ NumMonitors will be zero if not running Win98, NT 5, or later } +end; + +type + HMONITOR = type Integer; + PMonitorInfoA = ^TMonitorInfoA; + TMonitorInfoA = record + cbSize: DWORD; + rcMonitor: TRect; + rcWork: TRect; + dwFlags: DWORD; + end; +const + MONITOR_DEFAULTTONEAREST = $2; +type + TMultiMonApis = record + funcMonitorFromRect: function(lprcScreenCoords: PRect; dwFlags: DWORD): HMONITOR; stdcall; + funcMonitorFromPoint: function(ptScreenCoords: TPoint; dwFlags: DWORD): HMONITOR; stdcall; + funcMonitorFromWindow: function(hWnd: HWND; dwFlags: DWORD): HMONITOR; stdcall; + funcGetMonitorInfoA: function(hMonitor: HMONITOR; lpMonitorInfo: PMonitorInfoA): BOOL; stdcall; + end; + +{ Under D4 I could be using the MultiMon unit for the multiple monitor + function imports, but its stubs for MonitorFromRect and MonitorFromPoint + are seriously bugged... So I chose to avoid the MultiMon unit entirely. } + +function InitMultiMonApis(var Apis: TMultiMonApis): Boolean; +var + User32Handle: THandle; +begin + User32Handle := GetModuleHandle(user32); + Apis.funcMonitorFromRect := GetProcAddress(User32Handle, 'MonitorFromRect'); + Apis.funcMonitorFromPoint := GetProcAddress(User32Handle, 'MonitorFromPoint'); + Apis.funcMonitorFromWindow := GetProcAddress(User32Handle, 'MonitorFromWindow'); + Apis.funcGetMonitorInfoA := GetProcAddress(User32Handle, 'GetMonitorInfoA'); + Result := Assigned(Apis.funcMonitorFromRect) and + Assigned(Apis.funcMonitorFromPoint) and Assigned(Apis.funcGetMonitorInfoA); +end; + +function GetRectOfMonitorContainingRect(const R: TRect; + const WorkArea: Boolean): TRect; +{ Returns the work area of the monitor which the rectangle R intersects with + the most, or the monitor nearest R if no monitors intersect. } +var + Apis: TMultiMonApis; + M: HMONITOR; + MonitorInfo: TMonitorInfoA; +begin + if UsingMultipleMonitors and InitMultiMonApis(Apis) then begin + M := Apis.funcMonitorFromRect(@R, MONITOR_DEFAULTTONEAREST); + MonitorInfo.cbSize := SizeOf(MonitorInfo); + if Apis.funcGetMonitorInfoA(M, @MonitorInfo) then begin + if not WorkArea then + Result := MonitorInfo.rcMonitor + else + Result := MonitorInfo.rcWork; + Exit; + end; + end; + Result := GetRectOfPrimaryMonitor(WorkArea); +end; + +function GetRectOfMonitorContainingPoint(const P: TPoint; + const WorkArea: Boolean): TRect; +{ Returns the screen area of the monitor containing the point P, or the monitor + nearest P if P isn't in any monitor's work area. } +var + Apis: TMultiMonApis; + M: HMONITOR; + MonitorInfo: TMonitorInfoA; +begin + if UsingMultipleMonitors and InitMultiMonApis(Apis) then begin + M := Apis.funcMonitorFromPoint(P, MONITOR_DEFAULTTONEAREST); + MonitorInfo.cbSize := SizeOf(MonitorInfo); + if Apis.funcGetMonitorInfoA(M, @MonitorInfo) then begin + if not WorkArea then + Result := MonitorInfo.rcMonitor + else + Result := MonitorInfo.rcWork; + Exit; + end; + end; + Result := GetRectOfPrimaryMonitor(WorkArea); +end; + +function GetRectOfMonitorContainingWindow(const W: HWND; + const WorkArea: Boolean): TRect; +var + Apis: TMultiMonApis; + M: HMONITOR; + MonitorInfo: TMonitorInfoA; +begin + if UsingMultipleMonitors and InitMultiMonApis(Apis) then begin + M := Apis.funcMonitorFromWindow(W, MONITOR_DEFAULTTONEAREST); + MonitorInfo.cbSize := SizeOf(MonitorInfo); + if Apis.funcGetMonitorInfoA(M, @MonitorInfo) then begin + if not WorkArea then + Result := MonitorInfo.rcMonitor + else + Result := MonitorInfo.rcWork; + Exit; + end; + end; + Result := GetRectOfPrimaryMonitor(WorkArea); +end; + +var + TrackMouseEventInited: BOOL; + +procedure InitTrackMouseEvent; +var + TrackMouseEventComCtlModule: THandle; +begin + { First look for TrackMouseEvent which is available on Windows 98 & NT 4 only. + If it doesn't exist, look for _TrackMouseEvent which is available on + Windows 95 if IE 3.0 or later is installed. } + if not TrackMouseEventInited then begin + TrackMouseEventFunc := GetProcAddress(GetModuleHandle(user32), + 'TrackMouseEvent'); + if @TrackMouseEventFunc = nil then begin + TrackMouseEventComCtlModule := + {$IFDEF JR_D5} SafeLoadLibrary {$ELSE} LoadLibrary {$ENDIF} (comctl32); + if TrackMouseEventComCtlModule <> 0 then + TrackMouseEventFunc := GetProcAddress(TrackMouseEventComCtlModule, + '_TrackMouseEvent'); + end; + InterlockedExchange(Integer(TrackMouseEventInited), Ord(True)); + end; +end; + +function CallTrackMouseEvent(const Wnd: HWND; const Flags: DWORD): Boolean; +var + Track: TTrackMouseEvent; +begin + Result := False; + if Assigned(TrackMouseEventFunc) then begin + Track.cbSize := SizeOf(Track); + Track.dwFlags := Flags; + Track.hwndTrack := Wnd; + Track.dwHoverTime := 0; + Result := TrackMouseEventFunc(Track); + end; +end; + +{$IFNDEF JR_D5} +procedure FreeAndNil(var Obj); +var + P: TObject; +begin + P := TObject(Obj); + TObject(Obj) := nil; + P.Free; +end; +{$ENDIF} + +function EnumFontsProc(const lplf: TLogFont; const lptm: TTextMetric; + dwType: DWORD; lpData: LPARAM): Integer; stdcall; +begin + Boolean(Pointer(lpData)^) := True; + Result := 0; +end; + +function CreateRotatedFont(DC: HDC): HFONT; +{ Creates a font based on the DC's current font, but rotated 270 degrees } +var + LogFont: TLogFont; + TM: TTextMetric; + VerticalFontName: array[0..LF_FACESIZE-1] of Char; + VerticalFontExists: Boolean; +begin + if GetObject(GetCurrentObject(DC, OBJ_FONT), SizeOf(LogFont), + @LogFont) = 0 then begin + { just in case... } + Result := 0; + Exit; + end; + LogFont.lfEscapement := 2700; + LogFont.lfOrientation := 2700; + LogFont.lfOutPrecision := OUT_TT_ONLY_PRECIS; { needed for Win9x } + + { Don't let a random TrueType font be substituted when MS Sans Serif or + Microsoft Sans Serif are used. Hard-code Arial. } + if (StrIComp(LogFont.lfFaceName, 'MS Sans Serif') = 0) or + (StrIComp(LogFont.lfFaceName, 'Microsoft Sans Serif') = 0) then begin + StrPCopy(LogFont.lfFaceName, 'Arial'); + { Set lfHeight to the actual height of the current font. This is needed + to work around a Windows 98 issue: on a clean install of the OS, + SPI_GETNONCLIENTMETRICS returns -5 for lfSmCaptionFont.lfHeight. This is + wrong; it should return -11 for an 8 pt font. With normal, unrotated text + this actually displays correctly, since MS Sans Serif doesn't support + sizes below 8 pt. However, when we change to a TrueType font like Arial, + this becomes a problem because it'll actually create a font that small. } + if GetTextMetrics(DC, TM) then begin + { If the original height was negative, keep it negative } + if LogFont.lfHeight <= 0 then + LogFont.lfHeight := -(TM.tmHeight - TM.tmInternalLeading) + else + LogFont.lfHeight := TM.tmHeight; + end; + end; + + { Use a vertical font if available so that Asian characters aren't drawn + sideways } + if StrLen(LogFont.lfFaceName) < SizeOf(VerticalFontName)-1 then begin + VerticalFontName[0] := '@'; + StrCopy(@VerticalFontName[1], LogFont.lfFaceName); + VerticalFontExists := False; + EnumFonts(DC, VerticalFontName, @EnumFontsProc, @VerticalFontExists); + if VerticalFontExists then + StrCopy(LogFont.lfFaceName, VerticalFontName); + end; + + Result := CreateFontIndirect(LogFont); +end; + +procedure DrawRotatedText(const DC: HDC; AText: String; const ARect: TRect; + const AFormat: Cardinal); +{ Like DrawText, but draws the text at a 270 degree angle. + The format flag this function respects are + DT_NOPREFIX, DT_HIDEPREFIX, DT_CENTER, DT_END_ELLIPSIS, DT_NOCLIP } +var + RotatedFont, SaveFont: HFONT; + TextMetrics: TTextMetric; + X, Y, P, I, SU, FU, W: Integer; + SaveAlign: UINT; + SavePen, Pen: HPEN; + Clip: Boolean; + + function GetSize(DC: HDC; const S: string): Integer; + var + Size: TSize; + begin + GetTextExtentPoint32(DC, PChar(S), Length(S), Size); + Result := Size.cx; + end; + +begin + if Length(AText) = 0 then Exit; + + RotatedFont := CreateRotatedFont(DC); + SaveFont := SelectObject(DC, RotatedFont); + + GetTextMetrics(DC, TextMetrics); + X := ARect.Left + ((ARect.Right - ARect.Left) - TextMetrics.tmHeight) div 2; + + Clip := (AFormat and DT_NOCLIP) <> DT_NOCLIP; + + { Find the index of the character that should be underlined. Delete '&' + characters from the string. Like DrawText, only the last prefixed character + will be underlined. } + P := 0; + I := 1; + if (AFormat and DT_NOPREFIX) <> DT_NOPREFIX then + while I <= Length(AText) do begin + if AText[I] in LeadBytes then + Inc(I) + else if AText[I] = '&' then begin + Delete(AText, I, 1); + { Note: PChar cast is so that if Delete deleted the last character in + the string, we don't step past the end of the string (which would cause + an AV if AText is now empty), but rather look at the null character + and treat it as an accelerator key like DrawText. } + if PChar(AText)[I-1] <> '&' then + P := I; + end; + Inc(I); + end; + + if (AFormat and DT_END_ELLIPSIS) = DT_END_ELLIPSIS then + begin + if (Length(AText) > 1) and (GetSize(DC, AText) > ARect.Bottom - ARect.Top) then + begin + W := ARect.Bottom - ARect.Top; + if W > 2 then + begin + Delete(AText, Length(AText), 1); + while (Length(AText) > 1) and (GetSize(DC, AText + '...') > W) do + Delete(AText, Length(AText), 1); + end + else AText := AText[1]; + if P > Length(AText) then P := 0; + AText := AText + '...'; + end; + end; + + if (AFormat and DT_CENTER) = DT_CENTER then + Y := ARect.Top + ((ARect.Bottom - ARect.Top) - GetSize(DC, AText)) div 2 + else + Y := ARect.Top; + + if Clip then + begin + SaveDC(DC); + with ARect do IntersectClipRect(DC, Left, Top, Right, Bottom); + end; + + SaveAlign := SetTextAlign(DC, TA_BOTTOM); + TextOut(DC, X, Y, PChar(AText), Length(AText)); + SetTextAlign(DC, SaveAlign); + { Underline } + if (P > 0) and (AFormat and DT_HIDEPREFIX = 0) then begin + SU := GetTextWidth(DC, Copy(AText, 1, P-1), False); + FU := SU + GetTextWidth(DC, PChar(AText)[P-1], False); + Inc(X, TextMetrics.tmDescent - 2); + Pen := CreatePen(PS_SOLID, 1, GetTextColor(DC)); + SavePen := SelectObject(DC, Pen); + MoveToEx(DC, X, Y + SU, nil); + LineTo(DC, X, Y + FU); + SelectObject(DC, SavePen); + DeleteObject(Pen); + end; + + if Clip then RestoreDC(DC, -1); + + SelectObject(DC, SaveFont); + DeleteObject(RotatedFont); +end; + +function NeedToPlaySound(const Alias: String): Boolean; +{ This function checks the registry to see if the specified sound event alias + is assigned to a file. + The purpose of having this function is so it can avoid calls to PlaySound if + possible, because on Windows 2000 there is an annoying 1/3 second delay on + the first call to PlaySound. + Windows Explorer actually uses this same technique when playing sounds for + the Start menu. } +var + K: HKEY; + Data: array[0..3] of WideChar; + DataSize: DWORD; + ErrorCode: Longint; +begin + if (Win32MajorVersion < 5) or (Win32Platform <> VER_PLATFORM_WIN32_NT) then begin + { No need to check pre-Windows 2000 versions since their PlaySound + functions don't have the delay; always return True. } + Result := True; + Exit; + end; + Result := False; + if RegOpenKeyEx(HKEY_CURRENT_USER, + PChar('AppEvents\Schemes\Apps\.Default\' + Alias + '\.Current'), + 0, KEY_QUERY_VALUE, K) = ERROR_SUCCESS then begin + DataSize := SizeOf(Data); + { Note: Use the 'W' version of RegQueryValueEx for more speed } + ErrorCode := RegQueryValueExW(K, nil, nil, nil, @Data, @DataSize); + if ((ErrorCode = ERROR_SUCCESS) and (Data[0] <> #0)) or + (ErrorCode = ERROR_MORE_DATA) then + Result := True; + RegCloseKey(K); + end; +end; + +function Max(A, B: Integer): Integer; +begin + if A >= B then + Result := A + else + Result := B; +end; + +function Min(A, B: Integer): Integer; +begin + if A <= B then + Result := A + else + Result := B; +end; + +function FindAccelChar(const S: String): Char; +{ Finds the last accelerator key in S. Returns #0 if no accelerator key was + found. '&&' is ignored. } +var + P: PChar; +begin + P := PChar(S); + Result := #0; + while True do begin + P := AnsiStrScan(P, '&'); + if P = nil then Break; + Inc(P); + if P^ <> '&' then begin + if P^ = #0 then Break; + Result := P^; + end; + Inc(P); + end; +end; + +function IsWindowsXP: Boolean; +begin + Result := (Win32Platform = VER_PLATFORM_WIN32_NT) and + ((Win32MajorVersion > 5) or + ((Win32MajorVersion = 5) and (Win32MinorVersion >= 1))); +end; + +function GetInputLocaleCodePage: UINT; +{ Returns the code page identifier of the active input locale, or CP_ACP if + for some unknown reason it couldn't be determined. } +var + Buf: array[0..15] of Char; + ErrorCode: Integer; +begin + if GetLocaleInfo(GetKeyboardLayout(0) and $FFFF, LOCALE_IDEFAULTANSICODEPAGE, + Buf, SizeOf(Buf)) > 0 then begin + Buf[High(Buf)] := #0; { ensure null termination, just in case... } + Val(Buf, Result, ErrorCode); + { Just to be *completely* safe, verify that the code page returned by + GetLocaleInfo actually exists. The result of this function may be fed + into WideCharToMultiByte, and we don't want WideCharToMultiByte to fail + entirely because of a bad code page. } + if (ErrorCode <> 0) or not IsValidCodePage(Result) then + Result := CP_ACP; + end + else + Result := CP_ACP; +end; + +end. diff --git a/official/2.1.6+2.1.beta1/Source/TB2Common.pas.orig b/official/2.1.6+2.1.beta1/Source/TB2Common.pas.orig new file mode 100644 index 0000000..b755a56 --- /dev/null +++ b/official/2.1.6+2.1.beta1/Source/TB2Common.pas.orig @@ -0,0 +1,1043 @@ +unit TB2Common; + +{ + Toolbar2000 + Copyright (C) 1998-2005 by Jordan Russell + All rights reserved. + + The contents of this file are subject to the "Toolbar2000 License"; you may + not use or distribute this file except in compliance with the + "Toolbar2000 License". A copy of the "Toolbar2000 License" may be found in + TB2k-LICENSE.txt or at: + http://www.jrsoftware.org/files/tb2k/TB2k-LICENSE.txt + + Alternatively, the contents of this file may be used under the terms of the + GNU General Public License (the "GPL"), in which case the provisions of the + GPL are applicable instead of those in the "Toolbar2000 License". A copy of + the GPL may be found in GPL-LICENSE.txt or at: + http://www.jrsoftware.org/files/tb2k/GPL-LICENSE.txt + If you wish to allow use of your version of this file only under the terms of + the GPL and not to allow others to use your version of this file under the + "Toolbar2000 License", indicate your decision by deleting the provisions + above and replace them with the notice and other provisions required by the + GPL. If you do not delete the provisions above, a recipient may use your + version of this file under either the "Toolbar2000 License" or the GPL. + + $jrsoftware: tb2k/Source/TB2Common.pas,v 1.31 2005/06/29 20:10:10 jr Exp $ +} + +interface + +{$I TB2Ver.inc} + +uses + Windows, Classes, SysUtils, Messages, Controls, Forms; + +type + TListSortExCompare = function(const Item1, Item2, ExtraData: Pointer): Integer; + THandleWMPrintNCPaintProc = procedure(Wnd: HWND; DC: HDC; AppData: Longint); + +function AddToFrontOfList(var List: TList; Item: Pointer): Boolean; +function AddToList(var List: TList; Item: Pointer): Boolean; +function ApplicationIsActive: Boolean; +function AreFlatMenusEnabled: Boolean; +function AreKeyboardCuesEnabled: Boolean; +function CallTrackMouseEvent(const Wnd: HWND; const Flags: DWORD): Boolean; +function CreateHalftoneBrush: HBRUSH; +function CreateNullRegion: HRGN; +function CreateRotatedFont(DC: HDC): HFONT; +function DivRoundUp(const Dividend, Divisor: Integer): Integer; +procedure DrawHalftoneInvertRect(const DC: HDC; const NewRect, OldRect: PRect; + const NewSize, OldSize: TSize); +procedure DrawRotatedText(const DC: HDC; AText: String; const ARect: TRect; + const AFormat: Cardinal); +procedure DrawInvertRect(const DC: HDC; const NewRect, OldRect: PRect; + const NewSize, OldSize: TSize; const Brush: HBRUSH; BrushLast: HBRUSH); +function EscapeAmpersands(const S: String): String; +function FindAccelChar(const S: String): Char; +{$IFNDEF JR_D5} +procedure FreeAndNil(var Obj); +{$ENDIF} +function GetInputLocaleCodePage: UINT; +function GetMenuShowDelay: Integer; +function GetRectOfMonitorContainingPoint(const P: TPoint; const WorkArea: Boolean): TRect; +function GetRectOfMonitorContainingRect(const R: TRect; const WorkArea: Boolean): TRect; +function GetRectOfMonitorContainingWindow(const W: HWND; const WorkArea: Boolean): TRect; +function GetRectOfPrimaryMonitor(const WorkArea: Boolean): TRect; +function GetTextHeight(const DC: HDC): Integer; +function GetTextWidth(const DC: HDC; S: String; const Prefix: Boolean): Integer; +procedure HandleWMPrint(const Wnd: HWND; var Message: TMessage; + const NCPaintFunc: THandleWMPrintNCPaintProc; const AppData: Longint); +procedure HandleWMPrintClient(const Control: TWinControl; + var Message: TMessage); +function IsWindowsXP: Boolean; +procedure ListSortEx(const List: TList; const Compare: TListSortExCompare; + const ExtraData: Pointer); +procedure InitTrackMouseEvent; +function Max(A, B: Integer): Integer; +function Min(A, B: Integer): Integer; +function MethodsEqual(const M1, M2: TMethod): Boolean; +function NeedToPlaySound(const Alias: String): Boolean; +procedure ProcessPaintMessages; +procedure RemoveMessages(const AMin, AMax: Integer); +procedure RemoveFromList(var List: TList; Item: Pointer); +procedure SelectNCUpdateRgn(Wnd: HWND; DC: HDC; Rgn: HRGN); +function StripAccelChars(const S: String): String; +function StripTrailingPunctuation(const S: String): String; +function UsingMultipleMonitors: Boolean; + +const + PopupMenuWindowNCSize = 3; + DT_HIDEPREFIX = $00100000; + +var + TrackMouseEventFunc: function(var EventTrack: TTrackMouseEvent): BOOL; stdcall; + +implementation + +uses + TB2Version; + +function ApplicationIsActive: Boolean; +{ Returns True if the application is in the foreground } +begin + Result := GetActiveWindow <> 0; +end; + +{$IFNDEF JR_D3} +function CopyPalette(Palette: HPALETTE): HPALETTE; +var + PaletteSize: Integer; + LogPal: TMaxLogPalette; +begin + Result := 0; + if Palette = 0 then Exit; + PaletteSize := 0; + if GetObject(Palette, SizeOf(PaletteSize), @PaletteSize) = 0 then Exit; + if PaletteSize = 0 then Exit; + with LogPal do begin + palVersion := $0300; + palNumEntries := PaletteSize; + GetPaletteEntries(Palette, 0, PaletteSize, palPalEntry); + end; + Result := CreatePalette(PLogPalette(@LogPal)^); +end; +{$ENDIF} + +procedure ListSortEx(const List: TList; const Compare: TListSortExCompare; + const ExtraData: Pointer); +{ Similar to TList.Sort, but lets you pass a user-defined ExtraData pointer } + procedure QuickSortEx(L: Integer; const R: Integer); + var + I, J: Integer; + P: Pointer; + begin + repeat + I := L; + J := R; + P := List[(L + R) shr 1]; + repeat + while Compare(List[I], P, ExtraData) < 0 do Inc(I); + while Compare(List[J], P, ExtraData) > 0 do Dec(J); + if I <= J then + begin + List.Exchange(I, J); + Inc(I); + Dec(J); + end; + until I > J; + if L < J then QuickSortEx(L, J); + L := I; + until I >= R; + end; +begin + if List.Count > 1 then + QuickSortEx(0, List.Count-1); +end; + +type + PPrintEnumProcData = ^TPrintEnumProcData; + TPrintEnumProcData = record + PrintChildren: Boolean; + ParentWnd: HWND; + DC: HDC; + PrintFlags: LPARAM; + end; + +function PrintEnumProc(Wnd: HWND; LParam: LPARAM): BOOL; stdcall; +var + R: TRect; + SaveIndex: Integer; +begin + Result := True; { continue enumerating } + with PPrintEnumProcData(LParam)^ do begin + { Skip window if it isn't a child/owned window of ParentWnd or isn't visible } + if (HWND(GetWindowLong(Wnd, GWL_HWNDPARENT)) <> ParentWnd) or + (GetWindowLong(Wnd, GWL_STYLE) and WS_VISIBLE = 0) then + { ^ don't use IsWindowVisible since it returns False if the window's + parent window is not visible } + Exit; + GetWindowRect(Wnd, R); + MapWindowPoints(0, ParentWnd, R, 2); + SaveIndex := SaveDC(DC); + { Like Windows, offset the window origin to the top-left coordinates of + the child/owned window } + MoveWindowOrg(DC, R.Left, R.Top); + { Like Windows, intersect the clipping region with the entire rectangle of + the child/owned window } + OffsetRect(R, -R.Left, -R.Top); + IntersectClipRect(DC, R.Left, R.Top, R.Right, R.Bottom); + { Send a WM_PRINT message to the child/owned window } + SendMessage(Wnd, WM_PRINT, WPARAM(DC), PrintFlags); + { Restore the DC's state, in case the WM_PRINT handler didn't put things + back the way it found them } + RestoreDC(DC, SaveIndex); + end; +end; + +procedure HandleWMPrint(const Wnd: HWND; var Message: TMessage; + const NCPaintFunc: THandleWMPrintNCPaintProc; const AppData: Longint); +{ note: AppData is an application-defined value which is passed to NCPaintFunc } +var + DC: HDC; + SaveIndex, SaveIndex2: Integer; + R: TRect; + P: TPoint; + Data: TPrintEnumProcData; +begin + if (Message.LParam and PRF_CHECKVISIBLE = 0) or IsWindowVisible(Wnd) then begin + DC := HDC(Message.WParam); + SaveIndex2 := SaveDC(DC); + try + if Message.LParam and PRF_NONCLIENT <> 0 then begin + SaveIndex := SaveDC(DC); + if Assigned(NCPaintFunc) then + NCPaintFunc(Wnd, DC, AppData); + RestoreDC(DC, SaveIndex); + end; + { Calculate the difference between the top-left corner of the window + and the top-left corner of its client area } + GetWindowRect(Wnd, R); + P.X := 0; P.Y := 0; + ClientToScreen(Wnd, P); + Dec(P.X, R.Left); Dec(P.Y, R.Top); + if Message.LParam and PRF_CLIENT <> 0 then begin + { Like Windows, the flags PRF_ERASEBKGND, PRF_CHILDREN, and PRF_OWNED + are ignored if PRF_CLIENT isn't also specified } + if Message.LParam and PRF_ERASEBKGND <> 0 then begin + { Send WM_ERASEBKGND } + SaveIndex := SaveDC(DC); + if Message.LParam and PRF_NONCLIENT <> 0 then + MoveWindowOrg(DC, P.X, P.Y); + SendMessage(Wnd, WM_ERASEBKGND, Message.WParam, 0); + RestoreDC(DC, SaveIndex); + end; + { Send WM_PRINTCLIENT } + SaveIndex := SaveDC(DC); + if Message.LParam and PRF_NONCLIENT <> 0 then + MoveWindowOrg(DC, P.X, P.Y); + SendMessage(Wnd, WM_PRINTCLIENT, Message.WParam, 0); + RestoreDC(DC, SaveIndex); + { Like Windows, always offset child/owned windows by the size of the + client area even if PRF_NONCLIENT isn't specified (a bug?) } + MoveWindowOrg(DC, P.X, P.Y); + Data.ParentWnd := Wnd; + Data.DC := DC; + { Send WM_PRINT to child/owned windows } + if Message.LParam and PRF_CHILDREN <> 0 then begin + Data.PrintChildren := True; + Data.PrintFlags := PRF_NONCLIENT or PRF_CLIENT or PRF_ERASEBKGND or + PRF_CHILDREN; { same flags as Windows passes to children } + EnumChildWindows(Wnd, @PrintEnumProc, LPARAM(@Data)); + end; + if Message.LParam and PRF_OWNED <> 0 then begin + Data.PrintChildren := False; + Data.PrintFlags := Message.LParam; + EnumWindows(@PrintEnumProc, LPARAM(@Data)); + end; + end; + finally + RestoreDC(DC, SaveIndex2); + end; + end; + { Windows' WM_PRINT returns 1. I'm not sure why. } + Message.Result := 1; +end; + +type + TWinControlAccess = class(TWinControl); + +procedure HandleWMPrintClient(const Control: TWinControl; var Message: TMessage); +var + Msg: TWMPaint; + SaveIndex: Integer; +begin + Msg.Msg := WM_PAINT; + Msg.DC := HDC(Message.WParam); + Msg.Unused := 0; + Msg.Result := 0; + SaveIndex := SaveDC(HDC(Message.WParam)); + try + TWinControlAccess(Control).PaintHandler(Msg); + finally + RestoreDC(HDC(Message.WParam), SaveIndex); + end; +end; + +function DivRoundUp(const Dividend, Divisor: Integer): Integer; +{ Similar to the 'div' operator, but if there is a remainder it always rounds + the result up one (or down if the result is negative). } +asm + mov ecx, edx + cdq + idiv ecx + test edx, edx + jz @@1 + test eax, eax + jns @@2 + dec eax + jmp @@1 + @@2: + inc eax + @@1: +end; + +function GetTextHeight(const DC: HDC): Integer; +var + TextMetric: TTextMetric; +begin + GetTextMetrics(DC, TextMetric); + Result := TextMetric.tmHeight; +end; + +function StripAccelChars(const S: String): String; +var + I: Integer; +begin + Result := S; + I := 1; + while I <= Length(Result) do begin + if not(Result[I] in LeadBytes) then begin + if Result[I] = '&' then + System.Delete(Result, I, 1); + Inc(I); + end + else + Inc(I, 2); + end; +end; + +function EscapeAmpersands(const S: String): String; +{ Replaces any '&' characters with '&&' } +var + I: Integer; +begin + Result := S; + I := 1; + while I <= Length(Result) do begin + if not(Result[I] in LeadBytes) then begin + if Result[I] = '&' then begin + Inc(I); + Insert('&', Result, I); + end; + Inc(I); + end + else + Inc(I, 2); + end; +end; + +function StripTrailingPunctuation(const S: String): String; +{ Removes any colon (':') or ellipsis ('...') from the end of S and returns + the resulting string } +var + L: Integer; +begin + Result := S; + L := Length(Result); + if (L > 1) and (Result[L] = ':') and (ByteType(Result, L) = mbSingleByte) then + SetLength(Result, L-1) + else if (L > 3) and (Result[L-2] = '.') and (Result[L-1] = '.') and + (Result[L] = '.') and (ByteType(Result, L-2) = mbSingleByte) then + SetLength(Result, L-3); +end; + +function GetTextWidth(const DC: HDC; S: String; const Prefix: Boolean): Integer; +{ Returns the width of the specified string using the font currently selected + into DC. If Prefix is True, it first removes "&" characters as necessary. } +var + Size: TSize; +begin + { This procedure is 10x faster than using DrawText with the DT_CALCRECT flag } + if Prefix then + S := StripAccelChars(S); + GetTextExtentPoint32(DC, PChar(S), Length(S), Size); + Result := Size.cx; +end; + +procedure ProcessPaintMessages; +{ Dispatches all pending WM_PAINT messages. In effect, this is like an + 'UpdateWindow' on all visible windows } +var + Msg: TMsg; +begin + while PeekMessage(Msg, 0, WM_PAINT, WM_PAINT, PM_NOREMOVE) do begin + case Integer(GetMessage(Msg, 0, WM_PAINT, WM_PAINT)) of + -1: Break; { if GetMessage failed } + 0: begin + { Repost WM_QUIT messages } + PostQuitMessage(Msg.WParam); + Break; + end; + end; + DispatchMessage(Msg); + end; +end; + +procedure RemoveMessages(const AMin, AMax: Integer); +{ Removes any messages with the specified ID from the queue } +var + Msg: TMsg; +begin + while PeekMessage(Msg, 0, AMin, AMax, PM_REMOVE) do begin + if Msg.message = WM_QUIT then begin + { Repost WM_QUIT messages } + PostQuitMessage(Msg.WParam); + Break; + end; + end; +end; + +procedure SelectNCUpdateRgn(Wnd: HWND; DC: HDC; Rgn: HRGN); +var + R: TRect; + NewClipRgn: HRGN; +begin + if (Rgn <> 0) and (Rgn <> 1) then begin + GetWindowRect(Wnd, R); + if SelectClipRgn(DC, Rgn) = ERROR then begin + NewClipRgn := CreateRectRgnIndirect(R); + SelectClipRgn(DC, NewClipRgn); + DeleteObject(NewClipRgn); + end; + OffsetClipRgn(DC, -R.Left, -R.Top); + end; +end; + +function AddToList(var List: TList; Item: Pointer): Boolean; +{ Returns True if Item didn't already exist in the list } +begin + if List = nil then + List := TList.Create; + Result := List.IndexOf(Item) = -1; + if Result then + List.Add(Item); +end; + +function AddToFrontOfList(var List: TList; Item: Pointer): Boolean; +{ Returns True if Item didn't already exist in the list } +begin + if List = nil then + List := TList.Create; + Result := List.IndexOf(Item) = -1; + if Result then + List.Insert(0, Item); +end; + +procedure RemoveFromList(var List: TList; Item: Pointer); +begin + if Assigned(List) then begin + List.Remove(Item); + if List.Count = 0 then begin + List.Free; + List := nil; + end; + end; +end; + +var + RegMenuShowDelay: Integer; + RegMenuShowDelayInited: BOOL = False; +function GetMenuShowDelay: Integer; +const + DefaultMenuShowDelay = 400; + function ReadMenuShowDelayFromRegistry: Integer; + var + K: HKEY; + Typ, DataSize: DWORD; + Data: array[0..31] of Char; + Res: Longint; + E: Integer; + begin + Result := DefaultMenuShowDelay; + if RegOpenKeyEx(HKEY_CURRENT_USER, 'Control Panel\Desktop', 0, + KEY_QUERY_VALUE, K) = ERROR_SUCCESS then begin + DataSize := SizeOf(Data); + Res := RegQueryValueEx(K, 'MenuShowDelay', nil, @Typ, @Data, @DataSize); + RegCloseKey(K); + if Res <> ERROR_FILE_NOT_FOUND then begin + if (Res <> ERROR_SUCCESS) or (Typ <> REG_SZ) then + Result := 0 + else begin + Val(Data, Result, E); + if E <> 0 then Result := 0; + end; + end; + end; + end; +begin + if Lo(GetVersion) >= 4 then begin + if not SystemParametersInfo(106{SPI_GETMENUSHOWDELAY}, 0, @Result, 0) then begin + { SPI_GETMENUSHOWDELAY is only supported by Windows NT 4.0 and Windows 98. + On Windows 95, it must use the registry to retrieve this setting. } + if not RegMenuShowDelayInited then begin + RegMenuShowDelay := ReadMenuShowDelayFromRegistry; + InterlockedExchange(Integer(RegMenuShowDelayInited), Ord(True)); + end; + Result := RegMenuShowDelay; + end; + if Result < 0 then Result := 0; + end + else + Result := DefaultMenuShowDelay; +end; + +function AreFlatMenusEnabled: Boolean; +{ Returns True if "flat menus" are enabled. Always returns False on pre-XP + Windows versions. } +const + SPI_GETFLATMENU = $1022; +var + FlatMenusEnabled: BOOL; +begin + { Interestingly, on Windows 2000, SystemParametersInfo(SPI_GETFLATMENU, ...) + succeeds and can return True in pvParam^ if the proper bit is set in + UserPreferencesMask. Since flat menus are not really used on Windows + 2000, call IsWindowsXP first to see if we're running at least XP. } + Result := IsWindowsXP and SystemParametersInfo(SPI_GETFLATMENU, 0, + @FlatMenusEnabled, 0) and FlatMenusEnabled; +end; + +function AreKeyboardCuesEnabled: Boolean; +{ Returns True if "keyboard cues" are enabled. Always returns True on + pre-2000 Windows versions. } +const + SPI_GETKEYBOARDCUES = $100A; +var + CuesEnabled: BOOL; +begin + Result := (Win32MajorVersion < 5) or + not SystemParametersInfo(SPI_GETKEYBOARDCUES, 0, @CuesEnabled, 0) or + CuesEnabled; +end; + +function CreateNullRegion: HRGN; +var + R: TRect; +begin + SetRectEmpty(R); + Result := CreateRectRgnIndirect(R); +end; + +procedure DrawInvertRect(const DC: HDC; const NewRect, OldRect: PRect; + const NewSize, OldSize: TSize; const Brush: HBRUSH; BrushLast: HBRUSH); +{ Draws a dragging outline, hiding the old one if neccessary. This code is + based on MFC sources. + + Either NewRect or OldRect can be nil or empty. } +var + SaveIndex: Integer; + rgnNew, rgnOutside, rgnInside, rgnLast, rgnUpdate: HRGN; + R: TRect; +begin + rgnLast := 0; + rgnUpdate := 0; + + { First, determine the update region and select it } + if NewRect = nil then begin + SetRectEmpty(R); + rgnOutside := CreateRectRgnIndirect(R); + end + else begin + R := NewRect^; + rgnOutside := CreateRectRgnIndirect(R); + InflateRect(R, -NewSize.cx, -NewSize.cy); + IntersectRect(R, R, NewRect^); + end; + rgnInside := CreateRectRgnIndirect(R); + rgnNew := CreateNullRegion; + CombineRgn(rgnNew, rgnOutside, rgnInside, RGN_XOR); + + if BrushLast = 0 then + BrushLast := Brush; + + if OldRect <> nil then begin + { Find difference between new region and old region } + rgnLast := CreateNullRegion; + with OldRect^ do + SetRectRgn(rgnOutside, Left, Top, Right, Bottom); + R := OldRect^; + InflateRect(R, -OldSize.cx, -OldSize.cy); + IntersectRect(R, R, OldRect^); + SetRectRgn(rgnInside, R.Left, R.Top, R.Right, R.Bottom); + CombineRgn(rgnLast, rgnOutside, rgnInside, RGN_XOR); + + { Only diff them if brushes are the same } + if Brush = BrushLast then begin + rgnUpdate := CreateNullRegion; + CombineRgn(rgnUpdate, rgnLast, rgnNew, RGN_XOR); + end; + end; + + { Save the DC state so that the clipping region can be restored } + SaveIndex := SaveDC(DC); + try + if (Brush <> BrushLast) and (OldRect <> nil) then begin + { Brushes are different -- erase old region first } + SelectClipRgn(DC, rgnLast); + GetClipBox(DC, R); + SelectObject(DC, BrushLast); + PatBlt(DC, R.Left, R.Top, R.Right-R.Left, R.Bottom-R.Top, PATINVERT); + end; + + { Draw into the update/new region } + if rgnUpdate <> 0 then + SelectClipRgn(DC, rgnUpdate) + else + SelectClipRgn(DC, rgnNew); + GetClipBox(DC, R); + SelectObject(DC, Brush); + PatBlt(DC, R.Left, R.Top, R.Right-R.Left, R.Bottom-R.Top, PATINVERT); + finally + { Clean up DC } + RestoreDC(DC, SaveIndex); + end; + + { Free regions } + if rgnNew <> 0 then DeleteObject(rgnNew); + if rgnOutside <> 0 then DeleteObject(rgnOutside); + if rgnInside <> 0 then DeleteObject(rgnInside); + if rgnLast <> 0 then DeleteObject(rgnLast); + if rgnUpdate <> 0 then DeleteObject(rgnUpdate); +end; + +function CreateHalftoneBrush: HBRUSH; +const + Patterns: array[Boolean] of Word = ($5555, $AAAA); +var + I: Integer; + GrayPattern: array[0..7] of Word; + GrayBitmap: HBITMAP; +begin + for I := 0 to 7 do + GrayPattern[I] := Patterns[Odd(I)]; + GrayBitmap := CreateBitmap(8, 8, 1, 1, @GrayPattern); + Result := CreatePatternBrush(GrayBitmap); + DeleteObject(GrayBitmap); +end; + +procedure DrawHalftoneInvertRect(const DC: HDC; const NewRect, OldRect: PRect; + const NewSize, OldSize: TSize); +var + Brush: HBRUSH; +begin + Brush := CreateHalftoneBrush; + try + DrawInvertRect(DC, NewRect, OldRect, NewSize, OldSize, Brush, Brush); + finally + DeleteObject(Brush); + end; +end; + +function MethodsEqual(const M1, M2: TMethod): Boolean; +begin + Result := (M1.Code = M2.Code) and (M1.Data = M2.Data); +end; + +function GetRectOfPrimaryMonitor(const WorkArea: Boolean): TRect; +begin + if not WorkArea or not SystemParametersInfo(SPI_GETWORKAREA, 0, @Result, 0) then + Result := Rect(0, 0, Screen.Width, Screen.Height); +end; + +function UsingMultipleMonitors: Boolean; +{ Returns True if the system has more than one display monitor configured. } +var + NumMonitors: Integer; +begin + NumMonitors := GetSystemMetrics(80 {SM_CMONITORS}); + Result := (NumMonitors <> 0) and (NumMonitors <> 1); + { ^ NumMonitors will be zero if not running Win98, NT 5, or later } +end; + +type + HMONITOR = type Integer; + PMonitorInfoA = ^TMonitorInfoA; + TMonitorInfoA = record + cbSize: DWORD; + rcMonitor: TRect; + rcWork: TRect; + dwFlags: DWORD; + end; +const + MONITOR_DEFAULTTONEAREST = $2; +type + TMultiMonApis = record + funcMonitorFromRect: function(lprcScreenCoords: PRect; dwFlags: DWORD): HMONITOR; stdcall; + funcMonitorFromPoint: function(ptScreenCoords: TPoint; dwFlags: DWORD): HMONITOR; stdcall; + funcMonitorFromWindow: function(hWnd: HWND; dwFlags: DWORD): HMONITOR; stdcall; + funcGetMonitorInfoA: function(hMonitor: HMONITOR; lpMonitorInfo: PMonitorInfoA): BOOL; stdcall; + end; + +{ Under D4 I could be using the MultiMon unit for the multiple monitor + function imports, but its stubs for MonitorFromRect and MonitorFromPoint + are seriously bugged... So I chose to avoid the MultiMon unit entirely. } + +function InitMultiMonApis(var Apis: TMultiMonApis): Boolean; +var + User32Handle: THandle; +begin + User32Handle := GetModuleHandle(user32); + Apis.funcMonitorFromRect := GetProcAddress(User32Handle, 'MonitorFromRect'); + Apis.funcMonitorFromPoint := GetProcAddress(User32Handle, 'MonitorFromPoint'); + Apis.funcMonitorFromWindow := GetProcAddress(User32Handle, 'MonitorFromWindow'); + Apis.funcGetMonitorInfoA := GetProcAddress(User32Handle, 'GetMonitorInfoA'); + Result := Assigned(Apis.funcMonitorFromRect) and + Assigned(Apis.funcMonitorFromPoint) and Assigned(Apis.funcGetMonitorInfoA); +end; + +function GetRectOfMonitorContainingRect(const R: TRect; + const WorkArea: Boolean): TRect; +{ Returns the work area of the monitor which the rectangle R intersects with + the most, or the monitor nearest R if no monitors intersect. } +var + Apis: TMultiMonApis; + M: HMONITOR; + MonitorInfo: TMonitorInfoA; +begin + if UsingMultipleMonitors and InitMultiMonApis(Apis) then begin + M := Apis.funcMonitorFromRect(@R, MONITOR_DEFAULTTONEAREST); + MonitorInfo.cbSize := SizeOf(MonitorInfo); + if Apis.funcGetMonitorInfoA(M, @MonitorInfo) then begin + if not WorkArea then + Result := MonitorInfo.rcMonitor + else + Result := MonitorInfo.rcWork; + Exit; + end; + end; + Result := GetRectOfPrimaryMonitor(WorkArea); +end; + +function GetRectOfMonitorContainingPoint(const P: TPoint; + const WorkArea: Boolean): TRect; +{ Returns the screen area of the monitor containing the point P, or the monitor + nearest P if P isn't in any monitor's work area. } +var + Apis: TMultiMonApis; + M: HMONITOR; + MonitorInfo: TMonitorInfoA; +begin + if UsingMultipleMonitors and InitMultiMonApis(Apis) then begin + M := Apis.funcMonitorFromPoint(P, MONITOR_DEFAULTTONEAREST); + MonitorInfo.cbSize := SizeOf(MonitorInfo); + if Apis.funcGetMonitorInfoA(M, @MonitorInfo) then begin + if not WorkArea then + Result := MonitorInfo.rcMonitor + else + Result := MonitorInfo.rcWork; + Exit; + end; + end; + Result := GetRectOfPrimaryMonitor(WorkArea); +end; + +function GetRectOfMonitorContainingWindow(const W: HWND; + const WorkArea: Boolean): TRect; +var + Apis: TMultiMonApis; + M: HMONITOR; + MonitorInfo: TMonitorInfoA; +begin + if UsingMultipleMonitors and InitMultiMonApis(Apis) then begin + M := Apis.funcMonitorFromWindow(W, MONITOR_DEFAULTTONEAREST); + MonitorInfo.cbSize := SizeOf(MonitorInfo); + if Apis.funcGetMonitorInfoA(M, @MonitorInfo) then begin + if not WorkArea then + Result := MonitorInfo.rcMonitor + else + Result := MonitorInfo.rcWork; + Exit; + end; + end; + Result := GetRectOfPrimaryMonitor(WorkArea); +end; + +var + TrackMouseEventInited: BOOL; + +procedure InitTrackMouseEvent; +var + TrackMouseEventComCtlModule: THandle; +begin + { First look for TrackMouseEvent which is available on Windows 98 & NT 4 only. + If it doesn't exist, look for _TrackMouseEvent which is available on + Windows 95 if IE 3.0 or later is installed. } + if not TrackMouseEventInited then begin + TrackMouseEventFunc := GetProcAddress(GetModuleHandle(user32), + 'TrackMouseEvent'); + if @TrackMouseEventFunc = nil then begin + TrackMouseEventComCtlModule := + {$IFDEF JR_D5} SafeLoadLibrary {$ELSE} LoadLibrary {$ENDIF} (comctl32); + if TrackMouseEventComCtlModule <> 0 then + TrackMouseEventFunc := GetProcAddress(TrackMouseEventComCtlModule, + '_TrackMouseEvent'); + end; + InterlockedExchange(Integer(TrackMouseEventInited), Ord(True)); + end; +end; + +function CallTrackMouseEvent(const Wnd: HWND; const Flags: DWORD): Boolean; +var + Track: TTrackMouseEvent; +begin + Result := False; + if Assigned(TrackMouseEventFunc) then begin + Track.cbSize := SizeOf(Track); + Track.dwFlags := Flags; + Track.hwndTrack := Wnd; + Track.dwHoverTime := 0; + Result := TrackMouseEventFunc(Track); + end; +end; + +{$IFNDEF JR_D5} +procedure FreeAndNil(var Obj); +var + P: TObject; +begin + P := TObject(Obj); + TObject(Obj) := nil; + P.Free; +end; +{$ENDIF} + +function EnumFontsProc(const lplf: TLogFont; const lptm: TTextMetric; + dwType: DWORD; lpData: LPARAM): Integer; stdcall; +begin + Boolean(Pointer(lpData)^) := True; + Result := 0; +end; + +function CreateRotatedFont(DC: HDC): HFONT; +{ Creates a font based on the DC's current font, but rotated 270 degrees } +var + LogFont: TLogFont; + TM: TTextMetric; + VerticalFontName: array[0..LF_FACESIZE-1] of Char; + VerticalFontExists: Boolean; +begin + if GetObject(GetCurrentObject(DC, OBJ_FONT), SizeOf(LogFont), + @LogFont) = 0 then begin + { just in case... } + Result := 0; + Exit; + end; + LogFont.lfEscapement := 2700; + LogFont.lfOrientation := 2700; + LogFont.lfOutPrecision := OUT_TT_ONLY_PRECIS; { needed for Win9x } + + { Don't let a random TrueType font be substituted when MS Sans Serif or + Microsoft Sans Serif are used. Hard-code Arial. } + if (StrIComp(LogFont.lfFaceName, 'MS Sans Serif') = 0) or + (StrIComp(LogFont.lfFaceName, 'Microsoft Sans Serif') = 0) then begin + StrPCopy(LogFont.lfFaceName, 'Arial'); + { Set lfHeight to the actual height of the current font. This is needed + to work around a Windows 98 issue: on a clean install of the OS, + SPI_GETNONCLIENTMETRICS returns -5 for lfSmCaptionFont.lfHeight. This is + wrong; it should return -11 for an 8 pt font. With normal, unrotated text + this actually displays correctly, since MS Sans Serif doesn't support + sizes below 8 pt. However, when we change to a TrueType font like Arial, + this becomes a problem because it'll actually create a font that small. } + if GetTextMetrics(DC, TM) then begin + { If the original height was negative, keep it negative } + if LogFont.lfHeight <= 0 then + LogFont.lfHeight := -(TM.tmHeight - TM.tmInternalLeading) + else + LogFont.lfHeight := TM.tmHeight; + end; + end; + + { Use a vertical font if available so that Asian characters aren't drawn + sideways } + if StrLen(LogFont.lfFaceName) < SizeOf(VerticalFontName)-1 then begin + VerticalFontName[0] := '@'; + StrCopy(@VerticalFontName[1], LogFont.lfFaceName); + VerticalFontExists := False; + EnumFonts(DC, VerticalFontName, @EnumFontsProc, @VerticalFontExists); + if VerticalFontExists then + StrCopy(LogFont.lfFaceName, VerticalFontName); + end; + + Result := CreateFontIndirect(LogFont); +end; + +procedure DrawRotatedText(const DC: HDC; AText: String; const ARect: TRect; + const AFormat: Cardinal); +{ Like DrawText, but draws the text at a 270 degree angle. + The only format flag this function respects is DT_HIDEPREFIX. Text is always + drawn centered. } +var + RotatedFont, SaveFont: HFONT; + TextMetrics: TTextMetric; + X, Y, P, I, SU, FU: Integer; + SaveAlign: UINT; + SavePen, Pen: HPEN; +begin + RotatedFont := CreateRotatedFont(DC); + SaveFont := SelectObject(DC, RotatedFont); + + GetTextMetrics(DC, TextMetrics); + X := ARect.Left + ((ARect.Right - ARect.Left) - TextMetrics.tmHeight) div 2; + Y := ARect.Top + ((ARect.Bottom - ARect.Top) - GetTextWidth(DC, AText, True)) div 2; + + { Find the index of the character that should be underlined. Delete '&' + characters from the string. Like DrawText, only the last prefixed character + will be underlined. } + P := 0; + I := 1; + while I <= Length(AText) do begin + if AText[I] in LeadBytes then + Inc(I) + else if AText[I] = '&' then begin + Delete(AText, I, 1); + { Note: PChar cast is so that if Delete deleted the last character in + the string, we don't step past the end of the string (which would cause + an AV if AText is now empty), but rather look at the null character + and treat it as an accelerator key like DrawText. } + if PChar(AText)[I-1] <> '&' then + P := I; + end; + Inc(I); + end; + + SaveAlign := SetTextAlign(DC, TA_BOTTOM); + TextOut(DC, X, Y, PChar(AText), Length(AText)); + SetTextAlign(DC, SaveAlign); + { Underline } + if (P > 0) and (AFormat and DT_HIDEPREFIX = 0) then begin + SU := GetTextWidth(DC, Copy(AText, 1, P-1), False); + FU := SU + GetTextWidth(DC, PChar(AText)[P-1], False); + Inc(X, TextMetrics.tmDescent - 2); + Pen := CreatePen(PS_SOLID, 1, GetTextColor(DC)); + SavePen := SelectObject(DC, Pen); + MoveToEx(DC, X, Y + SU, nil); + LineTo(DC, X, Y + FU); + SelectObject(DC, SavePen); + DeleteObject(Pen); + end; + + SelectObject(DC, SaveFont); + DeleteObject(RotatedFont); +end; + +function NeedToPlaySound(const Alias: String): Boolean; +{ This function checks the registry to see if the specified sound event alias + is assigned to a file. + The purpose of having this function is so it can avoid calls to PlaySound if + possible, because on Windows 2000 there is an annoying 1/3 second delay on + the first call to PlaySound. + Windows Explorer actually uses this same technique when playing sounds for + the Start menu. } +var + K: HKEY; + Data: array[0..3] of WideChar; + DataSize: DWORD; + ErrorCode: Longint; +begin + if (Win32MajorVersion < 5) or (Win32Platform <> VER_PLATFORM_WIN32_NT) then begin + { No need to check pre-Windows 2000 versions since their PlaySound + functions don't have the delay; always return True. } + Result := True; + Exit; + end; + Result := False; + if RegOpenKeyEx(HKEY_CURRENT_USER, + PChar('AppEvents\Schemes\Apps\.Default\' + Alias + '\.Current'), + 0, KEY_QUERY_VALUE, K) = ERROR_SUCCESS then begin + DataSize := SizeOf(Data); + { Note: Use the 'W' version of RegQueryValueEx for more speed } + ErrorCode := RegQueryValueExW(K, nil, nil, nil, @Data, @DataSize); + if ((ErrorCode = ERROR_SUCCESS) and (Data[0] <> #0)) or + (ErrorCode = ERROR_MORE_DATA) then + Result := True; + RegCloseKey(K); + end; +end; + +function Max(A, B: Integer): Integer; +begin + if A >= B then + Result := A + else + Result := B; +end; + +function Min(A, B: Integer): Integer; +begin + if A <= B then + Result := A + else + Result := B; +end; + +function FindAccelChar(const S: String): Char; +{ Finds the last accelerator key in S. Returns #0 if no accelerator key was + found. '&&' is ignored. } +var + P: PChar; +begin + P := PChar(S); + Result := #0; + while True do begin + P := AnsiStrScan(P, '&'); + if P = nil then Break; + Inc(P); + if P^ <> '&' then begin + if P^ = #0 then Break; + Result := P^; + end; + Inc(P); + end; +end; + +function IsWindowsXP: Boolean; +begin + Result := (Win32Platform = VER_PLATFORM_WIN32_NT) and + ((Win32MajorVersion > 5) or + ((Win32MajorVersion = 5) and (Win32MinorVersion >= 1))); +end; + +function GetInputLocaleCodePage: UINT; +{ Returns the code page identifier of the active input locale, or CP_ACP if + for some unknown reason it couldn't be determined. } +var + Buf: array[0..15] of Char; + ErrorCode: Integer; +begin + if GetLocaleInfo(GetKeyboardLayout(0) and $FFFF, LOCALE_IDEFAULTANSICODEPAGE, + Buf, SizeOf(Buf)) > 0 then begin + Buf[High(Buf)] := #0; { ensure null termination, just in case... } + Val(Buf, Result, ErrorCode); + { Just to be *completely* safe, verify that the code page returned by + GetLocaleInfo actually exists. The result of this function may be fed + into WideCharToMultiByte, and we don't want WideCharToMultiByte to fail + entirely because of a bad code page. } + if (ErrorCode <> 0) or not IsValidCodePage(Result) then + Result := CP_ACP; + end + else + Result := CP_ACP; +end; + +end. diff --git a/official/2.1.6+2.1.beta1/Source/TB2Consts.pas b/official/2.1.6+2.1.beta1/Source/TB2Consts.pas new file mode 100644 index 0000000..2d634d8 --- /dev/null +++ b/official/2.1.6+2.1.beta1/Source/TB2Consts.pas @@ -0,0 +1,33 @@ +unit TB2Consts; +{ $jrsoftware: tb2k/Source/TB2Consts.pas,v 1.7 2002/11/14 18:07:19 jr Exp $ } + +interface + +{$I TB2Ver.inc} + +resourcestring + { Exceptions } + STBToolbarIndexOutOfBounds = 'Toolbar item index out of range'; + STBToolbarItemReinserted = 'Toolbar item already inserted'; + STBViewerNotFound = 'An item viewer associated the specified item could not be found'; + + { TTBChevronItem } + STBChevronItemMoreButtonsHint = 'More Buttons|'; + + { TTBMRUListItem } + STBMRUListItemDefCaption = '(MRU List)'; + + { TTBMDIWindowItem } + STBMDIWindowItemDefCaption = '(Window List)'; + + { TTBDock exception messages } + STBDockParentNotAllowed = 'A TTBDock control cannot be placed inside a tool window or another TTBDock'; + STBDockCannotChangePosition = 'Cannot change Position of a TTBDock if it already contains controls'; + + { TTBCustomDockableWindow exception messages } + STBToolwinNameNotSet = 'Cannot save dockable window''s position because Name property is not set'; + STBToolwinDockedToNameNotSet = 'Cannot save dockable window''s position because DockedTo''s Name property not set'; + +implementation + +end. diff --git a/official/2.1.6+2.1.beta1/Source/TB2Dock.pas b/official/2.1.6+2.1.beta1/Source/TB2Dock.pas new file mode 100644 index 0000000..a7d62a9 --- /dev/null +++ b/official/2.1.6+2.1.beta1/Source/TB2Dock.pas @@ -0,0 +1,5554 @@ +unit TB2Dock; + +{ + Toolbar2000 + Copyright (C) 1998-2005 by Jordan Russell + All rights reserved. + + The contents of this file are subject to the "Toolbar2000 License"; you may + not use or distribute this file except in compliance with the + "Toolbar2000 License". A copy of the "Toolbar2000 License" may be found in + TB2k-LICENSE.txt or at: + http://www.jrsoftware.org/files/tb2k/TB2k-LICENSE.txt + + Alternatively, the contents of this file may be used under the terms of the + GNU General Public License (the "GPL"), in which case the provisions of the + GPL are applicable instead of those in the "Toolbar2000 License". A copy of + the GPL may be found in GPL-LICENSE.txt or at: + http://www.jrsoftware.org/files/tb2k/GPL-LICENSE.txt + If you wish to allow use of your version of this file only under the terms of + the GPL and not to allow others to use your version of this file under the + "Toolbar2000 License", indicate your decision by deleting the provisions + above and replace them with the notice and other provisions required by the + GPL. If you do not delete the provisions above, a recipient may use your + version of this file under either the "Toolbar2000 License" or the GPL. + + $jrsoftware: tb2k/Source/TB2Dock.pas,v 1.99 2005/07/15 19:35:03 jr Exp $ +} + +interface + +{x$DEFINE TB2Dock_DisableLock} +{ Remove the 'x' to enable the define. It will disable calls to + LockWindowUpdate, which it calls to disable screen updates while dragging. + You may want to temporarily enable the define while debugging so you are able + to see your code window while stepping through the dragging routines. } + +{$I TB2Ver.inc} + +uses + Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms; + +type + TTBCustomForm = {$IFDEF JR_D3} TCustomForm {$ELSE} TForm {$ENDIF}; + + { TTBDock } + + TTBDockBoundLinesValues = (blTop, blBottom, blLeft, blRight); + TTBDockBoundLines = set of TTBDockBoundLinesValues; + TTBDockPosition = (dpTop, dpBottom, dpLeft, dpRight); + TTBDockType = (dtNotDocked, dtFloating, dtTopBottom, dtLeftRight); + TTBDockableTo = set of TTBDockPosition; + + TTBCustomDockableWindow = class; + TTBBasicBackground = class; + + TTBInsertRemoveEvent = procedure(Sender: TObject; Inserting: Boolean; + Bar: TTBCustomDockableWindow) of object; + TTBRequestDockEvent = procedure(Sender: TObject; Bar: TTBCustomDockableWindow; + var Accept: Boolean) of object; + + TTBDock = class(TCustomControl) + private + { Property values } + FPosition: TTBDockPosition; + FAllowDrag: Boolean; + FBoundLines: TTBDockBoundLines; + FBackground: TTBBasicBackground; + FBkgOnToolbars: Boolean; + FFixAlign: Boolean; + FCommitNewPositions: Boolean; + FLimitToOneRow: Boolean; + FOnInsertRemoveBar: TTBInsertRemoveEvent; + FOnRequestDock: TTBRequestDockEvent; + {$IFNDEF JR_D4} + FOnResize: TNotifyEvent; + {$ENDIF} + + { Internal } + FDisableArrangeToolbars: Integer; { Increment to disable ArrangeToolbars } + FArrangeToolbarsNeeded: Boolean; + FNonClientWidth, FNonClientHeight: Integer; + + { Property access methods } + //function GetVersion: TToolbar97Version; + procedure SetAllowDrag(Value: Boolean); + procedure SetBackground(Value: TTBBasicBackground); + procedure SetBackgroundOnToolbars(Value: Boolean); + procedure SetBoundLines(Value: TTBDockBoundLines); + procedure SetFixAlign(Value: Boolean); + procedure SetPosition(Value: TTBDockPosition); + //procedure SetVersion(const Value: TToolbar97Version); + + function GetToolbarCount: Integer; + function GetToolbars(Index: Integer): TTBCustomDockableWindow; + + { Internal } + procedure BackgroundChanged(Sender: TObject); + procedure ChangeDockList(const Insert: Boolean; const Bar: TTBCustomDockableWindow); + procedure CommitPositions; + procedure DrawNCArea(const DrawToDC: Boolean; const ADC: HDC; + const Clip: HRGN); + function GetDesignModeRowOf(const XY: Integer): Integer; + procedure RelayMsgToFloatingBars(var Message: TMessage); + procedure ToolbarVisibilityChanged(const Bar: TTBCustomDockableWindow; + const ForceRemove: Boolean); + + { Messages } + procedure CMDialogChar(var Message: TCMDialogChar); message CM_DIALOGCHAR; + procedure CMDialogKey(var Message: TCMDialogKey); message CM_DIALOGKEY; + procedure CMSysColorChange(var Message: TMessage); message CM_SYSCOLORCHANGE; + procedure WMEraseBkgnd(var Message: TWMEraseBkgnd); message WM_ERASEBKGND; + procedure WMMove(var Message: TWMMove); message WM_MOVE; + {$IFNDEF JR_D4} + procedure WMSize(var Message: TWMSize); message WM_SIZE; + {$ENDIF} + procedure WMNCCalcSize(var Message: TWMNCCalcSize); message WM_NCCALCSIZE; + procedure WMNCPaint(var Message: TMessage); message WM_NCPAINT; + procedure WMPrint(var Message: TMessage); message WM_PRINT; + procedure WMPrintClient(var Message: TMessage); message WM_PRINTCLIENT; + procedure WMSysCommand(var Message: TWMSysCommand); message WM_SYSCOMMAND; + protected + DockList: TList; { List of the toolbars docked, and those floating and have LastDock + pointing to the dock. Items are casted in TTBCustomDockableWindow's. } + DockVisibleList: TList; { Similar to DockList, but lists only docked and visible toolbars } + function Accepts(ADockableWindow: TTBCustomDockableWindow): Boolean; virtual; + procedure AlignControls(AControl: TControl; var Rect: TRect); override; + procedure ChangeWidthHeight(const NewWidth, NewHeight: Integer); + procedure DrawBackground(DC: HDC; const DrawRect: TRect); virtual; + function GetPalette: HPALETTE; override; + function HasVisibleToolbars: Boolean; + procedure InvalidateBackgrounds; + procedure Loaded; override; + procedure Notification(AComponent: TComponent; Operation: TOperation); override; + procedure SetParent(AParent: TWinControl); override; + function ToolbarVisibleOnDock(const AToolbar: TTBCustomDockableWindow): Boolean; + procedure Paint; override; + function UsingBackground: Boolean; virtual; + property ArrangeToolbarsNeeded: Boolean read FArrangeToolbarsNeeded write FArrangeToolbarsNeeded; + property DisableArrangeToolbars: Integer read FDisableArrangeToolbars write FDisableArrangeToolbars; + public + constructor Create(AOwner: TComponent); override; + procedure CreateParams(var Params: TCreateParams); override; + destructor Destroy; override; + + procedure ArrangeToolbars; virtual; + procedure BeginUpdate; + procedure EndUpdate; + function GetCurrentRowSize(const Row: Integer; var AFullSize: Boolean): Integer; + function GetHighestRow(const HighestEffective: Boolean): Integer; + function GetMinRowSize(const Row: Integer; + const ExcludeControl: TTBCustomDockableWindow): Integer; + + property CommitNewPositions: Boolean read FCommitNewPositions write FCommitNewPositions; + property NonClientWidth: Integer read FNonClientWidth; + property NonClientHeight: Integer read FNonClientHeight; + property ToolbarCount: Integer read GetToolbarCount; + property Toolbars[Index: Integer]: TTBCustomDockableWindow read GetToolbars; + published + property AllowDrag: Boolean read FAllowDrag write SetAllowDrag default True; + property Background: TTBBasicBackground read FBackground write SetBackground; + property BackgroundOnToolbars: Boolean read FBkgOnToolbars write SetBackgroundOnToolbars default True; + property BoundLines: TTBDockBoundLines read FBoundLines write SetBoundLines default []; + property Color default clBtnFace; + property FixAlign: Boolean read FFixAlign write SetFixAlign default False; + property LimitToOneRow: Boolean read FLimitToOneRow write FLimitToOneRow default False; + property PopupMenu; + property Position: TTBDockPosition read FPosition write SetPosition default dpTop; + //property Version: TToolbar97Version read GetVersion write SetVersion stored False; + property Visible; + + {$IFDEF JR_D5} + property OnContextPopup; + {$ENDIF} + property OnInsertRemoveBar: TTBInsertRemoveEvent read FOnInsertRemoveBar write FOnInsertRemoveBar; + property OnMouseDown; + property OnMouseMove; + property OnMouseUp; + property OnRequestDock: TTBRequestDockEvent read FOnRequestDock write FOnRequestDock; + {$IFDEF JR_D4} + property OnResize; + {$ELSE} + property OnResize: TNotifyEvent read FOnResize write FOnResize; + {$ENDIF} + end; + + { TTBFloatingWindowParent - internal } + + TTBToolWindowNCRedrawWhatElement = (twrdBorder, twrdCaption, twrdCloseButton); + TTBToolWindowNCRedrawWhat = set of TTBToolWindowNCRedrawWhatElement; + + TTBFloatingWindowParentClass = class of TTBFloatingWindowParent; + TTBFloatingWindowParent = class(TCustomForm) + private + FCloseButtonDown: Boolean; { True if Close button is currently depressed } + FDockableWindow: TTBCustomDockableWindow; + FParentForm: TTBCustomForm; + FShouldShow: Boolean; + + procedure SetCloseButtonState(Pushed: Boolean); + procedure RedrawNCArea(const RedrawWhat: TTBToolWindowNCRedrawWhat); + + procedure CMShowingChanged(var Message: TMessage); message CM_SHOWINGCHANGED; + procedure CMDialogKey(var Message: TCMDialogKey); message CM_DIALOGKEY; + procedure CMTextChanged(var Message: TMessage); message CM_TEXTCHANGED; + procedure WMActivate(var Message: TWMActivate); message WM_ACTIVATE; + procedure WMClose(var Message: TWMClose); message WM_CLOSE; + procedure WMGetMinMaxInfo(var Message: TWMGetMinMaxInfo); message WM_GETMINMAXINFO; + procedure WMMouseActivate(var Message: TWMMouseActivate); message WM_MOUSEACTIVATE; + procedure WMMove(var Message: TWMMove); message WM_MOVE; + procedure WMNCCalcSize(var Message: TWMNCCalcSize); message WM_NCCALCSIZE; + procedure WMNCHitTest(var Message: TWMNCHitTest); message WM_NCHITTEST; + procedure WMNCLButtonDblClk(var Message: TWMNCLButtonDblClk); message WM_NCLBUTTONDBLCLK; + procedure WMNCLButtonDown(var Message: TWMNCLButtonDown); message WM_NCLBUTTONDOWN; + procedure WMNCPaint(var Message: TMessage); message WM_NCPAINT; + procedure WMNCRButtonUp(var Message: TWMNCRButtonUp); message WM_NCRBUTTONUP; + procedure WMPrint(var Message: TMessage); message WM_PRINT; + procedure WMPrintClient(var Message: TMessage); message WM_PRINTCLIENT; + protected + procedure AlignControls(AControl: TControl; var Rect: TRect); override; + procedure CreateParams(var Params: TCreateParams); override; + procedure DrawNCArea(const DrawToDC: Boolean; const ADC: HDC; + const Clip: HRGN; RedrawWhat: TTBToolWindowNCRedrawWhat); dynamic; + property DockableWindow: TTBCustomDockableWindow read FDockableWindow; + property CloseButtonDown: Boolean read FCloseButtonDown; + public + property ParentForm: TTBCustomForm read FParentForm; + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + end; + + { TTBCustomDockableWindow } + + TTBDockChangingEvent = procedure(Sender: TObject; Floating: Boolean; + DockingTo: TTBDock) of object; + TTBDragHandleStyle = (dhDouble, dhNone, dhSingle); + TTBDockMode = (dmCanFloat, dmCannotFloat, dmCannotFloatOrChangeDocks); + TTBFloatingMode = (fmOnTopOfParentForm, fmOnTopOfAllForms); + TTBSizeHandle = (twshLeft, twshRight, twshTop, twshTopLeft, + twshTopRight, twshBottom, twshBottomLeft, twshBottomRight); + { ^ must be in same order as HTLEFT..HTBOTTOMRIGHT } + TTBPositionReadIntProc = function(const ToolbarName, Value: String; const Default: Longint; + const ExtraData: Pointer): Longint; + TTBPositionReadStringProc = function(const ToolbarName, Value, Default: String; + const ExtraData: Pointer): String; + TTBPositionWriteIntProc = procedure(const ToolbarName, Value: String; const Data: Longint; + const ExtraData: Pointer); + TTBPositionWriteStringProc = procedure(const ToolbarName, Value, Data: String; + const ExtraData: Pointer); + TTBReadPositionData = record + ReadIntProc: TTBPositionReadIntProc; + ReadStringProc: TTBPositionReadStringProc; + ExtraData: Pointer; + end; + TTBWritePositionData = record + WriteIntProc: TTBPositionWriteIntProc; + WriteStringProc: TTBPositionWriteStringProc; + ExtraData: Pointer; + end; + TTBDockableWindowStyles = set of (tbdsResizeEightCorner, tbdsResizeClipCursor); + TTBShrinkMode = (tbsmNone, tbsmWrap, tbsmChevron); + + TTBCustomDockableWindow = class(TCustomControl) + private + { Property variables } + FAutoResize: Boolean; + FDblClickUndock: Boolean; + FDockPos, FDockRow, FEffectiveDockPos, FEffectiveDockRow: Integer; + FDocked: Boolean; + FCurrentDock, FDefaultDock, FLastDock: TTBDock; + FCurrentSize: Integer; + FFloating: Boolean; + FOnClose, FOnDockChanged, FOnMove, FOnRecreated, + FOnRecreating, {$IFNDEF JR_D4} FOnResize, {$ENDIF} + FOnVisibleChanged: TNotifyEvent; + FOnCloseQuery: TCloseQueryEvent; + FOnDockChanging, FOnDockChangingHidden: TTBDockChangingEvent; + FActivateParent, FHideWhenInactive, FCloseButton, FCloseButtonWhenDocked, + FFullSize, FResizable, FShowCaption, FStretch, FUseLastDock: Boolean; + FBorderStyle: TBorderStyle; + FDockMode: TTBDockMode; + FDragHandleStyle: TTBDragHandleStyle; + FDockableTo: TTBDockableTo; + FFloatingMode: TTBFloatingMode; + FSmoothDrag: Boolean; + FDockableWindowStyles: TTBDockableWindowStyles; + FLastRowSize: Integer; + FInsertRowBefore: Boolean; + + { Misc. } + FUpdatingBounds, { Incremented while internally changing the bounds. This allows + it to move the toolbar freely in design mode and prevents the + SizeChanging protected method from begin called } + FDisableArrange, { Incremented to disable Arrange } + FDisableOnMove, { Incremented to prevent WM_MOVE handler from calling the OnMoved handler } + FHidden: Integer; { Incremented while the toolbar is temporarily hidden } + FArrangeNeeded, FMoved: Boolean; + FInactiveCaption: Boolean; { True when the caption of the toolbar is currently the inactive color } + FFloatingPosition: TPoint; + FDockForms: TList; + FSavedAtRunTime: Boolean; + //FNonClientWidth, FNonClientHeight: Integer; + FDragMode, FDragSplitting, FDragCanSplit: Boolean; + FSmoothDragging: Boolean; + + { When floating. These are not used in design mode } + FCloseButtonDown: Boolean; { True if Close button is currently depressed } + FCloseButtonHover: Boolean; + FFloatParent: TTBFloatingWindowParent; { Run-time only: The actual Parent of the toolbar when it is floating } + + { Property access methods } + //function GetVersion: TToolbar97Version; + function GetNonClientWidth: Integer; + function GetNonClientHeight: Integer; + function IsLastDockStored: Boolean; + function IsWidthAndHeightStored: Boolean; + procedure SetAutoResize(Value: Boolean); + procedure SetBorderStyle(Value: TBorderStyle); + procedure SetCloseButton(Value: Boolean); + procedure SetCloseButtonWhenDocked(Value: Boolean); + procedure SetCurrentDock(Value: TTBDock); + procedure SetDefaultDock(Value: TTBDock); + procedure SetDockPos(Value: Integer); + procedure SetDockRow(Value: Integer); + procedure SetDragHandleStyle(Value: TTBDragHandleStyle); + procedure SetFloating(Value: Boolean); + procedure SetFloatingMode(Value: TTBFloatingMode); + procedure SetFloatingPosition(Value: TPoint); + procedure SetFullSize(Value: Boolean); + procedure SetLastDock(Value: TTBDock); + procedure SetResizable(Value: Boolean); + procedure SetShowCaption(Value: Boolean); + procedure SetStretch(Value: Boolean); + procedure SetUseLastDock(Value: Boolean); + //procedure SetVersion(const Value: TToolbar97Version); + + { Internal } + procedure CancelNCHover; + procedure DrawDraggingOutline(const DC: HDC; const NewRect, OldRect: PRect; + const NewDocking, OldDocking: Boolean); + procedure RedrawNCArea; + procedure SetCloseButtonState(Pushed: Boolean); + procedure ShowNCContextMenu(const Pos: TSmallPoint); + procedure Moved; + function GetShowingState: Boolean; + procedure UpdateCaptionState; + procedure UpdateTopmostFlag; + procedure UpdateVisibility; + procedure ReadSavedAtRunTime(Reader: TReader); + procedure WriteSavedAtRunTime(Writer: TWriter); + + { Messages } + procedure CMColorChanged(var Message: TMessage); message CM_COLORCHANGED; + procedure CMMouseLeave(var Message: TMessage); message CM_MOUSELEAVE; + procedure CMTextChanged(var Message: TMessage); message CM_TEXTCHANGED; + procedure CMShowingChanged(var Message: TMessage); message CM_SHOWINGCHANGED; + procedure CMVisibleChanged(var Message: TMessage); message CM_VISIBLECHANGED; + {$IFDEF JR_D5} + procedure WMContextMenu(var Message: TWMContextMenu); message WM_CONTEXTMENU; + {$ENDIF} + procedure WMEnable(var Message: TWMEnable); message WM_ENABLE; + procedure WMEraseBkgnd(var Message: TWMEraseBkgnd); message WM_ERASEBKGND; + procedure WMMove(var Message: TWMMove); message WM_MOVE; + procedure WMMouseMove(var Message: TMessage); message WM_MOUSEMOVE; + procedure WMNCCalcSize(var Message: TWMNCCalcSize); message WM_NCCALCSIZE; + procedure WMNCHitTest(var Message: TWMNCHitTest); message WM_NCHITTEST; + procedure WMNCMouseLeave(var Message: TMessage); message $2A2 {WM_NCMOUSELEAVE}; + procedure WMNCMouseMove(var Message: TWMNCMouseMove); message WM_NCMOUSEMOVE; + procedure WMNCLButtonDblClk(var Message: TWMNCLButtonDblClk); message WM_NCLBUTTONDBLCLK; + procedure WMNCLButtonDown(var Message: TWMNCLButtonDown); message WM_NCLBUTTONDOWN; + procedure WMNCPaint(var Message: TMessage); message WM_NCPAINT; + procedure WMNCRButtonUp(var Message: TWMNCRButtonUp); message WM_NCRBUTTONUP; + procedure WMPrint(var Message: TMessage); message WM_PRINT; + procedure WMPrintClient(var Message: TMessage); message WM_PRINTCLIENT; + procedure WMSetCursor(var Message: TWMSetCursor); message WM_SETCURSOR; + {$IFNDEF JR_D4} + procedure WMSize(var Message: TWMSize); message WM_SIZE; + {$ENDIF} + protected + property ActivateParent: Boolean read FActivateParent write FActivateParent default True; + property AutoResize: Boolean read FAutoResize write SetAutoResize default True; + property BorderStyle: TBorderStyle read FBorderStyle write SetBorderStyle default bsSingle; + property Color default clBtnFace; + property CloseButton: Boolean read FCloseButton write SetCloseButton default True; + property CloseButtonDown: Boolean read FCloseButtonDown; + property CloseButtonHover: Boolean read FCloseButtonHover; + property CloseButtonWhenDocked: Boolean read FCloseButtonWhenDocked write SetCloseButtonWhenDocked default False; + property DefaultDock: TTBDock read FDefaultDock write SetDefaultDock; + property DockableTo: TTBDockableTo read FDockableTo write FDockableTo default [dpTop, dpBottom, dpLeft, dpRight]; + property DockableWindowStyles: TTBDockableWindowStyles read FDockableWindowStyles write FDockableWindowStyles; + property DockMode: TTBDockMode read FDockMode write FDockMode default dmCanFloat; + property DragHandleStyle: TTBDragHandleStyle read FDragHandleStyle write SetDragHandleStyle default dhSingle; + property FloatingMode: TTBFloatingMode read FFloatingMode write SetFloatingMode default fmOnTopOfParentForm; + property FullSize: Boolean read FFullSize write SetFullSize default False; + property InactiveCaption: Boolean read FInactiveCaption; + property HideWhenInactive: Boolean read FHideWhenInactive write FHideWhenInactive default True; + property Resizable: Boolean read FResizable write SetResizable default True; + property ShowCaption: Boolean read FShowCaption write SetShowCaption default True; + property SmoothDrag: Boolean read FSmoothDrag write FSmoothDrag default True; + property Stretch: Boolean read FStretch write SetStretch default False; + property UseLastDock: Boolean read FUseLastDock write SetUseLastDock default True; + //property Version: TToolbar97Version read GetVersion write SetVersion stored False; + + property OnClose: TNotifyEvent read FOnClose write FOnClose; + property OnCloseQuery: TCloseQueryEvent read FOnCloseQuery write FOnCloseQuery; + property OnDockChanged: TNotifyEvent read FOnDockChanged write FOnDockChanged; + property OnDockChanging: TTBDockChangingEvent read FOnDockChanging write FOnDockChanging; + property OnDockChangingHidden: TTBDockChangingEvent read FOnDockChangingHidden write FOnDockChangingHidden; + property OnMove: TNotifyEvent read FOnMove write FOnMove; + property OnRecreated: TNotifyEvent read FOnRecreated write FOnRecreated; + property OnRecreating: TNotifyEvent read FOnRecreating write FOnRecreating; + {$IFNDEF JR_D4} + property OnResize: TNotifyEvent read FOnResize write FOnResize; + {$ENDIF} + property OnVisibleChanged: TNotifyEvent read FOnVisibleChanged write FOnVisibleChanged; + + { Overridden methods } + procedure CreateParams(var Params: TCreateParams); override; + procedure DefineProperties(Filer: TFiler); override; + function GetPalette: HPALETTE; override; + procedure Loaded; override; + procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override; + procedure Notification(AComponent: TComponent; Operation: TOperation); override; + function PaletteChanged(Foreground: Boolean): Boolean; override; + procedure SetParent(AParent: TWinControl); override; + + { Methods accessible to descendants } + procedure Arrange; + function CalcNCSizes: TPoint; virtual; + function CanDockTo(ADock: TTBDock): Boolean; virtual; + procedure ChangeSize(AWidth, AHeight: Integer); + function ChildControlTransparent(Ctl: TControl): Boolean; dynamic; + procedure Close; + procedure ControlExistsAtPos(const P: TPoint; var ControlExists: Boolean); virtual; + function DoArrange(CanMoveControls: Boolean; PreviousDockType: TTBDockType; + NewFloating: Boolean; NewDock: TTBDock): TPoint; virtual; abstract; + procedure DoDockChangingHidden(NewFloating: Boolean; DockingTo: TTBDock); dynamic; + procedure DoubleClick; + procedure DrawNCArea(const DrawToDC: Boolean; const ADC: HDC; + const Clip: HRGN); virtual; + procedure GetBaseSize(var ASize: TPoint); virtual; abstract; + function GetDockedCloseButtonRect(LeftRight: Boolean): TRect; virtual; + function GetFloatingWindowParentClass: TTBFloatingWindowParentClass; dynamic; + procedure GetMinShrinkSize(var AMinimumSize: Integer); virtual; + procedure GetMinMaxSize(var AMinClientWidth, AMinClientHeight, + AMaxClientWidth, AMaxClientHeight: Integer); virtual; + function GetShrinkMode: TTBShrinkMode; virtual; + procedure InitializeOrdering; dynamic; + function IsAutoResized: Boolean; + procedure ResizeBegin(SizeHandle: TTBSizeHandle); dynamic; + procedure ResizeEnd; dynamic; + procedure ResizeTrack(var Rect: TRect; const OrigRect: TRect); dynamic; + procedure ResizeTrackAccept; dynamic; + procedure SizeChanging(const AWidth, AHeight: Integer); virtual; + property EffectiveDockPosAccess: Integer read FEffectiveDockPos write FEffectiveDockPos; + property EffectiveDockRowAccess: Integer read FEffectiveDockRow write FEffectiveDockRow; + public + property DblClickUndock: Boolean read FDblClickUndock write FDblClickUndock default True; + property Docked: Boolean read FDocked; + property Canvas; + property CurrentDock: TTBDock read FCurrentDock write SetCurrentDock stored False; + property CurrentSize: Integer read FCurrentSize write FCurrentSize; + property DockPos: Integer read FDockPos write SetDockPos default -1; + property DockRow: Integer read FDockRow write SetDockRow default 0; + property DragMode: Boolean read FDragMode; + property DragSplitting: Boolean read FDragSplitting; + property EffectiveDockPos: Integer read FEffectiveDockPos; + property EffectiveDockRow: Integer read FEffectiveDockRow; + property Floating: Boolean read FFloating write SetFloating default False; + property FloatingPosition: TPoint read FFloatingPosition write SetFloatingPosition; + property LastDock: TTBDock read FLastDock write SetLastDock stored IsLastDockStored; + property NonClientWidth: Integer read GetNonClientWidth; + property NonClientHeight: Integer read GetNonClientHeight; + + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + function GetParentComponent: TComponent; override; + function HasParent: Boolean; override; + procedure SetBounds(ALeft, ATop, AWidth, AHeight: Integer); override; + + procedure AddDockForm(const Form: TTBCustomForm); + procedure AddDockedNCAreaToSize(var S: TPoint; const LeftRight: Boolean); + procedure AddFloatingNCAreaToSize(var S: TPoint); + procedure BeginMoving(const InitX, InitY: Integer); + procedure BeginSizing(const ASizeHandle: TTBSizeHandle); + procedure BeginUpdate; + procedure DoneReadingPositionData(const Data: TTBReadPositionData); dynamic; + procedure EndUpdate; + procedure GetDockedNCArea(var TopLeft, BottomRight: TPoint; + const LeftRight: Boolean); + function GetFloatingBorderSize: TPoint; virtual; + procedure GetFloatingNCArea(var TopLeft, BottomRight: TPoint); + function IsMovable: Boolean; + procedure MoveOnScreen(const OnlyIfFullyOffscreen: Boolean); + procedure ReadPositionData(const Data: TTBReadPositionData); dynamic; + procedure RemoveDockForm(const Form: TTBCustomForm); + procedure WritePositionData(const Data: TTBWritePositionData); dynamic; + published + property Height stored IsWidthAndHeightStored; + property Width stored IsWidthAndHeightStored; + end; + + TTBBasicBackground = class(TComponent) + protected + procedure Draw(DC: HDC; const DrawRect: TRect); virtual; abstract; + function GetPalette: HPALETTE; virtual; abstract; + procedure RegisterChanges(Proc: TNotifyEvent); virtual; abstract; + procedure SysColorChanged; virtual; abstract; + procedure UnregisterChanges(Proc: TNotifyEvent); virtual; abstract; + function UsingBackground: Boolean; virtual; abstract; + end; + + TTBBackground = class(TTBBasicBackground) + private + FBitmap, FBitmapCache: TBitmap; + FBkColor: TColor; + FNotifyList: TList; + FTransparent: Boolean; + procedure BitmapChanged(Sender: TObject); + procedure SetBitmap(Value: TBitmap); + procedure SetBkColor(Value: TColor); + procedure SetTransparent(Value: Boolean); + protected + procedure Draw(DC: HDC; const DrawRect: TRect); override; + function GetPalette: HPALETTE; override; + procedure RegisterChanges(Proc: TNotifyEvent); override; + procedure SysColorChanged; override; + procedure UnregisterChanges(Proc: TNotifyEvent); override; + function UsingBackground: Boolean; override; + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + published + property Bitmap: TBitmap read FBitmap write SetBitmap; + property BkColor: TColor read FBkColor write SetBkColor default clBtnFace; + property Transparent: Boolean read FTransparent write SetTransparent default False; + end; + +procedure TBRegLoadPositions(const OwnerComponent: TComponent; + const RootKey: DWORD; const BaseRegistryKey: String); +procedure TBRegSavePositions(const OwnerComponent: TComponent; + const RootKey: DWORD; const BaseRegistryKey: String); +procedure TBIniLoadPositions(const OwnerComponent: TComponent; + const Filename, SectionNamePrefix: String); +procedure TBIniSavePositions(const OwnerComponent: TComponent; + const Filename, SectionNamePrefix: String); + +procedure TBCustomLoadPositions(const OwnerComponent: TComponent; + const ReadIntProc: TTBPositionReadIntProc; + const ReadStringProc: TTBPositionReadStringProc; const ExtraData: Pointer); +procedure TBCustomSavePositions(const OwnerComponent: TComponent; + const WriteIntProc: TTBPositionWriteIntProc; + const WriteStringProc: TTBPositionWriteStringProc; const ExtraData: Pointer); + +function TBGetDockTypeOf(const Control: TTBDock; const Floating: Boolean): TTBDockType; +function TBGetToolWindowParentForm(const ToolWindow: TTBCustomDockableWindow): + TTBCustomForm; +function TBValidToolWindowParentForm(const ToolWindow: TTBCustomDockableWindow): + TTBCustomForm; + +implementation + +uses + Registry, IniFiles, Consts, Menus, + TB2Common, TB2Hook, TB2Consts; + +type + TControlAccess = class(TControl); + +const + DockedBorderSize = 2; + DockedBorderSize2 = DockedBorderSize*2; + DragHandleSizes: array[Boolean, TTBDragHandleStyle] of Integer = + ((9, 0, 6), (14, 14, 14)); + DragHandleXOffsets: array[Boolean, TTBDragHandleStyle] of Integer = + ((2, 0, 1), (3, 0, 5)); + HT_TB2k_Border = 2000; + HT_TB2k_Close = 2001; + HT_TB2k_Caption = 2002; + + DefaultBarWidthHeight = 8; + + ForceDockAtTopRow = 0; + ForceDockAtLeftPos = -8; + + PositionLeftOrRight = [dpLeft, dpRight]; + + twrdAll = [Low(TTBToolWindowNCRedrawWhatElement)..High(TTBToolWindowNCRedrawWhatElement)]; + + { Constants for TTBCustomDockableWindow registry values/data. + Don't localize any of these names! } + rvRev = 'Rev'; + rdCurrentRev = 2000; + rvVisible = 'Visible'; + rvDockedTo = 'DockedTo'; + rdDockedToFloating = '+'; + rvLastDock = 'LastDock'; + rvDockRow = 'DockRow'; + rvDockPos = 'DockPos'; + rvFloatLeft = 'FloatLeft'; + rvFloatTop = 'FloatTop'; + +threadvar + FloatingToolWindows: TList; + + +{ Misc. functions } + +function GetSmallCaptionHeight: Integer; +{ Returns height of the caption of a small window } +begin + Result := GetSystemMetrics(SM_CYSMCAPTION); +end; + +function GetMDIParent(const Form: TTBCustomForm): TTBCustomForm; +{ Returns the parent of the specified MDI child form. But, if Form isn't a + MDI child, it simply returns Form. } +var + I, J: Integer; +begin + Result := Form; + if Form = nil then Exit; + if {$IFDEF JR_D3} (Form is TForm) and {$ENDIF} + (TForm(Form).FormStyle = fsMDIChild) then + for I := 0 to Screen.FormCount-1 do + with Screen.Forms[I] do begin + if FormStyle <> fsMDIForm then Continue; + for J := 0 to MDIChildCount-1 do + if MDIChildren[J] = Form then begin + Result := Screen.Forms[I]; + Exit; + end; + end; +end; + +function TBGetDockTypeOf(const Control: TTBDock; const Floating: Boolean): TTBDockType; +begin + if Floating then + Result := dtFloating + else + if Control = nil then + Result := dtNotDocked + else begin + if not(Control.Position in PositionLeftOrRight) then + Result := dtTopBottom + else + Result := dtLeftRight; + end; +end; + +function TBGetToolWindowParentForm(const ToolWindow: TTBCustomDockableWindow): TTBCustomForm; +var + Ctl: TWinControl; +begin + Result := nil; + Ctl := ToolWindow; + while Assigned(Ctl.Parent) do begin + if Ctl.Parent is TTBCustomForm then + Result := TTBCustomForm(Ctl.Parent); + Ctl := Ctl.Parent; + end; + { ^ for compatibility with ActiveX controls, that code is used instead of + GetParentForm because it returns nil unless the form is the *topmost* + parent } + if Result is TTBFloatingWindowParent then + Result := TTBFloatingWindowParent(Result).ParentForm; +end; + +function TBValidToolWindowParentForm(const ToolWindow: TTBCustomDockableWindow): TTBCustomForm; +begin + Result := TBGetToolWindowParentForm(ToolWindow); + if Result = nil then + raise EInvalidOperation.{$IFDEF JR_D3}CreateFmt{$ELSE}CreateResFmt{$ENDIF} + (SParentRequired, [ToolWindow.Name]); +end; + +procedure ToolbarHookProc(Code: THookProcCode; Wnd: HWND; WParam: WPARAM; LParam: LPARAM); +var + I: Integer; + ToolWindow: TTBCustomDockableWindow; + Form: TTBCustomForm; +begin + case Code of + hpSendActivate, + hpSendActivateApp: begin + if Assigned(FloatingToolWindows) then + for I := 0 to FloatingToolWindows.Count-1 do + with TTBCustomDockableWindow(FloatingToolWindows.List[I]) do + { Hide or restore toolbars when a form or the application is + deactivated or activated, and/or update their caption state + (active/inactive) } + UpdateVisibility; + end; + hpSendWindowPosChanged: begin + if Assigned(FloatingToolWindows) then + for I := 0 to FloatingToolWindows.Count-1 do begin + ToolWindow := TTBCustomDockableWindow(FloatingToolWindows.List[I]); + with ToolWindow do begin + if (FFloatingMode = fmOnTopOfParentForm) and HandleAllocated then begin + with PWindowPos(LParam)^ do + { Call UpdateVisibility if parent form's visibility has + changed, or if it has been minimized or restored } + if ((flags and (SWP_SHOWWINDOW or SWP_HIDEWINDOW) <> 0) or + (flags and SWP_FRAMECHANGED <> 0)) then begin + Form := TBGetToolWindowParentForm(ToolWindow); + if Assigned(Form) and Form.HandleAllocated and ((Wnd = Form.Handle) or IsChild(Wnd, Form.Handle)) then + UpdateVisibility; + end; + end; + end; + end; + end; + hpPreDestroy: begin + if Assigned(FloatingToolWindows) then + for I := 0 to FloatingToolWindows.Count-1 do begin + with TTBCustomDockableWindow(FloatingToolWindows.List[I]) do + { It must remove the form window's ownership of the tool window + *before* the form gets destroyed, otherwise Windows will destroy + the tool window's handle. } + if Assigned(Parent) and Parent.HandleAllocated and + (HWND(GetWindowLong(Parent.Handle, GWL_HWNDPARENT)) = Wnd) then + SetWindowLong(Parent.Handle, GWL_HWNDPARENT, Longint(Application.Handle)); + { ^ Restore GWL_HWNDPARENT back to Application.Handle } + end; + end; + end; +end; + +type + PFindWindowData = ^TFindWindowData; + TFindWindowData = record + TaskActiveWindow, TaskFirstWindow, TaskFirstTopMost: HWND; + end; + +function DoFindWindow(Wnd: HWND; Param: Longint): Bool; stdcall; +begin + with PFindWindowData(Param)^ do + if (Wnd <> TaskActiveWindow) and (Wnd <> Application.Handle) and + IsWindowVisible(Wnd) and IsWindowEnabled(Wnd) then begin + if GetWindowLong(Wnd, GWL_EXSTYLE) and WS_EX_TOPMOST = 0 then begin + if TaskFirstWindow = 0 then TaskFirstWindow := Wnd; + end + else begin + if TaskFirstTopMost = 0 then TaskFirstTopMost := Wnd; + end; + end; + Result := True; +end; + +function FindTopLevelWindow(ActiveWindow: HWND): HWND; +var + FindData: TFindWindowData; +begin + with FindData do begin + TaskActiveWindow := ActiveWindow; + TaskFirstWindow := 0; + TaskFirstTopMost := 0; + EnumThreadWindows(GetCurrentThreadID, @DoFindWindow, Longint(@FindData)); + if TaskFirstWindow <> 0 then + Result := TaskFirstWindow + else + Result := TaskFirstTopMost; + end; +end; + +function IsAncestorOfWindow(const ParentWnd: HWND; Wnd: HWND): Boolean; +{ Returns True if Wnd is a child of, is owned by, or is the same window as + ParentWnd } +begin + while Wnd <> 0 do begin + if Wnd = ParentWnd then begin + Result := True; + Exit; + end; + Wnd := GetParent(Wnd); + end; + Result := False; +end; + +procedure RecalcNCArea(const Ctl: TWinControl); +begin + if Ctl.HandleAllocated then + SetWindowPos(Ctl.Handle, 0, 0, 0, 0, 0, SWP_FRAMECHANGED or + SWP_NOACTIVATE or SWP_NOMOVE or SWP_NOSIZE or SWP_NOZORDER); +end; + +procedure InvalidateAll(const Ctl: TWinControl); +{ Invalidate both non-client and client area, and erase. } +begin + if Ctl.HandleAllocated then + RedrawWindow(Ctl.Handle, nil, 0, RDW_FRAME or RDW_INVALIDATE or + RDW_ERASE or RDW_NOCHILDREN); +end; + +type + TSetCloseButtonStateProc = procedure(Pushed: Boolean) of object; + +function CloseButtonLoop(const Wnd: HWND; const ButtonRect: TRect; + const SetCloseButtonStateProc: TSetCloseButtonStateProc): Boolean; + function MouseInButton: Boolean; + var + P: TPoint; + begin + GetCursorPos(P); + Result := PtInRect(ButtonRect, P); + end; +var + Msg: TMsg; +begin + Result := False; + + SetCloseButtonStateProc(MouseInButton); + + SetCapture(Wnd); + + try + while GetCapture = Wnd do begin + case Integer(GetMessage(Msg, 0, 0, 0)) of + -1: Break; { if GetMessage failed } + 0: begin + { Repost WM_QUIT messages } + PostQuitMessage(Msg.WParam); + Break; + end; + end; + + case Msg.Message of + WM_KEYDOWN, WM_KEYUP: + { Ignore all keystrokes while in a close button loop } + ; + WM_MOUSEMOVE: begin + { Note to self: WM_MOUSEMOVE messages should never be dispatched + here to ensure no hints get shown } + SetCloseButtonStateProc(MouseInButton); + end; + WM_LBUTTONDOWN, WM_LBUTTONDBLCLK: + { Make sure it doesn't begin another loop } + Break; + WM_LBUTTONUP: begin + if MouseInButton then + Result := True; + Break; + end; + WM_RBUTTONDOWN..WM_MBUTTONDBLCLK: + { Ignore all other mouse up/down messages } + ; + else + TranslateMessage(Msg); + DispatchMessage(Msg); + end; + end; + finally + if GetCapture = Wnd then + ReleaseCapture; + SetCloseButtonStateProc(False); + end; +end; + + +{ TTBDock - internal } + +constructor TTBDock.Create(AOwner: TComponent); +begin + inherited; + + ControlStyle := ControlStyle + [csAcceptsControls, csMenuEvents] - + [csClickEvents, csCaptureMouse, csOpaque]; + FAllowDrag := True; + FBkgOnToolbars := True; + DockList := TList.Create; + DockVisibleList := TList.Create; + Color := clBtnFace; + Position := dpTop; +end; + +procedure TTBDock.CreateParams(var Params: TCreateParams); +begin + inherited; + { Disable complete redraws when size changes. CS_H/VREDRAW cause flicker + and are not necessary for this control at run time } + if not(csDesigning in ComponentState) then + with Params.WindowClass do + Style := Style and not(CS_HREDRAW or CS_VREDRAW); +end; + +destructor TTBDock.Destroy; +begin + if Assigned(FBackground) then + FBackground.UnregisterChanges(BackgroundChanged); + inherited; + DockVisibleList.Free; + DockList.Free; +end; + +procedure TTBDock.SetParent(AParent: TWinControl); +begin + if (AParent is TTBCustomDockableWindow) or (AParent is TTBDock) then + raise EInvalidOperation.Create(STBDockParentNotAllowed); + + inherited; +end; + +procedure TTBDock.BeginUpdate; +begin + Inc(FDisableArrangeToolbars); +end; + +procedure TTBDock.EndUpdate; +begin + Dec(FDisableArrangeToolbars); + if FArrangeToolbarsNeeded and (FDisableArrangeToolbars = 0) then + ArrangeToolbars; +end; + +function TTBDock.HasVisibleToolbars: Boolean; +var + I: Integer; +begin + Result := False; + for I := 0 to DockList.Count-1 do + if ToolbarVisibleOnDock(TTBCustomDockableWindow(DockList[I])) then begin + Result := True; + Break; + end; +end; + +function TTBDock.ToolbarVisibleOnDock(const AToolbar: TTBCustomDockableWindow): Boolean; +begin + Result := (AToolbar.Parent = Self) and + (AToolbar.Visible or (csDesigning in AToolbar.ComponentState)); +end; + +function TTBDock.GetCurrentRowSize(const Row: Integer; + var AFullSize: Boolean): Integer; +var + I, J: Integer; + T: TTBCustomDockableWindow; +begin + Result := 0; + AFullSize := False; + if Row < 0 then Exit; + for I := 0 to DockList.Count-1 do begin + T := DockList[I]; + if (T.FEffectiveDockRow = Row) and ToolbarVisibleOnDock(T) then begin + AFullSize := T.FullSize; + if not(Position in PositionLeftOrRight) then + J := T.Height + else + J := T.Width; + if J > Result then + Result := J; + end; + end; +end; + +function TTBDock.GetMinRowSize(const Row: Integer; + const ExcludeControl: TTBCustomDockableWindow): Integer; +var + I, J: Integer; + T: TTBCustomDockableWindow; +begin + Result := 0; + if Row < 0 then Exit; + for I := 0 to DockList.Count-1 do begin + T := DockList[I]; + if (T <> ExcludeControl) and (T.FEffectiveDockRow = Row) and + ToolbarVisibleOnDock(T) then begin + J := T.FLastRowSize; + if J > Result then + Result := J; + end; + end; +end; + +function TTBDock.GetDesignModeRowOf(const XY: Integer): Integer; +{ Similar to GetRowOf, but is a little different to accomidate design mode + better } +var + HighestRowPlus1, R, CurY, CurRowSize: Integer; + FullSize: Boolean; +begin + Result := 0; + HighestRowPlus1 := GetHighestRow(True)+1; + CurY := 0; + for R := 0 to HighestRowPlus1 do begin + Result := R; + if R = HighestRowPlus1 then Break; + CurRowSize := GetCurrentRowSize(R, FullSize); + if CurRowSize = 0 then Continue; + Inc(CurY, CurRowSize); + if XY < CurY then + Break; + end; +end; + +function TTBDock.GetHighestRow(const HighestEffective: Boolean): Integer; +{ Returns highest used row number, or -1 if no rows are used } +var + I, J: Integer; +begin + Result := -1; + for I := 0 to DockList.Count-1 do + with TTBCustomDockableWindow(DockList[I]) do begin + if HighestEffective then + J := FEffectiveDockRow + else + J := FDockRow; + if J > Result then + Result := J; + end; +end; + +procedure TTBDock.ChangeWidthHeight(const NewWidth, NewHeight: Integer); +{ Same as setting Width/Height directly, but does not lose Align position. } +begin + case Align of + alNone, alTop, alLeft: + SetBounds(Left, Top, NewWidth, NewHeight); + alBottom: + SetBounds(Left, Top-NewHeight+Height, NewWidth, NewHeight); + alRight: + SetBounds(Left-NewWidth+Width, Top, NewWidth, NewHeight); + end; +end; + +function TTBDock.Accepts(ADockableWindow: TTBCustomDockableWindow): Boolean; +begin + Result := AllowDrag; +end; + +procedure TTBDock.AlignControls(AControl: TControl; var Rect: TRect); +begin + ArrangeToolbars; +end; + +function CompareDockRowPos(const Item1, Item2, ExtraData: Pointer): Integer; far; +begin + if TTBCustomDockableWindow(Item1).FDockRow <> TTBCustomDockableWindow(Item2).FDockRow then + Result := TTBCustomDockableWindow(Item1).FDockRow - TTBCustomDockableWindow(Item2).FDockRow + else + Result := TTBCustomDockableWindow(Item1).FDockPos - TTBCustomDockableWindow(Item2).FDockPos; +end; + +procedure TTBDock.ArrangeToolbars; +{ The main procedure to arrange all the toolbars docked to it } +type + PPosDataRec = ^TPosDataRec; + TPosDataRec = record + Row, ActualRow, PrecSpace, FullSize, MinimumSize, Size, Overlap, Pos: Integer; + ShrinkMode: TTBShrinkMode; + NeedArrange: Boolean; + end; + PPosDataArray = ^TPosDataArray; + TPosDataArray = array[0..$7FFFFFFF div SizeOf(TPosDataRec)-1] of TPosDataRec; +var + NewDockList: TList; + PosData: PPosDataArray; + + function IndexOfDraggingToolbar(const List: TList): Integer; + { Returns index of toolbar in List that's currently being dragged, or -1 } + var + I: Integer; + begin + for I := 0 to List.Count-1 do + if TTBCustomDockableWindow(List[I]).FDragMode then begin + Result := I; + Exit; + end; + Result := -1; + end; + + function ShiftLeft(const Row, StartIndex, MaxSize: Integer): Integer; + { Removes PrecSpace pixels from toolbars at or before StartIndex until the + right edge of the toolbar at StartIndex is <= MaxSize. + Returns the total number of PrecSpace pixels removed from toolbars. } + var + PixelsOffEdge, I, J: Integer; + P: PPosDataRec; + begin + Result := 0; + PixelsOffEdge := -MaxSize; + for I := 0 to StartIndex do begin + P := @PosData[I]; + if P.Row = Row then begin + Inc(PixelsOffEdge, P.PrecSpace); + Inc(PixelsOffEdge, P.Size); + end; + end; + if PixelsOffEdge > 0 then + for I := StartIndex downto 0 do begin + P := @PosData[I]; + if P.Row = Row then begin + J := PixelsOffEdge; + if P.PrecSpace < J then + J := P.PrecSpace; + Dec(P.PrecSpace, J); + Dec(PixelsOffEdge, J); + Inc(Result, J); + if PixelsOffEdge = 0 then + Break; + end; + end; + end; + + function GetNextToolbar(const GoForward: Boolean; const Row: Integer; + const StartIndex: Integer): Integer; + var + I: Integer; + begin + Result := -1; + I := StartIndex; + while True do begin + if GoForward then begin + Inc(I); + if I >= NewDockList.Count then + Break; + end + else begin + Dec(I); + if I < 0 then + Break; + end; + if PosData[I].Row = Row then begin + Result := I; + Break; + end; + end; + end; + +var + LeftRight: Boolean; + EmptySize, HighestRow, R, CurPos, CurRowPixel, I, J, K, L, ClientW, + ClientH, MaxSize, TotalSize, PixelsPastMaxSize, Offset, CurRealPos, DragIndex, + MinRealPos, DragIndexPos, ToolbarsOnRow, CurRowSize: Integer; + P: PPosDataRec; + T: TTBCustomDockableWindow; + S: TPoint; + RowIsEmpty: Boolean; +label FoundNextToolbar; +begin + if (FDisableArrangeToolbars > 0) or (csLoading in ComponentState) then begin + FArrangeToolbarsNeeded := True; + Exit; + end; + + NewDockList := nil; + PosData := nil; + Inc(FDisableArrangeToolbars); + try + { Work around VCL alignment bug when docking toolbars taller or wider than + the client height or width of the form. } + {if not(csDesigning in ComponentState) and HandleAllocated then + SetWindowPos(Handle, HWND_TOP, 0, 0, 0, 0, + SWP_NOACTIVATE or SWP_NOMOVE or SWP_NOSIZE);} + + LeftRight := Position in PositionLeftOrRight; + + if not HasVisibleToolbars then begin + EmptySize := Ord(FFixAlign); + if csDesigning in ComponentState then + EmptySize := 9; + if not LeftRight then + ChangeWidthHeight(Width, EmptySize) + else + ChangeWidthHeight(EmptySize, Height); + Exit; + end; + + { It can't read the ClientWidth and ClientHeight properties because they + attempt to create a handle, which requires Parent to be set. "ClientW" + and "ClientH" are calculated instead. } + ClientW := Width - FNonClientWidth; + if ClientW < 0 then ClientW := 0; + ClientH := Height - FNonClientHeight; + if ClientH < 0 then ClientH := 0; + + { Remove toolbars from DockList & DockVisibleList that are destroying, so + that no methods on these toolbars will be called. + This is needed because in certain rare cases ArrangeToolbars can be + indirectly called while a docked toolbar is being destroyed. } + for I := DockList.Count-1 downto 0 do begin + T := DockList[I]; + if csDestroying in T.ComponentState then begin + DockList.Delete(I); + DockVisibleList.Remove(T); + end; + end; + + { If LimitToOneRow is True, only use the first row } + if FLimitToOneRow then + for I := 0 to DockList.Count-1 do + with TTBCustomDockableWindow(DockList[I]) do + FDockRow := 0; + + { Copy DockList to NewDockList, and ensure it is in correct ordering + according to DockRow/DockPos } + NewDockList := TList.Create; + NewDockList.Count := DockList.Count; + for I := 0 to NewDockList.Count-1 do + NewDockList[I] := DockList[I]; + I := IndexOfDraggingToolbar(NewDockList); + ListSortEx(NewDockList, CompareDockRowPos, nil); + DragIndex := IndexOfDraggingToolbar(NewDockList); + if (I <> -1) and TTBCustomDockableWindow(NewDockList[DragIndex]).FDragSplitting then begin + { When splitting, don't allow the toolbar being dragged to change + positions in the dock list } + NewDockList.Move(DragIndex, I); + DragIndex := I; + end; + ListSortEx(DockVisibleList, CompareDockRowPos, nil); + { Find highest row number } + HighestRow := GetHighestRow(False); + + { Create a temporary array that holds new position data for the toolbars } + PosData := AllocMem(NewDockList.Count * SizeOf(TPosDataRec)); + for I := 0 to NewDockList.Count-1 do begin + P := @PosData[I]; + T := NewDockList[I]; + P.ActualRow := T.FDockRow; + if ToolbarVisibleOnDock(T) then + P.Row := T.FDockRow + else + P.Row := -1; + P.Pos := T.FDockPos; + end; + + { Find FInsertRowBefore=True and FullSize=True toolbars and make sure there + aren't any other toolbars on the same row. If there are, shift them down + a row. } + for L := 0 to 1 do begin + R := 0; + while R <= HighestRow do begin + for I := 0 to NewDockList.Count-1 do begin + T := NewDockList[I]; + if (PosData[I].ActualRow = R) and + (((L = 0) and T.FInsertRowBefore and not LimitToOneRow) or + ((L = 1) and T.FullSize)) then + for J := 0 to NewDockList.Count-1 do + if (J <> I) and (PosData[J].ActualRow = R) then begin + for K := 0 to NewDockList.Count-1 do begin + if K <> I then begin + P := @PosData[K]; + if P.ActualRow >= R then + Inc(P.ActualRow); + if P.Row >= R then + Inc(P.Row); + end; + end; + Inc(HighestRow); + Break; + end; + end; + Inc(R); + end; + end; + + { Remove blank rows. + Note that rows that contain only invisible or currently floating toolbars + are intentionally not removed, so that when the toolbars are shown again, + they stay on their own row. } + R := 0; + while R <= HighestRow do begin + RowIsEmpty := True; + for I := 0 to NewDockList.Count-1 do + if PosData[I].ActualRow = R then begin + RowIsEmpty := False; + Break; + end; + if RowIsEmpty then begin + { Shift all ones higher than R back one } + for I := 0 to NewDockList.Count-1 do begin + if PosData[I].ActualRow > R then + Dec(PosData[I].ActualRow); + if PosData[I].Row > R then + Dec(PosData[I].Row); + end; + Dec(HighestRow); + end + else + Inc(R); + end; + + { Calculate positions and sizes of each row } + R := 0; + while R <= HighestRow do begin + if not LeftRight then + MaxSize := ClientW + else + MaxSize := ClientH; + + { Set initial sizes } + TotalSize := 0; + ToolbarsOnRow := 0; + MinRealPos := 0; + for I := 0 to NewDockList.Count-1 do begin + P := @PosData[I]; + if P.Row = R then begin + T := NewDockList[I]; + T.GetBaseSize(S); + if not LeftRight then + J := S.X + T.NonClientWidth + else + J := S.Y + T.NonClientHeight; + P.FullSize := J; + P.Size := J; + P.ShrinkMode := T.GetShrinkMode; + P.MinimumSize := 0; + T.GetMinShrinkSize(P.MinimumSize); + if P.MinimumSize > P.FullSize then + { don't allow minimum shrink size to be less than full size } + P.MinimumSize := P.FullSize; + if P.ShrinkMode = tbsmChevron then + Inc(MinRealPos, P.MinimumSize) + else + Inc(MinRealPos, P.FullSize); + { If the toolbar isn't the first toolbar on the row, and the toolbar + would go off the edge even after it's shrunk, then move it onto a + row of its own } + if (ToolbarsOnRow > 0) and (MinRealPos > MaxSize) and + not LimitToOneRow then begin + for K := I to NewDockList.Count-1 do begin + P := @PosData[K]; + if P.ActualRow >= R then + Inc(P.ActualRow); + if P.Row >= R then + Inc(P.Row); + end; + Inc(HighestRow); + Break; + end; + Inc(TotalSize, J); + Inc(ToolbarsOnRow); + end; + end; + PixelsPastMaxSize := TotalSize - MaxSize; + + { Set initial arrangement; don't shrink toolbars yet } + DragIndexPos := 0; + CurPos := 0; + CurRealPos := 0; + MinRealPos := 0; + for I := 0 to NewDockList.Count-1 do begin + P := @PosData[I]; + T := NewDockList[I]; + if P.Row = R then begin + if (CurPos = 0) and (T.FullSize or T.Stretch) then + { Force to left } + J := 0 + else + J := T.FDockPos; + if I = DragIndex then + DragIndexPos := J; + { Don't let this toolbar overlap preceding toolbars by more than + the sum of their minimum sizes } + if J < MinRealPos then + J := MinRealPos; + if J > CurPos then begin + { There's a gap between the left edge or previous toolbar and + this toolbar } + if PixelsPastMaxSize <= 0 then begin + P.PrecSpace := J - CurPos; + CurPos := J; + end + else + { Don't allow a gap if exceeding MaxSize } + J := CurPos; + end + else begin + if J < CurRealPos then + P.Overlap := CurRealPos - J; + end; + + Inc(CurPos, P.Size); + CurRealPos := J + P.Size; + Inc(MinRealPos, P.MinimumSize); + end; + end; + + { If we aren't exceeding MaxSize, allow the toolbar being dragged + to push other toolbars to the left } + if (PixelsPastMaxSize < 0) and (DragIndex <> -1) and + (PosData[DragIndex].Row = R) then begin + I := GetNextToolbar(False, R, DragIndex); + if I <> -1 then begin + J := ShiftLeft(R, I, DragIndexPos); + if J > 0 then begin + { Ensure that toolbars that follow the toolbar being dragged stay + at the same place by increasing PrecSpace on the next toolbar } + I := GetNextToolbar(True, R, DragIndex); + if I <> -1 then + Inc(PosData[I].PrecSpace, J); + end; + end; + end; + + { If any toolbars are going off the edge of the dock, try to make them + at least partially visible by shifting preceding toolbars left } + I := GetNextToolbar(False, R, NewDockList.Count); + if I <> -1 then + ShiftLeft(R, I, MaxSize); + + { Shrink toolbars that overlap other toolbars (Overlaps[x] > 0) } + if PixelsPastMaxSize > 0 then begin + Offset := 0; + for I := 0 to NewDockList.Count-1 do begin + if PosData[I].Row <> R then + Continue; + T := NewDockList[I]; + if (ToolbarsOnRow > 1) and T.FDragMode then + T.FDragCanSplit := True; + Inc(Offset, PosData[I].Overlap); + if Offset > PixelsPastMaxSize then + Offset := PixelsPastMaxSize; + if Offset > 0 then + for J := I-1 downto 0 do begin + P := @PosData[J]; + if P.Row <> R then + Continue; + { How much can we shrink this toolbar J to get toolbar I to + its preferred position? } + if P.ShrinkMode = tbsmChevron then + L := Offset + else + L := 0; + K := -(P.Size - L - P.MinimumSize); { the number of pixels that exceed the minimum size } + if K > 0 then + { Don't shrink a toolbar below its minimum allowed size } + Dec(L, K); + Dec(P.Size, L); + Dec(PixelsPastMaxSize, L); + Dec(Offset, L); + if (Offset = 0) or + { This is needed so toolbars can push other toolbars to the + right when splitting: } + (J = DragIndex) then + Break; + end; + end; + end; + + { Still exceeding MaxSize? Make sure the rightmost toolbar(s) are + at least partially visible with a width of MinimumSize } + if PixelsPastMaxSize > 0 then begin + for I := NewDockList.Count-1 downto 0 do begin + P := @PosData[I]; + if (P.Row <> R) or (P.ShrinkMode = tbsmNone) or + ((P.ShrinkMode = tbsmWrap) and (ToolbarsOnRow > 1)) then + Continue; + J := P.Size - P.MinimumSize; + if J > 0 then begin { can we shrink this toolbar any? } + if J > PixelsPastMaxSize then + J := PixelsPastMaxSize; + Dec(P.Size, J); + Dec(PixelsPastMaxSize, J); + end; + if PixelsPastMaxSize = 0 then + Break; + end; + end; + + { Set Poses, and adjust size of FullSize & Stretch toolbars } + CurPos := 0; + for I := 0 to NewDockList.Count-1 do begin + P := @PosData[I]; + T := NewDockList[I]; + if P.Row = R then begin + if T.FullSize or T.Stretch then begin + { Remove any preceding space from this toolbar } + Inc(P.Size, P.PrecSpace); + P.PrecSpace := 0; + end; + Inc(CurPos, P.PrecSpace); + if T.FullSize then begin + { Claim all space } + if P.Size < MaxSize then + P.Size := MaxSize; + end + else if T.Stretch then begin + { Steal any preceding space from the next toolbar } + for J := I+1 to NewDockList.Count-1 do + if PosData[J].Row = R then begin + Inc(P.Size, PosData[J].PrecSpace); + PosData[J].PrecSpace := 0; + goto FoundNextToolbar; + end; + { or claim any remaining space } + if P.Size < MaxSize - CurPos then + P.Size := MaxSize - CurPos; + FoundNextToolbar: + end; + P.Pos := CurPos; + Inc(CurPos, P.Size); + end; + end; + + Inc(R); + end; + + for I := 0 to NewDockList.Count-1 do begin + T := NewDockList[I]; + T.FEffectiveDockRow := PosData[I].ActualRow; + T.FEffectiveDockPos := PosData[I].Pos; + { If FCommitNewPositions is True, update all the toolbars' DockPos and + DockRow properties to match the actual positions. + Also update the ordering of DockList to match NewDockList } + if FCommitNewPositions then begin + T.FDockRow := T.FEffectiveDockRow; + T.FDockPos := T.FEffectiveDockPos; + DockList[I] := NewDockList[I]; + end; + end; + + { Now actually move the toolbars } + CurRowPixel := 0; + for R := 0 to HighestRow do begin + CurRowSize := 0; + for I := 0 to NewDockList.Count-1 do begin + P := @PosData[I]; + T := NewDockList[I]; + if P.Row = R then begin + K := T.FCurrentSize; + T.FCurrentSize := P.Size; + if P.Size >= P.FullSize then begin + T.FCurrentSize := 0; + { Reason: so that if new items are added to a non-shrunk toolbar + at run-time (causing its width to increase), the toolbar won't + shrink unnecessarily } + end; + if (P.ShrinkMode <> tbsmNone) and (T.FCurrentSize <> K) then begin + { If Size is changing and we are to display a chevron or wrap, + call DoArrange to get an accurate row size } + S := T.DoArrange(False, TBGetDockTypeOf(Self, False), False, Self); + { Force a rearrange in case the actual size isn't changing but the + chevron visibility might have changed (which can happen if + items are added to a FullSize=True toolbar at run-time) } + P.NeedArrange := True; + end + else begin + if (P.ShrinkMode = tbsmWrap) and (P.Size < P.FullSize) then begin + { Preserve existing height (or width) on a wrapped toolbar + whose size isn't changing now } + S.X := T.Width - T.NonClientWidth; + S.Y := T.Height - T.NonClientHeight; + end + else + T.GetBaseSize(S); + end; + if not LeftRight then + K := S.Y + else + K := S.X; + T.FLastRowSize := K; + if K > CurRowSize then + CurRowSize := K; + end; + end; + if CurRowSize <> 0 then + Inc(CurRowSize, DockedBorderSize2); + for I := 0 to NewDockList.Count-1 do begin + P := @PosData[I]; + T := NewDockList[I]; + if P.Row = R then begin + Inc(T.FUpdatingBounds); + try + K := T.FCurrentSize; + if P.NeedArrange then + T.FArrangeNeeded := True; + if not LeftRight then + T.SetBounds(P.Pos, CurRowPixel, P.Size, CurRowSize) + else + T.SetBounds(CurRowPixel, P.Pos, CurRowSize, P.Size); + if T.FArrangeNeeded then + { ^ don't arrange again if SetBounds call already caused one } + T.Arrange; + { Restore FCurrentSize since TTBToolbarView.DoUpdatePositions + clears it } + T.FCurrentSize := K; + finally + Dec(T.FUpdatingBounds); + end; + end; + end; + Inc(CurRowPixel, CurRowSize); + end; + + { Set the size of the dock } + if not LeftRight then + ChangeWidthHeight(Width, CurRowPixel + FNonClientHeight) + else + ChangeWidthHeight(CurRowPixel + FNonClientWidth, Height); + finally + Dec(FDisableArrangeToolbars); + FArrangeToolbarsNeeded := False; + FCommitNewPositions := False; + FreeMem(PosData); + NewDockList.Free; + end; +end; + +procedure TTBDock.CommitPositions; +{ Copies docked toolbars' EffectiveDockRow and EffectiveDockPos properties + into DockRow and DockPos respectively. + Note that this does not reorder DockList like ArrangeToolbars does when + FCommitNewPositions=True. } +var + I: Integer; + T: TTBCustomDockableWindow; +begin + for I := 0 to DockVisibleList.Count-1 do begin + T := DockVisibleList[I]; + T.FDockRow := T.FEffectiveDockRow; + T.FDockPos := T.FEffectiveDockPos; + end; +end; + +procedure TTBDock.ChangeDockList(const Insert: Boolean; + const Bar: TTBCustomDockableWindow); +{ Inserts or removes Bar from DockList } +var + I: Integer; +begin + I := DockList.IndexOf(Bar); + if Insert then begin + if I = -1 then begin + Bar.FreeNotification(Self); + DockList.Add(Bar); + end; + end + else begin + if I <> -1 then + DockList.Delete(I); + end; + ToolbarVisibilityChanged(Bar, False); +end; + +procedure TTBDock.ToolbarVisibilityChanged(const Bar: TTBCustomDockableWindow; + const ForceRemove: Boolean); +var + Modified, VisibleOnDock: Boolean; + I: Integer; +begin + Modified := False; + I := DockVisibleList.IndexOf(Bar); + VisibleOnDock := not ForceRemove and ToolbarVisibleOnDock(Bar); + if VisibleOnDock then begin + if I = -1 then begin + DockVisibleList.Add(Bar); + Modified := True; + end; + end + else begin + if I <> -1 then begin + DockVisibleList.Remove(Bar); + Modified := True; + end; + end; + + if Modified then begin + ArrangeToolbars; + + if Assigned(FOnInsertRemoveBar) then + FOnInsertRemoveBar(Self, VisibleOnDock, Bar); + end; +end; + +procedure TTBDock.Loaded; +begin + inherited; + { Rearranging is disabled while the component is loading, so now that it's + loaded, rearrange it. } + ArrangeToolbars; +end; + +procedure TTBDock.Notification(AComponent: TComponent; Operation: TOperation); +begin + inherited; + if Operation = opRemove then begin + if AComponent = FBackground then + Background := nil + else if AComponent is TTBCustomDockableWindow then begin + DockList.Remove(AComponent); + DockVisibleList.Remove(AComponent); + end; + end; +end; + +function TTBDock.GetPalette: HPALETTE; +begin + if UsingBackground and Assigned(FBackground) then + { ^ by default UsingBackground returns False if FBackground isn't assigned, + but UsingBackground may be overridden and return True when it isn't } + Result := FBackground.GetPalette + else + Result := 0; +end; + +procedure TTBDock.WMEraseBkgnd(var Message: TWMEraseBkgnd); +var + R, R2: TRect; + P1, P2: TPoint; + SaveIndex: Integer; +begin + { Draw the Background if there is one, otherwise use default erasing + behavior } + if UsingBackground then begin + R := ClientRect; + R2 := R; + { Make up for nonclient area } + P1 := ClientToScreen(Point(0, 0)); + P2 := Parent.ClientToScreen(BoundsRect.TopLeft); + Dec(R2.Left, Left + (P1.X-P2.X)); + Dec(R2.Top, Top + (P1.Y-P2.Y)); + SaveIndex := SaveDC(Message.DC); + IntersectClipRect(Message.DC, R.Left, R.Top, R.Right, R.Bottom); + DrawBackground(Message.DC, R2); + RestoreDC(Message.DC, SaveIndex); + Message.Result := 1; + end + else + inherited; +end; + +procedure TTBDock.Paint; +var + R: TRect; +begin + inherited; + { Draw dotted border in design mode } + if csDesigning in ComponentState then begin + R := ClientRect; + with Canvas do begin + Pen.Style := psDot; + Pen.Color := clBtnShadow; + Brush.Style := bsClear; + Rectangle(R.Left, R.Top, R.Right, R.Bottom); + Pen.Style := psSolid; + end; + end; +end; + +procedure TTBDock.WMMove(var Message: TWMMove); +begin + inherited; + if UsingBackground then + InvalidateBackgrounds; +end; + +{$IFNDEF JR_D4} +procedure TTBDock.WMSize(var Message: TWMSize); +begin + inherited; + if not(csLoading in ComponentState) and Assigned(FOnResize) then + FOnResize(Self); +end; +{$ENDIF} + +procedure TTBDock.WMNCCalcSize(var Message: TWMNCCalcSize); +begin + inherited; + { note to self: non-client size is stored in FNonClientWidth & + FNonClientHeight } + with Message.CalcSize_Params^.rgrc[0] do begin + if blTop in BoundLines then Inc(Top); + if blBottom in BoundLines then Dec(Bottom); + if blLeft in BoundLines then Inc(Left); + if blRight in BoundLines then Dec(Right); + end; +end; + +procedure TTBDock.DrawNCArea(const DrawToDC: Boolean; const ADC: HDC; + const Clip: HRGN); + + procedure DrawLine(const DC: HDC; const X1, Y1, X2, Y2: Integer); + begin + MoveToEx(DC, X1, Y1, nil); LineTo(DC, X2, Y2); + end; +var + RW, R, R2, RC: TRect; + DC: HDC; + HighlightPen, ShadowPen, SavePen: HPEN; + FillBrush: HBRUSH; +label 1; +begin + { This works around WM_NCPAINT problem described at top of source code } + {no! R := Rect(0, 0, Width, Height);} + GetWindowRect(Handle, RW); + R := RW; + OffsetRect(R, -R.Left, -R.Top); + + if not DrawToDC then + DC := GetWindowDC(Handle) + else + DC := ADC; + try + { Use update region } + if not DrawToDC then + SelectNCUpdateRgn(Handle, DC, Clip); + + { Draw BoundLines } + R2 := R; + if (BoundLines <> []) and + ((csDesigning in ComponentState) or HasVisibleToolbars) then begin + HighlightPen := CreatePen(PS_SOLID, 1, GetSysColor(COLOR_BTNHIGHLIGHT)); + ShadowPen := CreatePen(PS_SOLID, 1, GetSysColor(COLOR_BTNSHADOW)); + SavePen := SelectObject(DC, ShadowPen); + if blTop in BoundLines then begin + DrawLine(DC, R.Left, R.Top, R.Right, R.Top); + Inc(R2.Top); + end; + if blLeft in BoundLines then begin + DrawLine(DC, R.Left, R.Top, R.Left, R.Bottom); + Inc(R2.Left); + end; + SelectObject(DC, HighlightPen); + if blBottom in BoundLines then begin + DrawLine(DC, R.Left, R.Bottom-1, R.Right, R.Bottom-1); + Dec(R2.Bottom); + end; + if blRight in BoundLines then begin + DrawLine(DC, R.Right-1, R.Top, R.Right-1, R.Bottom); + Dec(R2.Right); + end; + SelectObject(DC, SavePen); + DeleteObject(ShadowPen); + DeleteObject(HighlightPen); + end; + Windows.GetClientRect(Handle, RC); + if not IsRectEmpty(RC) then begin + { ^ ExcludeClipRect can't be passed rectangles that have (Bottom < Top) or + (Right < Left) since it doesn't treat them as empty } + MapWindowPoints(Handle, 0, RC, 2); + OffsetRect(RC, -RW.Left, -RW.Top); + if EqualRect(RC, R2) then + { Skip FillRect because there would be nothing left after ExcludeClipRect } + goto 1; + ExcludeClipRect(DC, RC.Left, RC.Top, RC.Right, RC.Bottom); + end; + FillBrush := CreateSolidBrush(ColorToRGB(Color)); + FillRect(DC, R2, FillBrush); + DeleteObject(FillBrush); + 1: + finally + if not DrawToDC then + ReleaseDC(Handle, DC); + end; +end; + +procedure TTBDock.WMNCPaint(var Message: TMessage); +begin + DrawNCArea(False, 0, HRGN(Message.WParam)); +end; + +procedure DockNCPaintProc(Wnd: HWND; DC: HDC; AppData: Longint); +begin + TTBDock(AppData).DrawNCArea(True, DC, 0); +end; + +procedure TTBDock.WMPrint(var Message: TMessage); +begin + HandleWMPrint(Handle, Message, DockNCPaintProc, Longint(Self)); +end; + +procedure TTBDock.WMPrintClient(var Message: TMessage); +begin + HandleWMPrintClient(Self, Message); +end; + +procedure TTBDock.CMSysColorChange(var Message: TMessage); +begin + inherited; + if Assigned(FBackground) then + FBackground.SysColorChanged; +end; + +procedure TTBDock.RelayMsgToFloatingBars(var Message: TMessage); +var + I: Integer; + T: TTBCustomDockableWindow; +begin + for I := 0 to DockList.Count-1 do begin + T := DockList[I]; + if (csMenuEvents in T.ControlStyle) and T.Floating and T.Showing and + T.Enabled then begin + Message.Result := T.Perform(Message.Msg, Message.WParam, Message.LParam); + if Message.Result <> 0 then + Exit; + end; + end; +end; + +procedure TTBDock.WMSysCommand(var Message: TWMSysCommand); +begin + { Relay WM_SYSCOMMAND messages to floating toolbars which were formerly + docked. That way, items on floating menu bars can be accessed with Alt. } + RelayMsgToFloatingBars(TMessage(Message)); +end; + +procedure TTBDock.CMDialogKey(var Message: TCMDialogKey); +begin + RelayMsgToFloatingBars(TMessage(Message)); + if Message.Result = 0 then + inherited; +end; + +procedure TTBDock.CMDialogChar(var Message: TCMDialogChar); +begin + RelayMsgToFloatingBars(TMessage(Message)); + if Message.Result = 0 then + inherited; +end; + +{ TTBDock - property access methods } + +procedure TTBDock.SetAllowDrag(Value: Boolean); +var + I: Integer; +begin + if FAllowDrag <> Value then begin + FAllowDrag := Value; + for I := 0 to ControlCount-1 do + if Controls[I] is TTBCustomDockableWindow then + RecalcNCArea(TTBCustomDockableWindow(Controls[I])); + end; +end; + +function TTBDock.UsingBackground: Boolean; +begin + Result := Assigned(FBackground) and FBackground.UsingBackground; +end; + +procedure TTBDock.DrawBackground(DC: HDC; const DrawRect: TRect); +begin + FBackground.Draw(DC, DrawRect); +end; + +procedure TTBDock.InvalidateBackgrounds; +{ Called after background is changed } +var + I: Integer; + T: TTBCustomDockableWindow; +begin + Invalidate; + { Synchronize child toolbars also } + for I := 0 to DockList.Count-1 do begin + T := TTBCustomDockableWindow(DockList[I]); + if ToolbarVisibleOnDock(T) then + { Invalidate both non-client and client area } + InvalidateAll(T); + end; +end; + +procedure TTBDock.SetBackground(Value: TTBBasicBackground); +begin + if FBackground <> Value then begin + if Assigned(FBackground) then + FBackground.UnregisterChanges(BackgroundChanged); + FBackground := Value; + if Assigned(Value) then begin + Value.FreeNotification(Self); + Value.RegisterChanges(BackgroundChanged); + end; + InvalidateBackgrounds; + end; +end; + +procedure TTBDock.BackgroundChanged(Sender: TObject); +begin + InvalidateBackgrounds; +end; + +procedure TTBDock.SetBackgroundOnToolbars(Value: Boolean); +begin + if FBkgOnToolbars <> Value then begin + FBkgOnToolbars := Value; + InvalidateBackgrounds; + end; +end; + +procedure TTBDock.SetBoundLines(Value: TTBDockBoundLines); +var + X, Y: Integer; + B: TTBDockBoundLines; +begin + if FBoundLines <> Value then begin + FBoundLines := Value; + X := 0; + Y := 0; + B := BoundLines; { optimization } + if blTop in B then Inc(Y); + if blBottom in B then Inc(Y); + if blLeft in B then Inc(X); + if blRight in B then Inc(X); + FNonClientWidth := X; + FNonClientHeight := Y; + RecalcNCArea(Self); + end; +end; + +procedure TTBDock.SetFixAlign(Value: Boolean); +begin + if FFixAlign <> Value then begin + FFixAlign := Value; + ArrangeToolbars; + end; +end; + +procedure TTBDock.SetPosition(Value: TTBDockPosition); +begin + if (FPosition <> Value) and (ControlCount <> 0) then + raise EInvalidOperation.Create(STBDockCannotChangePosition); + FPosition := Value; + case Position of + dpTop: Align := alTop; + dpBottom: Align := alBottom; + dpLeft: Align := alLeft; + dpRight: Align := alRight; + end; +end; + +function TTBDock.GetToolbarCount: Integer; +begin + Result := DockVisibleList.Count; +end; + +function TTBDock.GetToolbars(Index: Integer): TTBCustomDockableWindow; +begin + Result := TTBCustomDockableWindow(DockVisibleList[Index]); +end; + +(*function TTBDock.GetVersion: TToolbar97Version; +begin + Result := Toolbar97VersionPropText; +end; + +procedure TTBDock.SetVersion(const Value: TToolbar97Version); +begin + { write method required for the property to show up in Object Inspector } +end;*) + + +{ TTBFloatingWindowParent - Internal } + +constructor TTBFloatingWindowParent.Create(AOwner: TComponent); +begin + { Don't use TForm's Create since it attempts to load a form resource, which + TTBFloatingWindowParent doesn't have. } + CreateNew(AOwner {$IFDEF VER93} , 0 {$ENDIF}); +end; + +destructor TTBFloatingWindowParent.Destroy; +begin + inherited; +end; + +procedure TTBFloatingWindowParent.CreateParams(var Params: TCreateParams); +const + ThickFrames: array[Boolean] of DWORD = (0, WS_THICKFRAME); +begin + inherited; + + { Disable complete redraws when size changes. CS_H/VREDRAW cause flicker + and are not necessary for this control at run time } + if not(csDesigning in ComponentState) then + with Params.WindowClass do + Style := Style and not(CS_HREDRAW or CS_VREDRAW); + + with Params do begin + { Note: WS_THICKFRAME and WS_BORDER styles are included to ensure that + sizing grips are displayed on child controls with scrollbars. The + thick frame or border is not drawn by Windows; TCustomToolWindow97 + handles all border drawing by itself. } + if not(csDesigning in ComponentState) then + Style := WS_POPUP or WS_BORDER or ThickFrames[FDockableWindow.FResizable] + else + Style := Style or WS_BORDER or ThickFrames[FDockableWindow.FResizable]; + { The WS_EX_TOOLWINDOW style is needed so there isn't a taskbar button + for the toolbar when FloatingMode = fmOnTopOfAllForms. } + ExStyle := WS_EX_TOOLWINDOW; + end; +end; + +procedure TTBFloatingWindowParent.AlignControls(AControl: TControl; var Rect: TRect); +begin + { ignore Align setting of the child toolbar } +end; + +procedure TTBFloatingWindowParent.WMGetMinMaxInfo(var Message: TWMGetMinMaxInfo); +begin + inherited; + { Because the window uses the WS_THICKFRAME style (but not for the usual + purpose), it must process the WM_GETMINMAXINFO message to remove the + minimum and maximum size limits it imposes by default. } + with Message.MinMaxInfo^ do begin + with ptMinTrackSize do begin + X := 1; + Y := 1; + { Note to self: Don't put GetMinimumSize code here, since + ClientWidth/Height values are sometimes invalid during a RecreateWnd } + end; + with ptMaxTrackSize do begin + { Because of the 16-bit (signed) size limitations of Windows 95, + Smallints must be used instead of Integers or Longints } + X := High(Smallint); + Y := High(Smallint); + end; + end; +end; + +procedure TTBFloatingWindowParent.CMShowingChanged(var Message: TMessage); +const + ShowFlags: array[Boolean] of UINT = ( + SWP_NOSIZE or SWP_NOMOVE or SWP_NOZORDER or SWP_NOACTIVATE or SWP_HIDEWINDOW, + SWP_NOSIZE or SWP_NOMOVE or SWP_NOZORDER or SWP_NOACTIVATE or SWP_SHOWWINDOW); +begin + { Must override TCustomForm/TForm's CM_SHOWINGCHANGED handler so that the + form doesn't get activated when Visible is set to True. } + SetWindowPos(WindowHandle, 0, 0, 0, 0, 0, ShowFlags[Showing and FShouldShow]); +end; + +procedure TTBFloatingWindowParent.CMDialogKey(var Message: TCMDialogKey); +begin + { If Escape if pressed on a floating toolbar, return focus to the form } + if (Message.CharCode = VK_ESCAPE) and (KeyDataToShiftState(Message.KeyData) = []) and + Assigned(ParentForm) then begin + ParentForm.SetFocus; + Message.Result := 1; + end + else + inherited; +end; + +procedure TTBFloatingWindowParent.CMTextChanged(var Message: TMessage); +begin + inherited; + RedrawNCArea([twrdCaption]); +end; + +function GetCaptionRect(const Control: TTBFloatingWindowParent; + const AdjustForBorder, MinusCloseButton: Boolean): TRect; +begin + Result := Rect(0, 0, Control.ClientWidth, GetSmallCaptionHeight-1); + if MinusCloseButton then + Dec(Result.Right, Result.Bottom); + if AdjustForBorder then + with Control.FDockableWindow.GetFloatingBorderSize do + OffsetRect(Result, X, Y); +end; + +function GetCloseButtonRect(const Control: TTBFloatingWindowParent; + const AdjustForBorder: Boolean): TRect; +begin + Result := GetCaptionRect(Control, AdjustForBorder, False); + Result.Left := Result.Right - (GetSmallCaptionHeight-1); +end; + +procedure TTBFloatingWindowParent.WMNCCalcSize(var Message: TWMNCCalcSize); +var + TL, BR: TPoint; +begin + { Doesn't call inherited since it overrides the normal NC sizes } + Message.Result := 0; + with Message.CalcSize_Params^ do begin + FDockableWindow.GetFloatingNCArea(TL, BR); + with rgrc[0] do begin + Inc(Left, TL.X); + Inc(Top, TL.Y); + Dec(Right, BR.X); + Dec(Bottom, BR.Y); + end; + end; +end; + +procedure TTBFloatingWindowParent.WMNCPaint(var Message: TMessage); +begin + { Don't call inherited because it overrides the default NC painting } + DrawNCArea(False, 0, HRGN(Message.WParam), twrdAll); +end; + +procedure FloatingWindowParentNCPaintProc(Wnd: HWND; DC: HDC; AppData: Longint); +begin + with TTBFloatingWindowParent(AppData) do + DrawNCArea(True, DC, 0, twrdAll); +end; + +procedure TTBFloatingWindowParent.WMPrint(var Message: TMessage); +begin + HandleWMPrint(Handle, Message, FloatingWindowParentNCPaintProc, Longint(Self)); +end; + +procedure TTBFloatingWindowParent.WMPrintClient(var Message: TMessage); +begin + HandleWMPrintClient(Self, Message); +end; + +procedure TTBFloatingWindowParent.WMNCHitTest(var Message: TWMNCHitTest); +var + P: TPoint; + R: TRect; + BorderSize: TPoint; + C: Integer; +begin + inherited; + with Message do begin + P := SmallPointToPoint(Pos); + GetWindowRect(Handle, R); + Dec(P.X, R.Left); Dec(P.Y, R.Top); + if Result <> HTCLIENT then begin + Result := HTNOWHERE; + if FDockableWindow.ShowCaption and PtInRect(GetCaptionRect(Self, True, False), P) then begin + if FDockableWindow.FCloseButton and PtInRect(GetCloseButtonRect(Self, True), P) then + Result := HT_TB2k_Close + else + Result := HT_TB2k_Caption; + end + else + if FDockableWindow.Resizable then begin + BorderSize := FDockableWindow.GetFloatingBorderSize; + if not(tbdsResizeEightCorner in FDockableWindow.FDockableWindowStyles) then begin + if (P.Y >= 0) and (P.Y < BorderSize.Y) then Result := HTTOP else + if (P.Y < Height) and (P.Y >= Height-BorderSize.Y-1) then Result := HTBOTTOM else + if (P.X >= 0) and (P.X < BorderSize.X) then Result := HTLEFT else + if (P.X < Width) and (P.X >= Width-BorderSize.X-1) then Result := HTRIGHT; + end + else begin + C := BorderSize.X + (GetSmallCaptionHeight-1); + if (P.X >= 0) and (P.X < BorderSize.X) then begin + Result := HTLEFT; + if (P.Y < C) then Result := HTTOPLEFT else + if (P.Y >= Height-C) then Result := HTBOTTOMLEFT; + end + else + if (P.X < Width) and (P.X >= Width-BorderSize.X-1) then begin + Result := HTRIGHT; + if (P.Y < C) then Result := HTTOPRIGHT else + if (P.Y >= Height-C) then Result := HTBOTTOMRIGHT; + end + else + if (P.Y >= 0) and (P.Y < BorderSize.Y) then begin + Result := HTTOP; + if (P.X < C) then Result := HTTOPLEFT else + if (P.X >= Width-C) then Result := HTTOPRIGHT; + end + else + if (P.Y < Height) and (P.Y >= Height-BorderSize.Y-1) then begin + Result := HTBOTTOM; + if (P.X < C) then Result := HTBOTTOMLEFT else + if (P.X >= Width-C) then Result := HTBOTTOMRIGHT; + end; + end; + end; + end; + end; +end; + +procedure TTBFloatingWindowParent.SetCloseButtonState(Pushed: Boolean); +begin + if FCloseButtonDown <> Pushed then begin + FCloseButtonDown := Pushed; + RedrawNCArea([twrdCloseButton]); + end; +end; + +procedure TTBFloatingWindowParent.WMNCLButtonDown(var Message: TWMNCLButtonDown); +var + P: TPoint; + R, BR: TRect; +begin + case Message.HitTest of + HT_TB2k_Caption: begin + P := FDockableWindow.ScreenToClient(Point(Message.XCursor, Message.YCursor)); + FDockableWindow.BeginMoving(P.X, P.Y); + end; + HTLEFT..HTBOTTOMRIGHT: + if FDockableWindow.Resizable then + FDockableWindow.BeginSizing(TTBSizeHandle(Message.HitTest - HTLEFT)); + HT_TB2k_Close: begin + GetWindowRect(Handle, R); + BR := GetCloseButtonRect(Self, True); + OffsetRect(BR, R.Left, R.Top); + if CloseButtonLoop(Handle, BR, SetCloseButtonState) then + FDockableWindow.Close; + end; + else + inherited; + end; +end; + +procedure TTBFloatingWindowParent.WMNCLButtonDblClk(var Message: TWMNCLButtonDblClk); +begin + if Message.HitTest = HT_TB2k_Caption then + FDockableWindow.DoubleClick; +end; + +procedure TTBFloatingWindowParent.WMNCRButtonUp(var Message: TWMNCRButtonUp); +begin + FDockableWindow.ShowNCContextMenu(TSmallPoint(TMessage(Message).LParam)); +end; + +procedure TTBFloatingWindowParent.WMClose(var Message: TWMClose); +var + MDIParentForm: TTBCustomForm; +begin + { A floating toolbar does not use WM_CLOSE messages when its close button + is clicked, but Windows still sends a WM_CLOSE message if the user + presses Alt+F4 while one of the toolbar's controls is focused. Inherited + is not called since we do not want Windows' default processing - which + destroys the window. Instead, relay the message to the parent form. } + MDIParentForm := GetMDIParent(TBGetToolWindowParentForm(FDockableWindow)); + if Assigned(MDIParentForm) and MDIParentForm.HandleAllocated then + SendMessage(MDIParentForm.Handle, WM_CLOSE, 0, 0); + { Note to self: MDIParentForm is used instead of OwnerForm since MDI + childs don't process Alt+F4 as Close } +end; + +procedure TTBFloatingWindowParent.WMActivate(var Message: TWMActivate); +var + ParentForm: TTBCustomForm; +begin + if csDesigning in ComponentState then begin + inherited; + Exit; + end; + + ParentForm := GetMDIParent(TBGetToolWindowParentForm(FDockableWindow)); + + if Assigned(ParentForm) and ParentForm.HandleAllocated then + SendMessage(ParentForm.Handle, WM_NCACTIVATE, Ord(Message.Active <> WA_INACTIVE), 0); + + if Message.Active <> WA_INACTIVE then begin + { This works around a "gotcha" in TCustomForm.CMShowingChanged. When a form + is hidden, it uses the internal VCL function FindTopMostWindow to + find a new active window. The problem is that handles of floating + toolbars on the form being hidden can be returned by + FindTopMostWindow, so the following code is used to prevent floating + toolbars on the hidden form from being left active. } + if not IsWindowVisible(Handle) then + { ^ Calling IsWindowVisible with a floating toolbar handle will + always return False if its parent form is hidden since the + WH_CALLWNDPROC hook automatically updates the toolbars' + visibility. } + { Find and activate a window besides this toolbar } + SetActiveWindow(FindTopLevelWindow(Handle)) + else + { If the toolbar is being activated and the previous active window wasn't + its parent form, the form is activated instead. This is done so that if + the application is deactivated while a floating toolbar was active and + the application is reactivated again, it returns focus to the form. } + if Assigned(ParentForm) and ParentForm.HandleAllocated and + (Message.ActiveWindow <> ParentForm.Handle) then + SetActiveWindow(ParentForm.Handle); + end; +end; + +procedure TTBFloatingWindowParent.WMMouseActivate(var Message: TWMMouseActivate); +var + ParentForm, MDIParentForm: TTBCustomForm; +begin + if csDesigning in ComponentState then begin + inherited; + Exit; + end; + + { When floating, prevent the toolbar from activating when clicked. + This is so it doesn't take the focus away from the window that had it } + Message.Result := MA_NOACTIVATE; + + { Similar to calling BringWindowToTop, but doesn't activate it } + SetWindowPos(Handle, HWND_TOP, 0, 0, 0, 0, + SWP_NOACTIVATE or SWP_NOMOVE or SWP_NOSIZE); + + { Since it is returning MA_NOACTIVATE, activate the form instead. } + ParentForm := TBGetToolWindowParentForm(FDockableWindow); + MDIParentForm := GetMDIParent(ParentForm); + if (FDockableWindow.FFloatingMode = fmOnTopOfParentForm) and + FDockableWindow.FActivateParent and + Assigned(MDIParentForm) and (GetActiveWindow <> Handle) then begin + { ^ Note to self: The GetActiveWindow check must be in there so that + double-clicks work properly on controls like Edits } + if MDIParentForm.HandleAllocated then + SetActiveWindow(MDIParentForm.Handle); + if (MDIParentForm <> ParentForm) and { if it's an MDI child form } + ParentForm.HandleAllocated then + BringWindowToTop(ParentForm.Handle); + end; +end; + +procedure TTBFloatingWindowParent.WMMove(var Message: TWMMove); +begin + inherited; + FDockableWindow.Moved; +end; + +procedure TTBFloatingWindowParent.DrawNCArea(const DrawToDC: Boolean; + const ADC: HDC; const Clip: HRGN; RedrawWhat: TTBToolWindowNCRedrawWhat); +{ Redraws all the non-client area (the border, title bar, and close button) of + the toolbar when it is floating. } +const + COLOR_GRADIENTACTIVECAPTION = 27; + COLOR_GRADIENTINACTIVECAPTION = 28; + CaptionBkColors: array[Boolean, Boolean] of Integer = + ((COLOR_ACTIVECAPTION, COLOR_INACTIVECAPTION), + (COLOR_GRADIENTACTIVECAPTION, COLOR_GRADIENTINACTIVECAPTION)); + CaptionTextColors: array[Boolean] of Integer = + (COLOR_CAPTIONTEXT, COLOR_INACTIVECAPTIONTEXT); + + function GradientCaptionsEnabled: Boolean; + const + SPI_GETGRADIENTCAPTIONS = $1008; { Win98/NT5 only } + var + S: BOOL; + begin + Result := SystemParametersInfo(SPI_GETGRADIENTCAPTIONS, 0, @S, 0) and S; + end; + +const + CloseButtonState: array[Boolean] of UINT = (0, DFCS_PUSHED); + ActiveCaptionFlags: array[Boolean] of UINT = (DC_ACTIVE, 0); + DC_GRADIENT = $20; + GradientCaptionFlags: array[Boolean] of UINT = (0, DC_GRADIENT); +var + DC: HDC; + R, R2: TRect; + Gradient: Boolean; + SavePen: HPEN; + SaveIndex: Integer; + S: TPoint; +begin + if not HandleAllocated then Exit; + + if not DrawToDC then + DC := GetWindowDC(Handle) + else + DC := ADC; + try + { Use update region } + if not DrawToDC then + SelectNCUpdateRgn(Handle, DC, Clip); + + { Work around an apparent NT 4.0 & 2000 bug. If the width of the DC is + greater than the width of the screen, then any call to ExcludeClipRect + inexplicably shrinks the clipping rectangle to the screen width. I've + found that calling IntersectClipRect as done below magically fixes the + problem (but I'm not sure why). } + GetWindowRect(Handle, R); OffsetRect(R, -R.Left, -R.Top); + IntersectClipRect(DC, R.Left, R.Top, R.Right, R.Bottom); + + Gradient := GradientCaptionsEnabled; + + { Border } + if twrdBorder in RedrawWhat then begin + { This works around WM_NCPAINT problem described at top of source code } + {no! R := Rect(0, 0, Width, Height);} + GetWindowRect(Handle, R); OffsetRect(R, -R.Left, -R.Top); + DrawEdge(DC, R, EDGE_RAISED, BF_RECT); + SaveIndex := SaveDC(DC); + S := FDockableWindow.GetFloatingBorderSize; + with R do + ExcludeClipRect(DC, Left + S.X, Top + S.Y, Right - S.X, Bottom - S.Y); + InflateRect(R, -2, -2); + FillRect(DC, R, GetSysColorBrush(COLOR_BTNFACE)); + RestoreDC(DC, SaveIndex); + end; + + if FDockableWindow.ShowCaption then begin + if (twrdCaption in RedrawWhat) and FDockableWindow.FCloseButton and + (twrdCloseButton in RedrawWhat) then + SaveIndex := SaveDC(DC) + else + SaveIndex := 0; + try + if SaveIndex <> 0 then + with GetCloseButtonRect(Self, True) do + { Reduces flicker } + ExcludeClipRect(DC, Left, Top, Right, Bottom); + + { Caption } + if twrdCaption in RedrawWhat then begin + R := GetCaptionRect(Self, True, FDockableWindow.FCloseButton); + { Note that Delphi's Win32 help for DrawCaption is totally wrong! + I got updated info from www.microsoft.com/msdn/sdk/ } + DrawCaption(Handle, DC, R, DC_TEXT or DC_SMALLCAP or + ActiveCaptionFlags[FDockableWindow.FInactiveCaption] or + GradientCaptionFlags[Gradient]); + + { Line below caption } + R := GetCaptionRect(Self, True, False); + SavePen := SelectObject(DC, CreatePen(PS_SOLID, 1, GetSysColor(COLOR_BTNFACE))); + MoveToEx(DC, R.Left, R.Bottom, nil); + LineTo(DC, R.Right, R.Bottom); + DeleteObject(SelectObject(DC, SavePen)); + end; + finally + if SaveIndex <> 0 then + RestoreDC(DC, SaveIndex); + end; + + { Close button } + if FDockableWindow.FCloseButton then begin + R := GetCloseButtonRect(Self, True); + R2 := R; + InflateRect(R2, 0, -2); + Dec(R2.Right, 2); + if twrdCaption in RedrawWhat then begin + SaveIndex := SaveDC(DC); + ExcludeClipRect(DC, R2.Left, R2.Top, R2.Right, R2.Bottom); + FillRect(DC, R, GetSysColorBrush(CaptionBkColors[Gradient, + FDockableWindow.FInactiveCaption])); + RestoreDC(DC, SaveIndex); + end; + if twrdCloseButton in RedrawWhat then + DrawFrameControl(DC, R2, DFC_CAPTION, DFCS_CAPTIONCLOSE or + CloseButtonState[FCloseButtonDown]); + end; + end; + finally + if not DrawToDC then + ReleaseDC(Handle, DC); + end; +end; + +procedure TTBFloatingWindowParent.RedrawNCArea(const RedrawWhat: TTBToolWindowNCRedrawWhat); +begin + { Note: IsWindowVisible is called as an optimization. There's no need to + draw on invisible windows. } + if HandleAllocated and IsWindowVisible(Handle) then + DrawNCArea(False, 0, 0, RedrawWhat); +end; + + +{ TTBCustomDockableWindow } + +constructor TTBCustomDockableWindow.Create(AOwner: TComponent); +begin + inherited; + + ControlStyle := ControlStyle + + [csAcceptsControls, csClickEvents, csDoubleClicks, csSetCaption] - + [csCaptureMouse{capturing is done manually}, csOpaque]; + FAutoResize := True; + FActivateParent := True; + FBorderStyle := bsSingle; + FCloseButton := True; + FDblClickUndock := True; + FDockableTo := [dpTop, dpBottom, dpLeft, dpRight]; + FDockableWindowStyles := [tbdsResizeEightCorner, tbdsResizeClipCursor]; + FDockPos := -1; + FDragHandleStyle := dhSingle; + FEffectiveDockRow := -1; + FHideWhenInactive := True; + FResizable := True; + FShowCaption := True; + FSmoothDrag := True; + FUseLastDock := True; + + Color := clBtnFace; + + if not(csDesigning in ComponentState) then + InstallHookProc(Self, ToolbarHookProc, [hpSendActivate, hpSendActivateApp, + hpSendWindowPosChanged, hpPreDestroy]); + InitTrackMouseEvent; +end; + +destructor TTBCustomDockableWindow.Destroy; +begin + inherited; + FDockForms.Free; { must be done after 'inherited' because Notification accesses FDockForms } + FFloatParent.Free; + UninstallHookProc(Self, ToolbarHookProc); +end; + +function TTBCustomDockableWindow.HasParent: Boolean; +begin + if Parent is TTBFloatingWindowParent then + Result := False + else + Result := inherited HasParent; +end; + +function TTBCustomDockableWindow.GetParentComponent: TComponent; +begin + if Parent is TTBFloatingWindowParent then + Result := nil + else + Result := inherited GetParentComponent; +end; + +procedure TTBCustomDockableWindow.Moved; +begin + if not(csLoading in ComponentState) and Assigned(FOnMove) and (FDisableOnMove <= 0) then + FOnMove(Self); +end; + +procedure TTBCustomDockableWindow.WMMove(var Message: TWMMove); + + procedure Redraw; + { Redraws the control using an off-screen bitmap to avoid flicker } + var + CR, R: TRect; + W: HWND; + DC, BmpDC: HDC; + Bmp: HBITMAP; + begin + if not HandleAllocated then Exit; + CR := ClientRect; + W := Handle; + if GetUpdateRect(W, R, False) and EqualRect(R, CR) then begin + { The client area is already completely invalid, so don't bother using + an off-screen bitmap } + InvalidateAll(Self); + Exit; + end; + BmpDC := 0; + Bmp := 0; + DC := GetDC(W); + try + BmpDC := CreateCompatibleDC(DC); + Bmp := CreateCompatibleBitmap(DC, CR.Right, CR.Bottom); + SelectObject(BmpDC, Bmp); + SendMessage(W, WM_NCPAINT, 0, 0); + SendMessage(W, WM_ERASEBKGND, WPARAM(BmpDC), 0); + SendMessage(W, WM_PAINT, WPARAM(BmpDC), 0); + BitBlt(DC, 0, 0, CR.Right, CR.Bottom, BmpDC, 0, 0, SRCCOPY); + finally + if BmpDC <> 0 then DeleteDC(BmpDC); + if Bmp <> 0 then DeleteObject(Bmp); + ReleaseDC(W, DC); + end; + ValidateRect(W, nil); + end; + +begin + inherited; + FMoved := True; + if Docked and CurrentDock.UsingBackground then begin + { Needs to redraw so that the background is lined up with the dock at the + new position. } + Redraw; + end; + Moved; +end; + +{$IFNDEF JR_D4} +procedure TTBCustomDockableWindow.WMSize(var Message: TWMSize); +begin + inherited; + if not(csLoading in ComponentState) and Assigned(FOnResize) then + FOnResize(Self); +end; +{$ENDIF} + +procedure TTBCustomDockableWindow.WMEnable(var Message: TWMEnable); +begin + inherited; + { When a modal dialog is displayed and the toolbar window gets disabled as + a result, remove its topmost flag. } + if FFloatingMode = fmOnTopOfAllForms then + UpdateTopmostFlag; +end; + +procedure TTBCustomDockableWindow.UpdateCaptionState; +{ Updates the caption active/inactive state of a floating tool window. + Called when the tool window is visible or is about to be shown. } + + function IsPopupWindowActive: Boolean; + const + IID_ITBPopupWindow: TGUID = '{E45CBE74-1ECF-44CB-B064-6D45B1924708}'; + var + Ctl: TWinControl; + begin + Ctl := FindControl(GetActiveWindow); + { Instead of using "is TTBPopupWindow", which would require linking to the + TB2Item unit, check if the control implements the ITBPopupWindow + interface. This will tell us if it's a TTBPopupWindow or descendant. } + Result := Assigned(Ctl) and Assigned(Ctl.GetInterfaceEntry(IID_ITBPopupWindow)); + end; + + function GetActiveFormWindow: HWND; + var + Ctl: TWinControl; + begin + Result := GetActiveWindow; + { If the active window is a TTBFloatingWindowParent (i.e. a control on a + floating toolbar is focused), return the parent form handle instead } + Ctl := FindControl(Result); + if Assigned(Ctl) and (Ctl is TTBFloatingWindowParent) then begin + Ctl := TTBFloatingWindowParent(Ctl).ParentForm; + if Assigned(Ctl) and Ctl.HandleAllocated then + Result := Ctl.Handle; + end; + end; + +var + Inactive: Boolean; + ActiveWnd: HWND; +begin + { Update caption state if floating, but not if a control on a popup window + (e.g. a TTBEditItem) is currently focused; we don't want the captions on + all floating toolbars to turn gray in that case. (The caption state will + get updated when we're called the next time the active window changes, + i.e. when the user dismisses the popup window.) } + if (Parent is TTBFloatingWindowParent) and Parent.HandleAllocated and + not IsPopupWindowActive then begin + Inactive := False; + if not ApplicationIsActive then + Inactive := True + else if (FFloatingMode = fmOnTopOfParentForm) and + (HWND(GetWindowLong(Parent.Handle, GWL_HWNDPARENT)) <> Application.Handle) then begin + { Use inactive caption if the active window doesn't own the float parent + (directly or indirectly). Note: For compatibility with browser-embedded + TActiveForms, we use IsAncestorOfWindow instead of checking + TBGetToolWindowParentForm. } + ActiveWnd := GetActiveFormWindow; + if (ActiveWnd = 0) or not IsAncestorOfWindow(ActiveWnd, Parent.Handle) then + Inactive := True; + end; + if FInactiveCaption <> Inactive then begin + FInactiveCaption := Inactive; + TTBFloatingWindowParent(Parent).RedrawNCArea(twrdAll); + end; + end; +end; + +function TTBCustomDockableWindow.GetShowingState: Boolean; + + function IsWindowVisibleAndNotMinimized(Wnd: HWND): Boolean; + begin + Result := IsWindowVisible(Wnd); + if Result then begin + { Wnd may not be a top-level window (e.g. in the case of an MDI child + form, or an ActiveForm embedded in a web page), so go up the chain of + parent windows and see if any of them are minimized } + repeat + if IsIconic(Wnd) then begin + Result := False; + Break; + end; + { Stop if we're at a top-level window (no need to check owner windows) } + if GetWindowLong(Wnd, GWL_STYLE) and WS_CHILD = 0 then + Break; + Wnd := GetParent(Wnd); + until Wnd = 0; + end; + end; + +var + HideFloatingToolbars: Boolean; + ParentForm: TTBCustomForm; +begin + Result := Showing and (FHidden = 0); + if Floating and not(csDesigning in ComponentState) then begin + HideFloatingToolbars := FFloatingMode = fmOnTopOfParentForm; + if HideFloatingToolbars then begin + ParentForm := TBGetToolWindowParentForm(Self); + if Assigned(ParentForm) and ParentForm.HandleAllocated and + IsWindowVisibleAndNotMinimized(ParentForm.Handle) then + HideFloatingToolbars := False; + end; + Result := Result and not (HideFloatingToolbars or (FHideWhenInactive and not ApplicationIsActive)); + end; +end; + +procedure TTBCustomDockableWindow.UpdateVisibility; +{ Updates the visibility of the tool window, and additionally the caption + state if floating and showing } +var + IsVisible: Boolean; +begin + if HandleAllocated then begin + IsVisible := IsWindowVisible(Handle); + if IsVisible <> GetShowingState then begin + Perform(CM_SHOWINGCHANGED, 0, 0); + { Note: CMShowingChanged will call UpdateCaptionState automatically + when floating and showing } + end + else if IsVisible and Floating then begin + { If we're floating and we didn't send the CM_SHOWINGCHANGED message + then we have to call UpdateCaptionState manually } + UpdateCaptionState; + end; + end; +end; + +function IsTopmost(const Wnd: HWND): Boolean; +begin + Result := GetWindowLong(Wnd, GWL_EXSTYLE) and WS_EX_TOPMOST <> 0; +end; + +procedure TTBCustomDockableWindow.UpdateTopmostFlag; +const + Wnds: array[Boolean] of HWND = (HWND_NOTOPMOST, HWND_TOPMOST); +var + ShouldBeTopmost: Boolean; +begin + if HandleAllocated then begin + if FFloatingMode = fmOnTopOfAllForms then + ShouldBeTopmost := IsWindowEnabled(Handle) + else + ShouldBeTopmost := IsTopmost(HWND(GetWindowLong(Parent.Handle, GWL_HWNDPARENT))); + if ShouldBeTopmost <> IsTopmost(Parent.Handle) then + { ^ it must check if it already was topmost or non-topmost or else + it causes problems on Win95/98 for some reason } + SetWindowPos(Parent.Handle, Wnds[ShouldBeTopmost], 0, 0, 0, 0, + SWP_NOACTIVATE or SWP_NOMOVE or SWP_NOSIZE); + end; +end; + +procedure TTBCustomDockableWindow.CMShowingChanged(var Message: TMessage); + + function GetPrevWnd(W: HWND): HWND; + var + WasTopmost, Done: Boolean; + ParentWnd: HWND; + begin + WasTopmost := IsTopmost(Parent.Handle); + Result := W; + repeat + Done := True; + Result := GetWindow(Result, GW_HWNDPREV); + ParentWnd := Result; + while ParentWnd <> 0 do begin + if WasTopmost and not IsTopmost(ParentWnd) then begin + Done := False; + Break; + end; + ParentWnd := HWND(GetWindowLong(ParentWnd, GWL_HWNDPARENT)); + if ParentWnd = W then begin + Done := False; + Break; + end; + end; + until Done; + end; + +const + ShowFlags: array[Boolean] of UINT = ( + SWP_NOSIZE or SWP_NOMOVE or SWP_NOZORDER or SWP_NOACTIVATE or SWP_HIDEWINDOW, + SWP_NOSIZE or SWP_NOMOVE or SWP_NOZORDER or SWP_NOACTIVATE or SWP_SHOWWINDOW); +var + Show: Boolean; + Form: TTBCustomForm; +begin + { inherited isn't called since TTBCustomDockableWindow handles CM_SHOWINGCHANGED + itself. For reference, the original TWinControl implementation is: + const + ShowFlags: array[Boolean] of Word = ( + SWP_NOSIZE + SWP_NOMOVE + SWP_NOZORDER + SWP_NOACTIVATE + SWP_HIDEWINDOW, + SWP_NOSIZE + SWP_NOMOVE + SWP_NOZORDER + SWP_NOACTIVATE + SWP_SHOWWINDOW); + begin + SetWindowPos(FHandle, 0, 0, 0, 0, 0, ShowFlags[FShowing]); + end; + } + if HandleAllocated then begin + Show := GetShowingState; + if Parent is TTBFloatingWindowParent then begin + if Show then begin + { If the toolbar is floating, set its "owner window" to the parent form + so that the toolbar window always stays on top of the form } + if FFloatingMode = fmOnTopOfParentForm then begin + Form := GetMDIParent(TBGetToolWindowParentForm(Self)); + if Assigned(Form) and Form.HandleAllocated and + (HWND(GetWindowLong(Parent.Handle, GWL_HWNDPARENT)) <> Form.Handle) then begin + SetWindowLong(Parent.Handle, GWL_HWNDPARENT, Longint(Form.Handle)); + { Following is necessarily to make it immediately realize the + GWL_HWNDPARENT change } + SetWindowPos(Parent.Handle, GetPrevWnd(Form.Handle), 0, 0, 0, 0, SWP_NOACTIVATE or + SWP_NOMOVE or SWP_NOSIZE); + end; + end + else begin + SetWindowLong(Parent.Handle, GWL_HWNDPARENT, Longint(Application.Handle)); + end; + { Initialize caption state after setting owner but before showing } + UpdateCaptionState; + end; + UpdateTopmostFlag; + { Show/hide the TTBFloatingWindowParent. The following lines had to be + added to fix a problem that was in 1.65d/e. In 1.65d/e, it always + kept TTBFloatingWindowParent visible (this change was made to improve + compatibility with D4's Actions), but this for some odd reason would + cause a Stack Overflow error if the program's main form was closed + while a floating toolwindow was focused. (This problem did not occur + on NT.) } + TTBFloatingWindowParent(Parent).FShouldShow := Show; + Parent.Perform(CM_SHOWINGCHANGED, 0, 0); + end; + SetWindowPos(Handle, 0, 0, 0, 0, 0, ShowFlags[Show]); + if not Show and (GetActiveWindow = Handle) then + { If the window is hidden but is still active, find and activate a + different window } + SetActiveWindow(FindTopLevelWindow(Handle)); + end; +end; + +procedure TTBCustomDockableWindow.CreateParams(var Params: TCreateParams); +begin + inherited; + + { Disable complete redraws when size changes. CS_H/VREDRAW cause flicker + and are not necessary for this control at run time } + if not(csDesigning in ComponentState) then + with Params.WindowClass do + Style := Style and not(CS_HREDRAW or CS_VREDRAW); +end; + +procedure TTBCustomDockableWindow.Notification(AComponent: TComponent; Operation: TOperation); +begin + inherited; + if Operation = opRemove then begin + if AComponent = FDefaultDock then + FDefaultDock := nil + else + if AComponent = FLastDock then + FLastDock := nil + else begin + RemoveFromList(FDockForms, AComponent); + if Assigned(FFloatParent) and (csDestroying in FFloatParent.ComponentState) and + (AComponent = FFloatParent.FParentForm) then begin + { ^ Note: Must check csDestroying so that we are sure that FFloatParent + is actually being destroyed and not just being removed from its + Owner's component list } + if Parent = FFloatParent then begin + if FFloatingMode = fmOnTopOfParentForm then + Parent := nil + else + FFloatParent.FParentForm := nil; + end + else begin + FFloatParent.Free; + FFloatParent := nil; + end; + end; + end; + end; +end; + +procedure TTBCustomDockableWindow.MoveOnScreen(const OnlyIfFullyOffscreen: Boolean); +{ Moves the (floating) toolbar so that it is fully (or at least mostly) in + view on the screen } +var + R, S, Test: TRect; +begin + if Floating then begin + R := Parent.BoundsRect; + S := GetRectOfMonitorContainingRect(R, True); + + if OnlyIfFullyOffscreen and IntersectRect(Test, R, S) then + Exit; + + if R.Right > S.Right then + OffsetRect(R, S.Right - R.Right, 0); + if R.Bottom > S.Bottom then + OffsetRect(R, 0, S.Bottom - R.Bottom); + if R.Left < S.Left then + OffsetRect(R, S.Left - R.Left, 0); + if R.Top < S.Top then + OffsetRect(R, 0, S.Top - R.Top); + Parent.BoundsRect := R; + end; +end; + +procedure TTBCustomDockableWindow.ReadPositionData(const Data: TTBReadPositionData); +begin +end; + +procedure TTBCustomDockableWindow.DoneReadingPositionData(const Data: TTBReadPositionData); +begin +end; + +procedure TTBCustomDockableWindow.WritePositionData(const Data: TTBWritePositionData); +begin +end; + +procedure TTBCustomDockableWindow.InitializeOrdering; +begin +end; + +procedure TTBCustomDockableWindow.SizeChanging(const AWidth, AHeight: Integer); +begin +end; + +procedure TTBCustomDockableWindow.ReadSavedAtRunTime(Reader: TReader); +begin + FSavedAtRunTime := Reader.ReadBoolean; +end; + +procedure TTBCustomDockableWindow.WriteSavedAtRunTime(Writer: TWriter); +begin + { WriteSavedAtRunTime only called when not(csDesigning in ComponentState) } + Writer.WriteBoolean(True); +end; + +procedure TTBCustomDockableWindow.DefineProperties(Filer: TFiler); +begin + inherited; + Filer.DefineProperty('SavedAtRunTime', ReadSavedAtRunTime, + WriteSavedAtRunTime, not(csDesigning in ComponentState)); +end; + +procedure TTBCustomDockableWindow.Loaded; +var + R: TRect; +begin + inherited; + { Adjust coordinates if it was initially floating } + if not FSavedAtRunTime and not(csDesigning in ComponentState) and + (Parent is TTBFloatingWindowParent) then begin + R := BoundsRect; + MapWindowPoints(TBValidToolWindowParentForm(Self).Handle, 0, R, 2); + BoundsRect := R; + MoveOnScreen(False); + end; + InitializeOrdering; + { Arranging is disabled while component was loading, so arrange now } + Arrange; +end; + +procedure TTBCustomDockableWindow.BeginUpdate; +begin + Inc(FDisableArrange); +end; + +procedure TTBCustomDockableWindow.EndUpdate; +begin + Dec(FDisableArrange); + if FArrangeNeeded and (FDisableArrange = 0) then + Arrange; +end; + +procedure TTBCustomDockableWindow.AddDockForm(const Form: TTBCustomForm); +begin + if Form = nil then Exit; + if AddToList(FDockForms, Form) then + Form.FreeNotification(Self); +end; + +procedure TTBCustomDockableWindow.RemoveDockForm(const Form: TTBCustomForm); +begin + RemoveFromList(FDockForms, Form); +end; + +function TTBCustomDockableWindow.CanDockTo(ADock: TTBDock): Boolean; +begin + Result := ADock.Position in DockableTo; +end; + +function TTBCustomDockableWindow.IsAutoResized: Boolean; +begin + Result := AutoResize or Assigned(CurrentDock) or Floating; +end; + +procedure TTBCustomDockableWindow.ChangeSize(AWidth, AHeight: Integer); +var + S: TPoint; +begin + if Docked then + CurrentDock.ArrangeToolbars + else begin + S := CalcNCSizes; + Inc(AWidth, S.X); + Inc(AHeight, S.Y); + { Leave the width and/or height alone if the control is Anchored + (or Aligned) } + if not Floating then begin + if (akLeft in Anchors) and (akRight in Anchors) then + AWidth := Width; + if (akTop in Anchors) and (akBottom in Anchors) then + AHeight := Height; + end; + Inc(FUpdatingBounds); + try + SetBounds(Left, Top, AWidth, AHeight); + finally + Dec(FUpdatingBounds); + end; + end; +end; + +procedure TTBCustomDockableWindow.Arrange; +var + Size: TPoint; +begin + if (FDisableArrange > 0) or + { Prevent flicker while loading } + (csLoading in ComponentState) or + { Don't call DoArrangeControls when Parent is nil. The VCL sets Parent to + 'nil' during destruction of a component; we can't have an OrderControls + call after a descendant control has freed its data. } + (Parent = nil) then begin + FArrangeNeeded := True; + Exit; + end; + + FArrangeNeeded := False; + + Size := DoArrange(True, TBGetDockTypeOf(CurrentDock, Floating), Floating, + CurrentDock); + if IsAutoResized then + ChangeSize(Size.X, Size.Y); +end; + +procedure TTBCustomDockableWindow.SetBounds(ALeft, ATop, AWidth, AHeight: Integer); +begin + if not(csDesigning in ComponentState) and Floating then begin + { Force Top & Left to 0 if floating } + ALeft := 0; + ATop := 0; + if Parent is TTBFloatingWindowParent then + with Parent do + SetBounds(Left, Top, (Width-ClientWidth) + AWidth, + (Height-ClientHeight) + AHeight); + end; + if (FUpdatingBounds = 0) and ((AWidth <> Width) or (AHeight <> Height)) then + SizeChanging(AWidth, AHeight); + { This allows you to drag the toolbar around the dock at design time } + if (csDesigning in ComponentState) and not(csLoading in ComponentState) and + Docked and (FUpdatingBounds = 0) and ((ALeft <> Left) or (ATop <> Top)) then begin + if not(CurrentDock.Position in PositionLeftOrRight) then begin + FDockRow := CurrentDock.GetDesignModeRowOf(ATop+(Height div 2)); + FDockPos := ALeft; + end + else begin + FDockRow := CurrentDock.GetDesignModeRowOf(ALeft+(Width div 2)); + FDockPos := ATop; + end; + inherited SetBounds(Left, Top, AWidth, AHeight); { only pass any size changes } + CurrentDock.ArrangeToolbars; { let ArrangeToolbars take care of position changes } + end + else begin + inherited; + {if not(csLoading in ComponentState) and Floating and (FUpdatingBounds = 0) then + FFloatingPosition := BoundsRect.TopLeft;} + end; +end; + +procedure TTBCustomDockableWindow.SetParent(AParent: TWinControl); + procedure UpdateFloatingToolWindows; + begin + if Parent is TTBFloatingWindowParent then begin + AddToList(FloatingToolWindows, Self); + Parent.SetBounds(FFloatingPosition.X, FFloatingPosition.Y, + Parent.Width, Parent.Height); + end + else + RemoveFromList(FloatingToolWindows, Self); + end; + function ParentToCurrentDock(const Ctl: TWinControl): TTBDock; + begin + if Ctl is TTBDock then + Result := TTBDock(Ctl) + else + Result := nil; + end; +var + OldCurrentDock, NewCurrentDock: TTBDock; + NewFloating: Boolean; + OldParent: TWinControl; + SaveHandle: HWND; +begin + OldCurrentDock := ParentToCurrentDock(Parent); + NewCurrentDock := ParentToCurrentDock(AParent); + NewFloating := AParent is TTBFloatingWindowParent; + + if AParent = Parent then begin + { Even though AParent is the same as the current Parent, this code is + necessary because when the VCL destroys the parent of the tool window, + it calls TWinControl.Remove to set FParent instead of using SetParent. + However TControl.Destroy does call SetParent(nil), so it is + eventually notified of the change before it is destroyed. } + FCurrentDock := NewCurrentDock; + FFloating := NewFloating; + FDocked := Assigned(FCurrentDock); + UpdateFloatingToolWindows; + end + else begin + if not(csDestroying in ComponentState) and Assigned(AParent) then begin + if Assigned(FOnDockChanging) then + FOnDockChanging(Self, NewFloating, NewCurrentDock); + if Assigned(FOnRecreating) then + FOnRecreating(Self); + end; + + { Before changing between docked and floating state (and vice-versa) + or between docks, increment FHidden and call UpdateVisibility to hide the + toolbar. This prevents any flashing while it's being moved } + Inc(FHidden); + Inc(FDisableOnMove); + try + UpdateVisibility; + if Assigned(OldCurrentDock) then + OldCurrentDock.BeginUpdate; + if Assigned(NewCurrentDock) then + NewCurrentDock.BeginUpdate; + Inc(FUpdatingBounds); + try + if Assigned(AParent) then + DoDockChangingHidden(NewFloating, NewCurrentDock); + BeginUpdate; + try + { FCurrentSize probably won't be valid after changing Parents, so + reset it to zero } + FCurrentSize := 0; + + if Parent is TTBDock then begin + if not FUseLastDock or (FLastDock <> Parent) then + TTBDock(Parent).ChangeDockList(False, Self); + TTBDock(Parent).ToolbarVisibilityChanged(Self, True); + end; + + OldParent := Parent; + + SaveHandle := 0; + if Assigned(AParent) then begin + //AParent.HandleNeeded; + SaveHandle := WindowHandle; + WindowHandle := 0; + end; + { Ensure that the handle is destroyed now so that any messages in the queue + get flushed. This is neccessary since existing messages may reference + FDockedTo or FDocked, which is changed below. } + inherited SetParent(nil); + { ^ Note to self: SetParent is used instead of DestroyHandle because it does + additional processing } + FCurrentDock := NewCurrentDock; + FFloating := NewFloating; + FDocked := Assigned(FCurrentDock); + try + if SaveHandle <> 0 then begin + WindowHandle := SaveHandle; + Windows.SetParent(SaveHandle, AParent.Handle); + SetWindowPos(SaveHandle, 0, 0, 0, 0, 0, SWP_FRAMECHANGED or + SWP_NOACTIVATE or SWP_NOMOVE or SWP_NOSIZE or SWP_NOZORDER); + end; + inherited; + except + { Failure is rare, but just in case, restore FDockedTo and FDocked back. } + FCurrentDock := ParentToCurrentDock(Parent); + FFloating := Parent is TTBFloatingWindowParent; + FDocked := Assigned(FCurrentDock); + raise; + end; + + { FEffectiveDockRow probably won't be valid on the new Parent, so + reset it to -1 so that GetMinRowSize will temporarily ignore this + toolbar } + FEffectiveDockRow := -1; + + if not FSmoothDragging and (OldParent is TTBFloatingWindowParent) then begin + if FFloatParent = OldParent then FFloatParent := nil; + OldParent.Free; + end; + + if Parent is TTBDock then begin + if FUseLastDock and not FSmoothDragging then begin + LastDock := TTBDock(Parent); { calls ChangeDockList if LastDock changes } + TTBDock(Parent).ToolbarVisibilityChanged(Self, False); + end + else + TTBDock(Parent).ChangeDockList(True, Self); + end; + + UpdateFloatingToolWindows; + + { Schedule an arrange } + Arrange; + finally + EndUpdate; + end; + finally + Dec(FUpdatingBounds); + if Assigned(NewCurrentDock) then + NewCurrentDock.EndUpdate; + if Assigned(OldCurrentDock) then + OldCurrentDock.EndUpdate; + end; + finally + Dec(FDisableOnMove); + Dec(FHidden); + UpdateVisibility; + { ^ The above UpdateVisibility call not only updates the tool window's + visibility after decrementing FHidden, it also sets the + active/inactive state of the caption. } + end; + if Assigned(Parent) then + Moved; + + if not(csDestroying in ComponentState) and Assigned(AParent) then begin + if Assigned(FOnRecreated) then + FOnRecreated(Self); + if Assigned(FOnDockChanged) then + FOnDockChanged(Self); + end; + end; +end; + +procedure TTBCustomDockableWindow.AddDockedNCAreaToSize(var S: TPoint; + const LeftRight: Boolean); +var + TopLeft, BottomRight: TPoint; +begin + GetDockedNCArea(TopLeft, BottomRight, LeftRight); + Inc(S.X, TopLeft.X + BottomRight.X); + Inc(S.Y, TopLeft.Y + BottomRight.Y); +end; + +procedure TTBCustomDockableWindow.AddFloatingNCAreaToSize(var S: TPoint); +var + TopLeft, BottomRight: TPoint; +begin + GetFloatingNCArea(TopLeft, BottomRight); + Inc(S.X, TopLeft.X + BottomRight.X); + Inc(S.Y, TopLeft.Y + BottomRight.Y); +end; + +procedure TTBCustomDockableWindow.GetDockedNCArea(var TopLeft, BottomRight: TPoint; + const LeftRight: Boolean); +var + Z: Integer; +begin + Z := DockedBorderSize; { code optimization... } + TopLeft.X := Z; + TopLeft.Y := Z; + BottomRight.X := Z; + BottomRight.Y := Z; + if not LeftRight then begin + Inc(TopLeft.X, DragHandleSizes[CloseButtonWhenDocked, DragHandleStyle]); + //if FShowChevron then + // Inc(BottomRight.X, tbChevronSize); + end + else begin + Inc(TopLeft.Y, DragHandleSizes[CloseButtonWhenDocked, DragHandleStyle]); + //if FShowChevron then + // Inc(BottomRight.Y, tbChevronSize); + end; +end; + +function TTBCustomDockableWindow.GetFloatingBorderSize: TPoint; +{ Returns size of a thick border. Note that, depending on the Windows version, + this may not be the same as the actual window metrics since it draws its + own border } +const + XMetrics: array[Boolean] of Integer = (SM_CXDLGFRAME, SM_CXFRAME); + YMetrics: array[Boolean] of Integer = (SM_CYDLGFRAME, SM_CYFRAME); +begin + Result.X := GetSystemMetrics(XMetrics[Resizable]); + Result.Y := GetSystemMetrics(YMetrics[Resizable]); +end; + +procedure TTBCustomDockableWindow.GetFloatingNCArea(var TopLeft, BottomRight: TPoint); +begin + with GetFloatingBorderSize do begin + TopLeft.X := X; + TopLeft.Y := Y; + if ShowCaption then + Inc(TopLeft.Y, GetSmallCaptionHeight); + BottomRight.X := X; + BottomRight.Y := Y; + end; +end; + +function TTBCustomDockableWindow.GetDockedCloseButtonRect(LeftRight: Boolean): TRect; +var + X, Y, Z: Integer; +begin + Z := DragHandleSizes[CloseButtonWhenDocked, FDragHandleStyle] - 3; + if not LeftRight then begin + X := DockedBorderSize+1; + Y := DockedBorderSize; + end + else begin + X := (ClientWidth + DockedBorderSize) - Z; + Y := DockedBorderSize+1; + end; + Result := Bounds(X, Y, Z, Z); +end; + +function TTBCustomDockableWindow.CalcNCSizes: TPoint; +var + Z: Integer; +begin + if not Docked then begin + Result.X := 0; + Result.Y := 0; + end + else begin + Result.X := DockedBorderSize2; + Result.Y := DockedBorderSize2; + if CurrentDock.FAllowDrag then begin + Z := DragHandleSizes[FCloseButtonWhenDocked, FDragHandleStyle]; + if not(CurrentDock.Position in PositionLeftOrRight) then + Inc(Result.X, Z) + else + Inc(Result.Y, Z); + end; + end; +end; + +procedure TTBCustomDockableWindow.WMNCCalcSize(var Message: TWMNCCalcSize); +var + Z: Integer; +begin + { Doesn't call inherited since it overrides the normal NC sizes } + Message.Result := 0; + if Docked then + with Message.CalcSize_Params^ do begin + InflateRect(rgrc[0], -DockedBorderSize, -DockedBorderSize); + if CurrentDock.FAllowDrag then begin + Z := DragHandleSizes[FCloseButtonWhenDocked, FDragHandleStyle]; + if not(CurrentDock.Position in PositionLeftOrRight) then + Inc(rgrc[0].Left, Z) + else + Inc(rgrc[0].Top, Z); + end; + end; +end; + +procedure TTBCustomDockableWindow.WMSetCursor(var Message: TWMSetCursor); +var + P: TPoint; + R: TRect; + I: Integer; +begin + if Docked and CurrentDock.FAllowDrag and + (Message.CursorWnd = WindowHandle) and + (Smallint(Message.HitTest) = HT_TB2k_Border) and + (DragHandleStyle <> dhNone) then begin + GetCursorPos(P); + GetWindowRect(Handle, R); + if not(CurrentDock.Position in PositionLeftOrRight) then + I := P.X - R.Left + else + I := P.Y - R.Top; + if I < DockedBorderSize + DragHandleSizes[CloseButtonWhenDocked, DragHandleStyle] then begin + SetCursor(LoadCursor(0, IDC_SIZEALL)); + Message.Result := 1; + Exit; + end; + end; + inherited; +end; + +procedure TTBCustomDockableWindow.DrawNCArea(const DrawToDC: Boolean; + const ADC: HDC; const Clip: HRGN); +{ Redraws all the non-client area of the toolbar when it is docked. } +var + DC: HDC; + R: TRect; + VerticalDock: Boolean; + X, Y, Y2, Y3, YO, S, SaveIndex: Integer; + R2, R3, R4: TRect; + P1, P2: TPoint; + Brush: HBRUSH; + Clr: TColorRef; + UsingBackground, B: Boolean; + + procedure DrawRaisedEdge(R: TRect; const FillInterior: Boolean); + const + FillMiddle: array[Boolean] of UINT = (0, BF_MIDDLE); + begin + DrawEdge(DC, R, BDR_RAISEDINNER, BF_RECT or FillMiddle[FillInterior]); + end; + + function CreateCloseButtonBitmap: HBITMAP; + const + Pattern: array[0..15] of Byte = + (0, 0, $CC, 0, $78, 0, $30, 0, $78, 0, $CC, 0, 0, 0, 0, 0); + begin + Result := CreateBitmap(8, 8, 1, 1, @Pattern); + end; + + procedure DrawButtonBitmap(const Bmp: HBITMAP); + var + TempBmp: TBitmap; + begin + TempBmp := TBitmap.Create; + try + TempBmp.Handle := Bmp; + SetTextColor(DC, clBlack); + SetBkColor(DC, clWhite); + SelectObject(DC, GetSysColorBrush(COLOR_BTNTEXT)); + BitBlt(DC, R2.Left, R2.Top, R2.Right - R2.Left, R2.Bottom - R2.Top, + TempBmp.Canvas.Handle, 0, 0, $00E20746 {ROP_DSPDxax}); + finally + TempBmp.Free; + end; + end; + +const + CloseButtonState: array[Boolean] of UINT = (0, DFCS_PUSHED); +begin + if not Docked or not HandleAllocated then Exit; + + if not DrawToDC then + DC := GetWindowDC(Handle) + else + DC := ADC; + try + { Use update region } + if not DrawToDC then + SelectNCUpdateRgn(Handle, DC, Clip); + + { This works around WM_NCPAINT problem described at top of source code } + {no! R := Rect(0, 0, Width, Height);} + GetWindowRect(Handle, R); OffsetRect(R, -R.Left, -R.Top); + + VerticalDock := CurrentDock.Position in PositionLeftOrRight; + + Brush := CreateSolidBrush(ColorToRGB(Color)); + + UsingBackground := CurrentDock.UsingBackground and CurrentDock.FBkgOnToolbars; + + { Border } + if BorderStyle = bsSingle then + DrawRaisedEdge(R, False) + else + FrameRect(DC, R, Brush); + R2 := R; + InflateRect(R2, -1, -1); + if not UsingBackground then + FrameRect(DC, R2, Brush); + + { Draw the Background } + if UsingBackground then begin + R2 := R; + P1 := CurrentDock.ClientToScreen(Point(0, 0)); + P2 := CurrentDock.Parent.ClientToScreen(CurrentDock.BoundsRect.TopLeft); + Dec(R2.Left, Left + CurrentDock.Left + (P1.X-P2.X)); + Dec(R2.Top, Top + CurrentDock.Top + (P1.Y-P2.Y)); + InflateRect(R, -1, -1); + GetWindowRect(Handle, R4); + R3 := ClientRect; + with ClientToScreen(Point(0, 0)) do + OffsetRect(R3, X-R4.Left, Y-R4.Top); + SaveIndex := SaveDC(DC); + IntersectClipRect(DC, R.Left, R.Top, R.Right, R.Bottom); + ExcludeClipRect(DC, R3.Left, R3.Top, R3.Right, R3.Bottom); + CurrentDock.DrawBackground(DC, R2); + RestoreDC(DC, SaveIndex); + end; + + { The drag handle at the left, or top } + if CurrentDock.FAllowDrag then begin + SaveIndex := SaveDC(DC); + if not VerticalDock then + Y2 := ClientHeight + else + Y2 := ClientWidth; + Inc(Y2, DockedBorderSize); + S := DragHandleSizes[FCloseButtonWhenDocked, FDragHandleStyle]; + if FDragHandleStyle <> dhNone then begin + Y3 := Y2; + X := DockedBorderSize + DragHandleXOffsets[FCloseButtonWhenDocked, FDragHandleStyle]; + Y := DockedBorderSize; + YO := Ord(FDragHandleStyle = dhSingle); + if FCloseButtonWhenDocked then begin + if not VerticalDock then + Inc(Y, S - 2) + else + Dec(Y3, S - 2); + end; + Clr := GetSysColor(COLOR_BTNHIGHLIGHT); + for B := False to (FDragHandleStyle = dhDouble) do begin + if not VerticalDock then + R2 := Rect(X, Y+YO, X+3, Y2-YO) + else + R2 := Rect(Y+YO, X, Y3-YO, X+3); + DrawRaisedEdge(R2, True); + if not VerticalDock then + SetPixelV(DC, X, Y2-1-YO, Clr) + else + SetPixelV(DC, Y3-1-YO, X, Clr); + ExcludeClipRect(DC, R2.Left, R2.Top, R2.Right, R2.Bottom); + Inc(X, 3); + end; + end; + if not UsingBackground then begin + if not VerticalDock then + R2 := Rect(DockedBorderSize, DockedBorderSize, + DockedBorderSize+S, Y2) + else + R2 := Rect(DockedBorderSize, DockedBorderSize, + Y2, DockedBorderSize+S); + FillRect(DC, R2, Brush); + end; + RestoreDC(DC, SaveIndex); + { Close button } + if FCloseButtonWhenDocked then begin + R2 := GetDockedCloseButtonRect(VerticalDock); + if FCloseButtonDown then + DrawEdge(DC, R2, BDR_SUNKENOUTER, BF_RECT) + else if FCloseButtonHover then + DrawRaisedEdge(R2, False); + InflateRect(R2, -2, -2); + if FCloseButtonDown then + OffsetRect(R2, 1, 1); + DrawButtonBitmap(CreateCloseButtonBitmap); + end; + end; + + DeleteObject(Brush); + finally + if not DrawToDC then + ReleaseDC(Handle, DC); + end; +end; + +procedure TTBCustomDockableWindow.RedrawNCArea; +begin + { Note: IsWindowVisible is called as an optimization. There's no need to + draw on invisible windows. } + if HandleAllocated and IsWindowVisible(Handle) then + DrawNCArea(False, 0, 0); +end; + +procedure TTBCustomDockableWindow.WMNCPaint(var Message: TMessage); +begin + { Don't call inherited because it overrides the default NC painting } + DrawNCArea(False, 0, HRGN(Message.WParam)); +end; + +procedure DockableWindowNCPaintProc(Wnd: HWND; DC: HDC; AppData: Longint); +begin + with TTBCustomDockableWindow(AppData) do + DrawNCArea(True, DC, 0) +end; + +procedure TTBCustomDockableWindow.WMPrint(var Message: TMessage); +begin + HandleWMPrint(Handle, Message, DockableWindowNCPaintProc, Longint(Self)); +end; + +procedure TTBCustomDockableWindow.WMPrintClient(var Message: TMessage); +begin + HandleWMPrintClient(Self, Message); +end; + +procedure TTBCustomDockableWindow.WMEraseBkgnd(var Message: TWMEraseBkgnd); +var + R, R2, R3: TRect; + P1, P2: TPoint; + SaveIndex: Integer; +begin + if Docked and CurrentDock.UsingBackground and CurrentDock.FBkgOnToolbars then begin + R := ClientRect; + R2 := R; + P1 := CurrentDock.ClientToScreen(Point(0, 0)); + P2 := CurrentDock.Parent.ClientToScreen(CurrentDock.BoundsRect.TopLeft); + Dec(R2.Left, Left + CurrentDock.Left + (P1.X-P2.X)); + Dec(R2.Top, Top + CurrentDock.Top + (P1.Y-P2.Y)); + GetWindowRect(Handle, R3); + with ClientToScreen(Point(0, 0)) do begin + Inc(R2.Left, R3.Left-X); + Inc(R2.Top, R3.Top-Y); + end; + SaveIndex := SaveDC(Message.DC); + IntersectClipRect(Message.DC, R.Left, R.Top, R.Right, R.Bottom); + CurrentDock.DrawBackground(Message.DC, R2); + RestoreDC(Message.DC, SaveIndex); + Message.Result := 1; + end + else + inherited; +end; + +function TTBCustomDockableWindow.GetPalette: HPALETTE; +begin + if Docked then + Result := CurrentDock.GetPalette + else + Result := 0; +end; + +function TTBCustomDockableWindow.PaletteChanged(Foreground: Boolean): Boolean; +begin + Result := inherited PaletteChanged(Foreground); + if Result and not Foreground then begin + { There seems to be a bug in Delphi's palette handling. When the form is + inactive and another window realizes a palette, docked TToolbar97s + weren't getting redrawn. So this workaround code was added. } + InvalidateAll(Self); + end; +end; + +procedure TTBCustomDockableWindow.DrawDraggingOutline(const DC: HDC; + const NewRect, OldRect: PRect; const NewDocking, OldDocking: Boolean); +var + NewSize, OldSize: TSize; +begin + with GetFloatingBorderSize do begin + if NewDocking then NewSize.cx := 1 else NewSize.cx := X; + NewSize.cy := NewSize.cx; + if OldDocking then OldSize.cx := 1 else OldSize.cx := X; + OldSize.cy := OldSize.cx; + end; + DrawHalftoneInvertRect(DC, NewRect, OldRect, NewSize, OldSize); +end; + +procedure TTBCustomDockableWindow.CMColorChanged(var Message: TMessage); +begin + { Make sure non-client area is redrawn } + InvalidateAll(Self); + inherited; { the inherited handler calls Invalidate } +end; + +procedure TTBCustomDockableWindow.CMTextChanged(var Message: TMessage); +begin + inherited; + if Parent is TTBFloatingWindowParent then + TTBFloatingWindowParent(Parent).Caption := Caption; +end; + +procedure TTBCustomDockableWindow.CMVisibleChanged(var Message: TMessage); +begin + if not(csDesigning in ComponentState) and Docked then + CurrentDock.ToolbarVisibilityChanged(Self, False); + inherited; + if Assigned(FOnVisibleChanged) then + FOnVisibleChanged(Self); +end; + +procedure TTBCustomDockableWindow.BeginMoving(const InitX, InitY: Integer); +type + PDockedSize = ^TDockedSize; + TDockedSize = record + Dock: TTBDock; + BoundsRect: TRect; + Size: TPoint; + RowSizes: TList; + end; +const + SplitCursors: array[Boolean] of PChar = (IDC_SIZEWE, IDC_SIZENS); +var + UseSmoothDrag: Boolean; + DockList: TList; + NewDockedSizes: TList; {items are pointers to TDockedSizes} + OriginalDock, MouseOverDock: TTBDock; + MoveRect: TRect; + StartDocking, PreventDocking, PreventFloating, WatchForSplit, SplitVertical: Boolean; + ScreenDC: HDC; + OldCursor: HCURSOR; + NPoint, DPoint: TPoint; + OriginalDockRow, OriginalDockPos: Integer; + FirstPos, LastPos, CurPos: TPoint; + + function FindDockedSize(const ADock: TTBDock): PDockedSize; + var + I: Integer; + begin + for I := 0 to NewDockedSizes.Count-1 do begin + Result := NewDockedSizes[I]; + if Result.Dock = ADock then + Exit; + end; + Result := nil; + end; + + function GetRowOf(const RowSizes: TList; const XY: Integer; + var Before: Boolean): Integer; + { Returns row number of the specified coordinate. Before is set to True if it + was in the top (or left) quarter of the row. } + var + HighestRow, R, CurY, NextY, CurRowSize, EdgeSize: Integer; + FullSizeRow: Boolean; + begin + Before := False; + HighestRow := RowSizes.Count-1; + CurY := 0; + for R := 0 to HighestRow do begin + CurRowSize := Integer(RowSizes[R]); + FullSizeRow := FullSize or (CurRowSize and $10000 <> 0); + CurRowSize := Smallint(CurRowSize); + if CurRowSize = 0 then + Continue; + NextY := CurY + CurRowSize; + if not FullSizeRow then + EdgeSize := CurRowSize div 4 + else + EdgeSize := CurRowSize div 2; + if XY < CurY + EdgeSize then begin + Result := R; + Before := True; + Exit; + end; + if not FullSizeRow and (XY < NextY - EdgeSize) then begin + Result := R; + Exit; + end; + CurY := NextY; + end; + Result := HighestRow+1; + end; + + procedure Dropped; + var + NewDockRow: Integer; + Before: Boolean; + MoveRectClient: TRect; + C: Integer; + DockedSize: PDockedSize; + begin + if MouseOverDock <> nil then begin + DockedSize := FindDockedSize(MouseOverDock); + MoveRectClient := MoveRect; + OffsetRect(MoveRectClient, -DockedSize.BoundsRect.Left, + -DockedSize.BoundsRect.Top); + if not FDragSplitting then begin + if not(MouseOverDock.Position in PositionLeftOrRight) then + C := (MoveRectClient.Top+MoveRectClient.Bottom) div 2 + else + C := (MoveRectClient.Left+MoveRectClient.Right) div 2; + NewDockRow := GetRowOf(DockedSize.RowSizes, C, Before); + if Before then + WatchForSplit := False; + end + else begin + NewDockRow := FDockRow; + Before := False; + end; + if WatchForSplit then begin + if (MouseOverDock <> OriginalDock) or (NewDockRow <> OriginalDockRow) then + WatchForSplit := False + else begin + if not SplitVertical then + C := FirstPos.X - LastPos.X + else + C := FirstPos.Y - LastPos.Y; + if Abs(C) >= 10 then begin + WatchForSplit := False; + FDragSplitting := True; + SetCursor(LoadCursor(0, SplitCursors[SplitVertical])); + end; + end; + end; + FDockRow := NewDockRow; + if not(MouseOverDock.Position in PositionLeftOrRight) then + FDockPos := MoveRectClient.Left + else + FDockPos := MoveRectClient.Top; + Parent := MouseOverDock; + if not FSmoothDragging then + CurrentDock.CommitNewPositions := True; + FInsertRowBefore := Before; + try + CurrentDock.ArrangeToolbars; + finally + FInsertRowBefore := False; + end; + end + else begin + WatchForSplit := False; + FloatingPosition := MoveRect.TopLeft; + Floating := True; + { Make sure it doesn't go completely off the screen } + MoveOnScreen(True); + end; + + { Make sure it's repainted immediately (looks better on really slow + computers when smooth dragging is enabled) } + Update; + end; + + procedure MouseMoved; + var + OldMouseOverDock: TTBDock; + OldMoveRect: TRect; + Pos: TPoint; + + function GetDockRect(Control: TTBDock): TRect; + var + I: Integer; + begin + for I := 0 to NewDockedSizes.Count-1 do + with PDockedSize(NewDockedSizes[I])^ do begin + if Dock <> Control then Continue; + Result := Bounds(Pos.X-MulDiv(Size.X-1, NPoint.X, DPoint.X), + Pos.Y-MulDiv(Size.Y-1, NPoint.Y, DPoint.Y), + Size.X, Size.Y); + Exit; + end; + SetRectEmpty(Result); + end; + + function CheckIfCanDockTo(Control: TTBDock; R: TRect): Boolean; + const + DockSensX = 25; + DockSensY = 25; + var + S, Temp: TRect; + Sens: Integer; + begin + with Control do begin + Result := False; + + InflateRect(R, 3, 3); + S := GetDockRect(Control); + + { Like Office, distribute ~25 pixels of extra dock detection area + to the left side if the toolbar was grabbed at the left, both sides + if the toolbar was grabbed at the middle, or the right side if + toolbar was grabbed at the right. If outside, don't try to dock. } + Sens := MulDiv(DockSensX, NPoint.X, DPoint.X); + if (Pos.X < R.Left-(DockSensX-Sens)) or (Pos.X >= R.Right+Sens) then + Exit; + + { Don't try to dock to the left or right if pointer is above or below + the boundaries of the dock } + if (Control.Position in PositionLeftOrRight) and + ((Pos.Y < R.Top) or (Pos.Y >= R.Bottom)) then + Exit; + + { And also distribute ~25 pixels of extra dock detection area to + the top or bottom side } + Sens := MulDiv(DockSensY, NPoint.Y, DPoint.Y); + if (Pos.Y < R.Top-(DockSensY-Sens)) or (Pos.Y >= R.Bottom+Sens) then + Exit; + + Result := IntersectRect(Temp, R, S); + end; + end; + + var + R, R2: TRect; + I: Integer; + Dock: TTBDock; + Accept: Boolean; + TL, BR: TPoint; + begin + OldMouseOverDock := MouseOverDock; + OldMoveRect := MoveRect; + + GetCursorPos(Pos); + + if FDragSplitting then + MouseOverDock := CurrentDock + else begin + { Check if it can dock } + MouseOverDock := nil; + if StartDocking and not PreventDocking then + {for I := 0 to DockList.Count-1 do begin} {rl-} + for I := DockList.Count-1 downto 0 do begin {rl+} // Robert Lee: CurrentDock should not have the priority + Dock := DockList[I]; + if CheckIfCanDockTo(Dock, FindDockedSize(Dock).BoundsRect) then begin + MouseOverDock := Dock; + Accept := True; + if Assigned(MouseOverDock.FOnRequestDock) then + MouseOverDock.FOnRequestDock(MouseOverDock, Self, Accept); + if Accept then + Break + else + MouseOverDock := nil; + end; + end; + end; + + { If not docking, clip the point so it doesn't get dragged under the + taskbar } + if MouseOverDock = nil then begin + R := GetRectOfMonitorContainingPoint(Pos, True); + if Pos.X < R.Left then Pos.X := R.Left; + if Pos.X > R.Right then Pos.X := R.Right; + if Pos.Y < R.Top then Pos.Y := R.Top; + if Pos.Y > R.Bottom then Pos.Y := R.Bottom; + end; + + MoveRect := GetDockRect(MouseOverDock); + + { Make sure title bar (or at least part of the toolbar) is still accessible + if it's dragged almost completely off the screen. This prevents the + problem seen in Office 97 where you drag it offscreen so that only the + border is visible, sometimes leaving you no way to move it back short of + resetting the toolbar. } + if MouseOverDock = nil then begin + R2 := GetRectOfMonitorContainingPoint(Pos, True); + R := R2; + with GetFloatingBorderSize do + InflateRect(R, -(X+4), -(Y+4)); + if MoveRect.Bottom < R.Top then + OffsetRect(MoveRect, 0, R.Top-MoveRect.Bottom); + if MoveRect.Top > R.Bottom then + OffsetRect(MoveRect, 0, R.Bottom-MoveRect.Top); + if MoveRect.Right < R.Left then + OffsetRect(MoveRect, R.Left-MoveRect.Right, 0); + if MoveRect.Left > R.Right then + OffsetRect(MoveRect, R.Right-MoveRect.Left, 0); + + GetFloatingNCArea(TL, BR); + I := R2.Top + 4 - TL.Y; + if MoveRect.Top < I then + OffsetRect(MoveRect, 0, I-MoveRect.Top); + end; + + { Empty MoveRect if it's wanting to float but it's not allowed to, and + set the mouse cursor accordingly. } + if PreventFloating and not Assigned(MouseOverDock) then begin + SetRectEmpty(MoveRect); + SetCursor(LoadCursor(0, IDC_NO)); + end + else begin + if FDragSplitting then + SetCursor(LoadCursor(0, SplitCursors[SplitVertical])) + else + SetCursor(OldCursor); + end; + + { Update the dragging outline } + if not UseSmoothDrag then + DrawDraggingOutline(ScreenDC, @MoveRect, @OldMoveRect, MouseOverDock <> nil, + OldMouseOverDock <> nil) + else + if not IsRectEmpty(MoveRect) then + Dropped; + end; + + procedure BuildDockList; + + procedure Recurse(const ParentCtl: TWinControl); + var + D: TTBDockPosition; + I: Integer; + begin + if ContainsControl(ParentCtl) or not ParentCtl.Showing then + Exit; + with ParentCtl do begin + for D := Low(D) to High(D) do + for I := 0 to ParentCtl.ControlCount-1 do + if (Controls[I] is TTBDock) and (TTBDock(Controls[I]).Position = D) then + Recurse(TWinControl(Controls[I])); + for I := 0 to ParentCtl.ControlCount-1 do + if (Controls[I] is TWinControl) and not(Controls[I] is TTBDock) then + Recurse(TWinControl(Controls[I])); + end; + if (ParentCtl is TTBDock) and TTBDock(ParentCtl).Accepts(Self) and CanDockTo(TTBDock(ParentCtl)) and + (DockList.IndexOf(ParentCtl) = -1) then + DockList.Add(ParentCtl); + end; + + var + ParentForm: TTBCustomForm; + DockFormsList: TList; + I, J: Integer; + begin + { Manually add CurrentDock to the DockList first so that it gets priority + over other docks } + if Assigned(CurrentDock) and CurrentDock.Accepts(Self) and CanDockTo(CurrentDock) then + DockList.Add(CurrentDock); + ParentForm := TBGetToolWindowParentForm(Self); + DockFormsList := TList.Create; + try + if Assigned(FDockForms) then begin + for I := 0 to Screen.{$IFDEF JR_D3}CustomFormCount{$ELSE}FormCount{$ENDIF}-1 do begin + J := FDockForms.IndexOf(Screen.{$IFDEF JR_D3}CustomForms{$ELSE}Forms{$ENDIF}[I]); + if (J <> -1) and (FDockForms[J] <> ParentForm) then + DockFormsList.Add(FDockForms[J]); + end; + end; + if Assigned(ParentForm) then + DockFormsList.Insert(0, ParentForm); + for I := 0 to DockFormsList.Count-1 do + Recurse(DockFormsList[I]); + finally + DockFormsList.Free; + end; + end; + +var + Accept, FullSizeRow: Boolean; + R: TRect; + Msg: TMsg; + NewDockedSize: PDockedSize; + I, J, S: Integer; +begin + Accept := False; + SplitVertical := False; + WatchForSplit := False; + OriginalDock := CurrentDock; + OriginalDockRow := FDockRow; + OriginalDockPos := FDockPos; + try + FDragMode := True; + FDragSplitting := False; + if Docked then begin + FDragCanSplit := False; + CurrentDock.CommitNewPositions := True; + CurrentDock.ArrangeToolbars; { needed for WatchForSplit assignment below } + SplitVertical := CurrentDock.Position in PositionLeftOrRight; + WatchForSplit := FDragCanSplit; + end; + DockList := nil; + NewDockedSizes := nil; + try + UseSmoothDrag := FSmoothDrag; + FSmoothDragging := UseSmoothDrag; + + NPoint := Point(InitX, InitY); + { Adjust for non-client area } + if not(Parent is TTBFloatingWindowParent) then begin + GetWindowRect(Handle, R); + R.BottomRight := ClientToScreen(Point(0, 0)); + DPoint := Point(Width-1, Height-1); + end + else begin + GetWindowRect(Parent.Handle, R); + R.BottomRight := Parent.ClientToScreen(Point(0, 0)); + DPoint := Point(Parent.Width-1, Parent.Height-1); + end; + Dec(NPoint.X, R.Left-R.Right); + Dec(NPoint.Y, R.Top-R.Bottom); + + PreventDocking := GetKeyState(VK_CONTROL) < 0; + PreventFloating := DockMode <> dmCanFloat; + + { Build list of all TTBDock's on the form } + DockList := TList.Create; + if DockMode <> dmCannotFloatOrChangeDocks then + BuildDockList + else + if Docked then + DockList.Add(CurrentDock); + + { Ensure positions of each possible dock are committed } + for I := 0 to DockList.Count-1 do + TTBDock(DockList[I]).CommitPositions; + + { Set up potential sizes for each dock type } + NewDockedSizes := TList.Create; + for I := -1 to DockList.Count-1 do begin + New(NewDockedSize); + NewDockedSize.RowSizes := nil; + try + with NewDockedSize^ do begin + if I = -1 then begin + { -1 adds the floating size } + Dock := nil; + SetRectEmpty(BoundsRect); + Size := DoArrange(False, TBGetDockTypeOf(CurrentDock, Floating), True, nil); + AddFloatingNCAreaToSize(Size); + end + else begin + Dock := TTBDock(DockList[I]); + GetWindowRect(Dock.Handle, BoundsRect); + if Dock <> CurrentDock then begin + Size := DoArrange(False, TBGetDockTypeOf(CurrentDock, Floating), False, Dock); + AddDockedNCAreaToSize(Size, Dock.Position in PositionLeftOrRight); + end + else + Size := Point(Width, Height); + end; + end; + if Assigned(NewDockedSize.Dock) then begin + NewDockedSize.RowSizes := TList.Create; + for J := 0 to NewDockedSize.Dock.GetHighestRow(True) do begin + S := Smallint(NewDockedSize.Dock.GetCurrentRowSize(J, FullSizeRow)); + if FullSizeRow then + S := S or $10000; + NewDockedSize.RowSizes.Add(Pointer(S)); + end; + end; + NewDockedSizes.Add(NewDockedSize); + except + NewDockedSize.RowSizes.Free; + Dispose(NewDockedSize); + raise; + end; + end; + + { Before locking, make sure all pending paint messages are processed } + ProcessPaintMessages; + + { Save the original mouse cursor } + OldCursor := GetCursor; + + if not UseSmoothDrag then begin + { This uses LockWindowUpdate to suppress all window updating so the + dragging outlines doesn't sometimes get garbled. (This is safe, and in + fact, is the main purpose of the LockWindowUpdate function) + IMPORTANT! While debugging you might want to enable the 'TB2Dock_DisableLock' + conditional define (see top of the source code). } + {$IFNDEF TB2Dock_DisableLock} + LockWindowUpdate(GetDesktopWindow); + {$ENDIF} + { Get a DC of the entire screen. Works around the window update lock + by specifying DCX_LOCKWINDOWUPDATE. } + ScreenDC := GetDCEx(GetDesktopWindow, 0, + DCX_LOCKWINDOWUPDATE or DCX_CACHE or DCX_WINDOW); + end + else + ScreenDC := 0; + try + SetCapture(Handle); + + { Initialize } + StartDocking := Docked; + MouseOverDock := nil; + SetRectEmpty(MoveRect); + GetCursorPos(FirstPos); + LastPos := FirstPos; + MouseMoved; + StartDocking := True; + + { Stay in message loop until capture is lost. Capture is removed either + by this procedure manually doing it, or by an outside influence (like + a message box or menu popping up) } + while GetCapture = Handle do begin + case Integer(GetMessage(Msg, 0, 0, 0)) of + -1: Break; { if GetMessage failed } + 0: begin + { Repost WM_QUIT messages } + PostQuitMessage(Msg.WParam); + Break; + end; + end; + + case Msg.Message of + WM_KEYDOWN, WM_KEYUP: + { Ignore all keystrokes while dragging. But process Ctrl and Escape } + case Msg.WParam of + VK_CONTROL: + if PreventDocking <> (Msg.Message = WM_KEYDOWN) then begin + PreventDocking := Msg.Message = WM_KEYDOWN; + MouseMoved; + end; + VK_ESCAPE: + Break; + end; + WM_MOUSEMOVE: begin + { Note to self: WM_MOUSEMOVE messages should never be dispatched + here to ensure no hints get shown during the drag process } + CurPos := SmallPointToPoint(TSmallPoint(DWORD(GetMessagePos))); + if (LastPos.X <> CurPos.X) or (LastPos.Y <> CurPos.Y) then begin + MouseMoved; + LastPos := CurPos; + end; + end; + WM_LBUTTONDOWN, WM_LBUTTONDBLCLK: + { Make sure it doesn't begin another loop } + Break; + WM_LBUTTONUP: begin + Accept := True; + Break; + end; + WM_RBUTTONDOWN..WM_MBUTTONDBLCLK: + { Ignore all other mouse up/down messages } + ; + else + TranslateMessage(Msg); + DispatchMessage(Msg); + end; + end; + finally + { Since it sometimes breaks out of the loop without capture being + released } + if GetCapture = Handle then + ReleaseCapture; + + if not UseSmoothDrag then begin + { Hide dragging outline. Since NT will release a window update lock if + another thread comes to the foreground, it has to release the DC + and get a new one for erasing the dragging outline. Otherwise, + the DrawDraggingOutline appears to have no effect when this happens. } + ReleaseDC(GetDesktopWindow, ScreenDC); + ScreenDC := GetDCEx(GetDesktopWindow, 0, + DCX_LOCKWINDOWUPDATE or DCX_CACHE or DCX_WINDOW); + DrawDraggingOutline(ScreenDC, nil, @MoveRect, True, MouseOverDock <> nil); + ReleaseDC(GetDesktopWindow, ScreenDC); + + { Release window update lock } + {$IFNDEF TB2Dock_DisableLock} + LockWindowUpdate(0); + {$ENDIF} + end; + end; + + { Move to new position only if MoveRect isn't empty } + FSmoothDragging := False; + if Accept and not IsRectEmpty(MoveRect) then + { Note: Dropped must be called again after FSmoothDragging is reset to + False so that TTBDock.ArrangeToolbars makes the DockPos changes + permanent } + Dropped; + + { LastDock isn't automatically updated while FSmoothDragging=True, so + update it now that it's back to False } + if FUseLastDock and Assigned(CurrentDock) then + LastDock := CurrentDock; + + { Free FFloatParent if it's no longer the Parent } + if Assigned(FFloatParent) and (Parent <> FFloatParent) then begin + FFloatParent.Free; + FFloatParent := nil; + end; + finally + FSmoothDragging := False; + if not Docked then begin + { If we didn't end up docking, restore the original DockRow & DockPos + values } + FDockRow := OriginalDockRow; + FDockPos := OriginalDockPos; + end; + if Assigned(NewDockedSizes) then begin + for I := NewDockedSizes.Count-1 downto 0 do begin + NewDockedSize := NewDockedSizes[I]; + NewDockedSize.RowSizes.Free; + Dispose(NewDockedSize); + end; + NewDockedSizes.Free; + end; + DockList.Free; + end; + finally + FDragMode := False; + FDragSplitting := False; + end; +end; + +function TTBCustomDockableWindow.ChildControlTransparent(Ctl: TControl): Boolean; +begin + Result := False; +end; + +procedure TTBCustomDockableWindow.ControlExistsAtPos(const P: TPoint; + var ControlExists: Boolean); +var + I: Integer; +begin + for I := 0 to ControlCount-1 do + if not ChildControlTransparent(Controls[I]) and Controls[I].Visible and + PtInRect(Controls[I].BoundsRect, P) then begin + ControlExists := True; + Break; + end; +end; + +procedure TTBCustomDockableWindow.DoubleClick; +begin + if Docked then begin + if DblClickUndock and (DockMode = dmCanFloat) then begin + Floating := True; + MoveOnScreen(True); + end; + end + else if Floating then begin + if Assigned(LastDock) then + Parent := LastDock + else + if Assigned(DefaultDock) then begin + FDockRow := ForceDockAtTopRow; + FDockPos := ForceDockAtLeftPos; + Parent := DefaultDock; + end; + end; +end; + +function TTBCustomDockableWindow.IsMovable: Boolean; +begin + Result := (Docked and CurrentDock.FAllowDrag) or Floating; +end; + +procedure TTBCustomDockableWindow.MouseDown(Button: TMouseButton; + Shift: TShiftState; X, Y: Integer); +var + P: TPoint; + CtlExists: Boolean; +begin + inherited; + if (Button <> mbLeft) or not IsMovable then + Exit; + { Ignore message if user clicked on a child control } + P := Point(X, Y); + if PtInRect(ClientRect, P) then begin + CtlExists := False; + ControlExistsAtPos(P, CtlExists); + if CtlExists then + Exit; + end; + + if not(ssDouble in Shift) then begin + BeginMoving(X, Y); + MouseUp(mbLeft, [], -1, -1); + end + else + { Handle double click } + DoubleClick; +end; + +procedure TTBCustomDockableWindow.WMNCHitTest(var Message: TWMNCHitTest); +var + P: TPoint; + R: TRect; +begin + inherited; + if Docked then + with Message do begin + P := SmallPointToPoint(Pos); + GetWindowRect(Handle, R); + Dec(P.X, R.Left); Dec(P.Y, R.Top); + if Result <> HTCLIENT then begin + Result := HTNOWHERE; + if FCloseButtonWhenDocked and CurrentDock.FAllowDrag and + PtInRect(GetDockedCloseButtonRect( + TBGetDockTypeOf(CurrentDock, Floating) = dtLeftRight), P) then + Result := HT_TB2k_Close + else + Result := HT_TB2k_Border; + end; + end; +end; + +procedure TTBCustomDockableWindow.WMNCMouseMove(var Message: TWMNCMouseMove); +var + InArea: Boolean; +begin + inherited; + { Note: TME_NONCLIENT was introduced in Windows 98 and 2000 } + if (Win32MajorVersion >= 5) or + (Win32MajorVersion = 4) and (Win32MinorVersion >= 10) then + CallTrackMouseEvent(Handle, TME_LEAVE or $10 {TME_NONCLIENT}); + InArea := Message.HitTest = HT_TB2k_Close; + if FCloseButtonHover <> InArea then begin + FCloseButtonHover := InArea; + RedrawNCArea; + end; +end; + +procedure TTBCustomDockableWindow.WMNCMouseLeave(var Message: TMessage); +begin + if not MouseCapture then + CancelNCHover; + inherited; +end; + +procedure TTBCustomDockableWindow.CMMouseLeave(var Message: TMessage); +begin + inherited; + { On Windows versions that can't send a WM_NCMOUSELEAVE message, trap + CM_MOUSELEAVE to detect when the mouse moves from the non-client area to + another control. } + CancelNCHover; +end; + +procedure TTBCustomDockableWindow.WMMouseMove(var Message: TMessage); +begin + { On Windows versions that can't send a WM_NCMOUSELEAVE message, trap + WM_MOUSEMOVE to detect when the mouse moves from the non-client area to + the client area. + Note: We are overriding WM_MOUSEMOVE instead of MouseMove so that our + processing always gets done first. } + CancelNCHover; + inherited; +end; + +procedure TTBCustomDockableWindow.CancelNCHover; +begin + if FCloseButtonHover then begin + FCloseButtonHover := False; + RedrawNCArea; + end; +end; + +procedure TTBCustomDockableWindow.Close; +var + Accept: Boolean; +begin + Accept := True; + if Assigned(FOnCloseQuery) then + FOnCloseQuery(Self, Accept); + { Did the CloseQuery event return True? } + if Accept then begin + Hide; + if Assigned(FOnClose) then + FOnClose(Self); + end; +end; + +procedure TTBCustomDockableWindow.SetCloseButtonState(Pushed: Boolean); +begin + if FCloseButtonDown <> Pushed then begin + FCloseButtonDown := Pushed; + RedrawNCArea; + end; +end; + +procedure TTBCustomDockableWindow.WMNCLButtonDown(var Message: TWMNCLButtonDown); +var + R, BR: TRect; + P: TPoint; +begin + case Message.HitTest of + HT_TB2k_Close: begin + GetWindowRect(Handle, R); + BR := GetDockedCloseButtonRect( + TBGetDockTypeOf(CurrentDock, Floating) = dtLeftRight); + OffsetRect(BR, R.Left, R.Top); + if CloseButtonLoop(Handle, BR, SetCloseButtonState) then + Close; + end; + HT_TB2k_Border: begin + P := ScreenToClient(SmallPointToPoint(TSmallPoint(GetMessagePos()))); + if IsMovable then + BeginMoving(P.X, P.Y); + end; + else + inherited; + end; +end; + +procedure TTBCustomDockableWindow.WMNCLButtonDblClk(var Message: TWMNCLButtonDblClk); +begin + if Message.HitTest = HT_TB2k_Border then begin + if IsMovable then + DoubleClick; + end + else + inherited; +end; + +procedure TTBCustomDockableWindow.ShowNCContextMenu(const Pos: TSmallPoint); + + {$IFNDEF JR_D5} + { Note: this is identical to TControl.CheckMenuPopup (from Delphi 4), + except where noted. + TControl.CheckMenuPopup is unfortunately 'private', so it can't be called + outside of the Controls unit. } + procedure CheckMenuPopup; + var + Control: TControl; + PopupMenu: TPopupMenu; + begin + if csDesigning in ComponentState then Exit; + Control := Self; + while Control <> nil do + begin + { Added TControlAccess cast because GetPopupMenu is 'protected' } + PopupMenu := TControlAccess(Control).GetPopupMenu; + if (PopupMenu <> nil) then + begin + if not PopupMenu.AutoPopup then Exit; + SendCancelMode(nil); + PopupMenu.PopupComponent := Control; + { Changed the following. LPARAM of WM_NCRBUTTONUP is in screen + coordinates, not client coordinates } + {with ClientToScreen(SmallPointToPoint(Pos)) do + PopupMenu.Popup(X, Y);} + PopupMenu.Popup(Pos.X, Pos.Y); + Exit; + end; + Control := Control.Parent; + end; + end; + {$ENDIF} + +begin + {$IFDEF JR_D5} + { Delphi 5 and later use the WM_CONTEXTMENU message for popup menus } + SendMessage(Handle, WM_CONTEXTMENU, 0, LPARAM(Pos)); + {$ELSE} + CheckMenuPopup; + {$ENDIF} +end; + +procedure TTBCustomDockableWindow.WMNCRButtonUp(var Message: TWMNCRButtonUp); +begin + ShowNCContextMenu(TSmallPoint(TMessage(Message).LParam)); +end; + +{$IFDEF JR_D5} +procedure TTBCustomDockableWindow.WMContextMenu(var Message: TWMContextMenu); +{ Unfortunately TControl.WMContextMenu ignores clicks in the non-client area. + On docked toolbars, we need right clicks on the border, part of the + non-client area, to display the popup menu. The only way I see to have it do + that is to create a new version of WMContextMenu specifically for the + non-client area, and that is what this method is. + Note: This is identical to Delphi 5's TControl.WMContextMenu, except where + noted. } +var + Pt, Temp: TPoint; + Handled: Boolean; + PopupMenu: TPopupMenu; +begin + { Added 'inherited;' here } + inherited; + if Message.Result <> 0 then Exit; + if csDesigning in ComponentState then Exit; + + Pt := SmallPointToPoint(Message.Pos); + if Pt.X < 0 then + Temp := Pt + else + begin + Temp := ScreenToClient(Pt); + { Changed the following. We're only interested in the non-client area } + {if not PtInRect(ClientRect, Temp) then} + if PtInRect(ClientRect, Temp) then + begin + {inherited;} + Exit; + end; + end; + + Handled := False; + DoContextPopup(Temp, Handled); + Message.Result := Ord(Handled); + if Handled then Exit; + + PopupMenu := GetPopupMenu; + if (PopupMenu <> nil) and PopupMenu.AutoPopup then + begin + SendCancelMode(nil); + PopupMenu.PopupComponent := Self; + if Pt.X < 0 then + Pt := ClientToScreen(Point(0,0)); + PopupMenu.Popup(Pt.X, Pt.Y); + Message.Result := 1; + end; + + if Message.Result = 0 then + inherited; +end; +{$ENDIF} + +procedure TTBCustomDockableWindow.GetMinShrinkSize(var AMinimumSize: Integer); +begin +end; + +function TTBCustomDockableWindow.GetFloatingWindowParentClass: TTBFloatingWindowParentClass; +begin + Result := TTBFloatingWindowParent; +end; + +procedure TTBCustomDockableWindow.GetMinMaxSize(var AMinClientWidth, + AMinClientHeight, AMaxClientWidth, AMaxClientHeight: Integer); +begin +end; + +function TTBCustomDockableWindow.GetShrinkMode: TTBShrinkMode; +begin + Result := tbsmNone; +end; + +procedure TTBCustomDockableWindow.ResizeBegin; +begin +end; + +procedure TTBCustomDockableWindow.ResizeTrack(var Rect: TRect; const OrigRect: TRect); +begin +end; + +procedure TTBCustomDockableWindow.ResizeTrackAccept; +begin +end; + +procedure TTBCustomDockableWindow.ResizeEnd; +begin +end; + +procedure TTBCustomDockableWindow.BeginSizing(const ASizeHandle: TTBSizeHandle); +var + UseSmoothDrag, DragX, DragY, ReverseX, ReverseY: Boolean; + MinWidth, MinHeight, MaxWidth, MaxHeight: Integer; + DragRect, OrigDragRect: TRect; + ScreenDC: HDC; + OrigPos, OldPos: TPoint; + + procedure DoResize; + begin + BeginUpdate; + try + ResizeTrackAccept; + Parent.BoundsRect := DragRect; + SetBounds(Left, Top, Parent.ClientWidth, Parent.ClientHeight); + finally + EndUpdate; + end; + + { Make sure it doesn't go completely off the screen } + MoveOnScreen(True); + end; + + procedure MouseMoved; + var + Pos: TPoint; + OldDragRect: TRect; + begin + GetCursorPos(Pos); + { It needs to check if the cursor actually moved since last time. This is + because a call to LockWindowUpdate (apparently) generates a mouse move + message even when mouse hasn't moved. } + if (Pos.X = OldPos.X) and (Pos.Y = OldPos.Y) then Exit; + OldPos := Pos; + + OldDragRect := DragRect; + DragRect := OrigDragRect; + if DragX then begin + if not ReverseX then Inc(DragRect.Right, Pos.X-OrigPos.X) + else Inc(DragRect.Left, Pos.X-OrigPos.X); + end; + if DragY then begin + if not ReverseY then Inc(DragRect.Bottom, Pos.Y-OrigPos.Y) + else Inc(DragRect.Top, Pos.Y-OrigPos.Y); + end; + if DragRect.Right-DragRect.Left < MinWidth then begin + if not ReverseX then DragRect.Right := DragRect.Left + MinWidth + else DragRect.Left := DragRect.Right - MinWidth; + end; + if (MaxWidth > 0) and (DragRect.Right-DragRect.Left > MaxWidth) then begin + if not ReverseX then DragRect.Right := DragRect.Left + MaxWidth + else DragRect.Left := DragRect.Right - MaxWidth; + end; + if DragRect.Bottom-DragRect.Top < MinHeight then begin + if not ReverseY then DragRect.Bottom := DragRect.Top + MinHeight + else DragRect.Top := DragRect.Bottom - MinHeight; + end; + if (MaxHeight > 0) and (DragRect.Bottom-DragRect.Top > MaxHeight) then begin + if not ReverseY then DragRect.Bottom := DragRect.Top + MaxHeight + else DragRect.Top := DragRect.Bottom - MaxHeight; + end; + + ResizeTrack(DragRect, OrigDragRect); + if not UseSmoothDrag then + DrawDraggingOutline(ScreenDC, @DragRect, @OldDragRect, False, False) + else + DoResize; + end; +var + Accept: Boolean; + Msg: TMsg; + R: TRect; +begin + if not Floating then Exit; + + Accept := False; + + UseSmoothDrag := FSmoothDrag; + + MinWidth := 0; + MinHeight := 0; + MaxWidth := 0; + MaxHeight := 0; + GetMinMaxSize(MinWidth, MinHeight, MaxWidth, MaxHeight); + Inc(MinWidth, Parent.Width-Width); + Inc(MinHeight, Parent.Height-Height); + if MaxWidth > 0 then + Inc(MaxWidth, Parent.Width-Width); + if MaxHeight > 0 then + Inc(MaxHeight, Parent.Height-Height); + + DragX := ASizeHandle in [twshLeft, twshRight, twshTopLeft, twshTopRight, + twshBottomLeft, twshBottomRight]; + ReverseX := ASizeHandle in [twshLeft, twshTopLeft, twshBottomLeft]; + DragY := ASizeHandle in [twshTop, twshTopLeft, twshTopRight, twshBottom, + twshBottomLeft, twshBottomRight]; + ReverseY := ASizeHandle in [twshTop, twshTopLeft, twshTopRight]; + + ResizeBegin(ASizeHandle); + try + { Before locking, make sure all pending paint messages are processed } + ProcessPaintMessages; + + if not UseSmoothDrag then begin + { This uses LockWindowUpdate to suppress all window updating so the + dragging outlines doesn't sometimes get garbled. (This is safe, and in + fact, is the main purpose of the LockWindowUpdate function) + IMPORTANT! While debugging you might want to enable the 'TB2Dock_DisableLock' + conditional define (see top of the source code). } + {$IFNDEF TB2Dock_DisableLock} + LockWindowUpdate(GetDesktopWindow); + {$ENDIF} + { Get a DC of the entire screen. Works around the window update lock + by specifying DCX_LOCKWINDOWUPDATE. } + ScreenDC := GetDCEx(GetDesktopWindow, 0, + DCX_LOCKWINDOWUPDATE or DCX_CACHE or DCX_WINDOW); + end + else + ScreenDC := 0; + try + SetCapture(Handle); + if (tbdsResizeClipCursor in FDockableWindowStyles) and + not UsingMultipleMonitors then begin + R := GetRectOfPrimaryMonitor(False); + ClipCursor(@R); + end; + + { Initialize } + OrigDragRect := Parent.BoundsRect; + DragRect := OrigDragRect; + if not UseSmoothDrag then + DrawDraggingOutline(ScreenDC, @DragRect, nil, False, False); + GetCursorPos(OrigPos); + OldPos := OrigPos; + + { Stay in message loop until capture is lost. Capture is removed either + by this procedure manually doing it, or by an outside influence (like + a message box or menu popping up) } + while GetCapture = Handle do begin + case Integer(GetMessage(Msg, 0, 0, 0)) of + -1: Break; { if GetMessage failed } + 0: begin + { Repost WM_QUIT messages } + PostQuitMessage(Msg.WParam); + Break; + end; + end; + + case Msg.Message of + WM_KEYDOWN, WM_KEYUP: + { Ignore all keystrokes while sizing except for Escape } + if Msg.WParam = VK_ESCAPE then + Break; + WM_MOUSEMOVE: + { Note to self: WM_MOUSEMOVE messages should never be dispatched + here to ensure no hints get shown during the drag process } + MouseMoved; + WM_LBUTTONDOWN, WM_LBUTTONDBLCLK: + { Make sure it doesn't begin another loop } + Break; + WM_LBUTTONUP: begin + Accept := True; + Break; + end; + WM_RBUTTONDOWN..WM_MBUTTONDBLCLK: + { Ignore all other mouse up/down messages } + ; + else + TranslateMessage(Msg); + DispatchMessage(Msg); + end; + end; + finally + { Since it sometimes breaks out of the loop without capture being + released } + if GetCapture = Handle then + ReleaseCapture; + ClipCursor(nil); + + if not UseSmoothDrag then begin + { Hide dragging outline. Since NT will release a window update lock if + another thread comes to the foreground, it has to release the DC + and get a new one for erasing the dragging outline. Otherwise, + the DrawDraggingOutline appears to have no effect when this happens. } + ReleaseDC(GetDesktopWindow, ScreenDC); + ScreenDC := GetDCEx(GetDesktopWindow, 0, + DCX_LOCKWINDOWUPDATE or DCX_CACHE or DCX_WINDOW); + DrawDraggingOutline(ScreenDC, nil, @DragRect, False, False); + ReleaseDC(GetDesktopWindow, ScreenDC); + + { Release window update lock } + {$IFNDEF TB2Dock_DisableLock} + LockWindowUpdate(0); + {$ENDIF} + end; + end; + + if not UseSmoothDrag and Accept then + DoResize; + finally + ResizeEnd; + end; +end; + +procedure TTBCustomDockableWindow.DoDockChangingHidden(NewFloating: Boolean; + DockingTo: TTBDock); +begin + if not(csDestroying in ComponentState) and Assigned(FOnDockChangingHidden) then + FOnDockChangingHidden(Self, NewFloating, DockingTo); +end; + +{ TTBCustomDockableWindow - property access methods } + +function TTBCustomDockableWindow.GetNonClientWidth: Integer; +begin + Result := CalcNCSizes.X; +end; + +function TTBCustomDockableWindow.GetNonClientHeight: Integer; +begin + Result := CalcNCSizes.Y; +end; + +function TTBCustomDockableWindow.IsLastDockStored: Boolean; +begin + Result := FCurrentDock = nil; {}{should this be changed to 'Floating'?} +end; + +function TTBCustomDockableWindow.IsWidthAndHeightStored: Boolean; +begin + Result := (CurrentDock = nil) and not Floating; +end; + +procedure TTBCustomDockableWindow.SetCloseButton(Value: Boolean); +begin + if FCloseButton <> Value then begin + FCloseButton := Value; + + { Update the close button's visibility } + if Parent is TTBFloatingWindowParent then + TTBFloatingWindowParent(Parent).RedrawNCArea([twrdCaption, twrdCloseButton]); + end; +end; + +procedure TTBCustomDockableWindow.SetCloseButtonWhenDocked(Value: Boolean); +begin + if FCloseButtonWhenDocked <> Value then begin + FCloseButtonWhenDocked := Value; + if Docked then + RecalcNCArea(Self); + end; +end; + +procedure TTBCustomDockableWindow.SetDefaultDock(Value: TTBDock); +begin + if FDefaultDock <> Value then begin + FDefaultDock := Value; + if Assigned(Value) then + Value.FreeNotification(Self); + end; +end; + +procedure TTBCustomDockableWindow.SetCurrentDock(Value: TTBDock); +begin + if not(csLoading in ComponentState) then begin + if Assigned(Value) then + Parent := Value + else + Parent := TBValidToolWindowParentForm(Self); + end; +end; + +procedure TTBCustomDockableWindow.SetDockPos(Value: Integer); +begin + FDockPos := Value; + if Docked then + CurrentDock.ArrangeToolbars; +end; + +procedure TTBCustomDockableWindow.SetDockRow(Value: Integer); +begin + FDockRow := Value; + if Docked then + CurrentDock.ArrangeToolbars; +end; + +procedure TTBCustomDockableWindow.SetAutoResize(Value: Boolean); +begin + if FAutoResize <> Value then begin + FAutoResize := Value; + if Value then + Arrange; + end; +end; + +procedure TTBCustomDockableWindow.SetBorderStyle(Value: TBorderStyle); +begin + if FBorderStyle <> Value then begin + FBorderStyle := Value; + if Docked then + RecalcNCArea(Self); + end; +end; + +procedure TTBCustomDockableWindow.SetDragHandleStyle(Value: TTBDragHandleStyle); +begin + if FDragHandleStyle <> Value then begin + FDragHandleStyle := Value; + if Docked then + RecalcNCArea(Self); + end; +end; + +procedure TTBCustomDockableWindow.SetFloating(Value: Boolean); +var + ParentFrm: TTBCustomForm; + NewFloatParent: TTBFloatingWindowParent; +begin + if FFloating <> Value then begin + if Value and not(csDesigning in ComponentState) then begin + ParentFrm := TBValidToolWindowParentForm(Self); + if (FFloatParent = nil) or (FFloatParent.FParentForm <> ParentFrm) then begin + NewFloatParent := GetFloatingWindowParentClass.Create(nil); + try + with NewFloatParent do begin + TWinControl(FParentForm) := ParentFrm; + FDockableWindow := Self; + Name := Format('NBFloatingWindowParent_%.8x', [Longint(NewFloatParent)]); + { ^ Must assign a unique name. In previous versions, reading in + components at run-time that had no name caused them to get assigned + names like "_1" because a component with no name -- the + TTBFloatingWindowParent form -- already existed. } + Caption := Self.Caption; + BorderStyle := bsToolWindow; + SetBounds(0, 0, (Width-ClientWidth) + Self.ClientWidth, + (Height-ClientHeight) + Self.ClientHeight); + ShowHint := True; + Visible := True; + end; + except + NewFloatParent.Free; + raise; + end; + FFloatParent := NewFloatParent; + end; + ParentFrm.FreeNotification(Self); + Parent := FFloatParent; + SetBounds(0, 0, Width, Height); + end + else + Parent := TBValidToolWindowParentForm(Self); + end; +end; + +procedure TTBCustomDockableWindow.SetFloatingMode(Value: TTBFloatingMode); +begin + if FFloatingMode <> Value then begin + FFloatingMode := Value; + if HandleAllocated then + Perform(CM_SHOWINGCHANGED, 0, 0); + end; +end; + +procedure TTBCustomDockableWindow.SetFloatingPosition(Value: TPoint); +begin + FFloatingPosition := Value; + if Floating and Assigned(Parent) then + Parent.SetBounds(Value.X, Value.Y, Parent.Width, Parent.Height); +end; + +procedure TTBCustomDockableWindow.SetFullSize(Value: Boolean); +begin + if FFullSize <> Value then begin + FFullSize := Value; + if Docked then + CurrentDock.ArrangeToolbars; + end; +end; + +procedure TTBCustomDockableWindow.SetLastDock(Value: TTBDock); +begin + if FUseLastDock and Assigned(FCurrentDock) then + { When docked, LastDock must be equal to DockedTo } + Value := FCurrentDock; + if FLastDock <> Value then begin + if Assigned(FLastDock) and (FLastDock <> Parent) then + FLastDock.ChangeDockList(False, Self); + FLastDock := Value; + if Assigned(Value) then begin + FUseLastDock := True; + Value.FreeNotification(Self); + Value.ChangeDockList(True, Self); + end; + end; +end; + +procedure TTBCustomDockableWindow.SetResizable(Value: Boolean); +begin + if FResizable <> Value then begin + FResizable := Value; + if Floating and (Parent is TTBFloatingWindowParent) then begin + { Recreate the window handle because Resizable affects whether the + tool window is created with a WS_THICKFRAME style } + TTBFloatingWindowParent(Parent).RecreateWnd; + end; + end; +end; + +procedure TTBCustomDockableWindow.SetShowCaption(Value: Boolean); +begin + if FShowCaption <> Value then begin + FShowCaption := Value; + if Floating then begin + { Recalculate FloatingWindowParent's NC area, and resize the toolbar + accordingly } + RecalcNCArea(Parent); + Arrange; + end; + end; +end; + +procedure TTBCustomDockableWindow.SetStretch(Value: Boolean); +begin + if FStretch <> Value then begin + FStretch := Value; + if Docked then + CurrentDock.ArrangeToolbars; + end; +end; + +procedure TTBCustomDockableWindow.SetUseLastDock(Value: Boolean); +begin + if FUseLastDock <> Value then begin + FUseLastDock := Value; + if not Value then + LastDock := nil + else + LastDock := FCurrentDock; + end; +end; + +(*function TTBCustomDockableWindow.GetVersion: TToolbar97Version; +begin + Result := Toolbar97VersionPropText; +end; + +procedure TTBCustomDockableWindow.SetVersion(const Value: TToolbar97Version); +begin + { write method required for the property to show up in Object Inspector } +end;*) + + +{ TTBBackground } + +type + PNotifyEvent = ^TNotifyEvent; + +constructor TTBBackground.Create(AOwner: TComponent); +begin + inherited; + FBkColor := clBtnFace; + FBitmap := TBitmap.Create; + FBitmap.OnChange := BitmapChanged; +end; + +destructor TTBBackground.Destroy; +var + I: Integer; +begin + inherited; + FBitmapCache.Free; + FBitmap.Free; + if Assigned(FNotifyList) then begin + for I := FNotifyList.Count-1 downto 0 do + Dispose(PNotifyEvent(FNotifyList[I])); + FNotifyList.Free; + end; +end; + +procedure TTBBackground.BitmapChanged(Sender: TObject); +var + I: Integer; +begin + { Erase the cache and notify } + FBitmapCache.Free; + FBitmapCache := nil; + if Assigned(FNotifyList) then + for I := 0 to FNotifyList.Count-1 do + PNotifyEvent(FNotifyList[I])^(Self); +end; + +procedure TTBBackground.Draw(DC: HDC; const DrawRect: TRect); +var + UseBmp: TBitmap; + R2: TRect; + SaveIndex: Integer; + DC2: HDC; + Brush: HBRUSH; + P: TPoint; +begin + if FBitmapCache = nil then begin + FBitmapCache := TBitmap.Create; + FBitmapCache.Palette := CopyPalette(FBitmap.Palette); + FBitmapCache.Width := FBitmap.Width; + FBitmapCache.Height := FBitmap.Height; + if not FTransparent then begin + { Copy from a possible DIB to our DDB } + BitBlt(FBitmapCache.Canvas.Handle, 0, 0, FBitmapCache.Width, + FBitmapCache.Height, FBitmap.Canvas.Handle, 0, 0, SRCCOPY); + end + else begin + with FBitmapCache do begin + Canvas.Brush.Color := FBkColor; + R2 := Rect(0, 0, Width, Height); + Canvas.BrushCopy(R2, FBitmap, R2, + FBitmap.Canvas.Pixels[0, Height-1] or $02000000); + end; + end; + FBitmap.Dormant; + end; + UseBmp := FBitmapCache; + + DC2 := 0; + SaveIndex := SaveDC(DC); + try + if UseBmp.Palette <> 0 then begin + SelectPalette(DC, UseBmp.Palette, True); + RealizePalette(DC); + end; + { Note: versions of Toolbar97 prior to 1.68 used 'UseBmp.Canvas.Handle' + instead of DC2 in the BitBlt call. This was changed because there + seems to be a bug in D2/BCB1's Graphics.pas: if you called + .Background.LoadFromFile() twice the background + would not be shown. } + if (UseBmp.Width = 8) and (UseBmp.Height = 8) then begin + { Use pattern brushes to draw 8x8 bitmaps. + Note: Win9x can't use bitmaps <8x8 in size for pattern brushes } + Brush := CreatePatternBrush(UseBmp.Handle); + GetWindowOrgEx(DC, P); + SetBrushOrgEx(DC, DrawRect.Left - P.X, DrawRect.Top - P.Y, nil); + FillRect(DC, DrawRect, Brush); + DeleteObject(Brush); + end + else begin + { BitBlt is faster than pattern brushes on large bitmaps } + DC2 := CreateCompatibleDC(DC); + SelectObject(DC2, UseBmp.Handle); + R2 := DrawRect; + while R2.Left < R2.Right do begin + while R2.Top < R2.Bottom do begin + BitBlt(DC, R2.Left, R2.Top, UseBmp.Width, UseBmp.Height, + DC2, 0, 0, SRCCOPY); + Inc(R2.Top, UseBmp.Height); + end; + R2.Top := DrawRect.Top; + Inc(R2.Left, UseBmp.Width); + end; + end; + finally + if DC2 <> 0 then + DeleteDC(DC2); + { Restore the palette and brush origin back } + RestoreDC(DC, SaveIndex); + end; +end; + +function TTBBackground.GetPalette: HPALETTE; +begin + Result := FBitmap.Palette; +end; + +procedure TTBBackground.SysColorChanged; +begin + if FTransparent and (FBkColor < 0) then + BitmapChanged(nil); +end; + +function TTBBackground.UsingBackground: Boolean; +begin + Result := (FBitmap.Width <> 0) and (FBitmap.Height <> 0); +end; + +procedure TTBBackground.RegisterChanges(Proc: TNotifyEvent); +var + I: Integer; + P: PNotifyEvent; +begin + if FNotifyList = nil then + FNotifyList := TList.Create; + for I := 0 to FNotifyList.Count-1 do begin + P := FNotifyList[I]; + if (TMethod(P^).Code = TMethod(Proc).Code) and + (TMethod(P^).Data = TMethod(Proc).Data) then + Exit; + end; + FNotifyList.Expand; + New(P); + P^ := Proc; + FNotifyList.Add(P); +end; + +procedure TTBBackground.UnregisterChanges(Proc: TNotifyEvent); +var + I: Integer; + P: PNotifyEvent; +begin + if FNotifyList = nil then + Exit; + for I := 0 to FNotifyList.Count-1 do begin + P := FNotifyList[I]; + if (TMethod(P^).Code = TMethod(Proc).Code) and + (TMethod(P^).Data = TMethod(Proc).Data) then begin + FNotifyList.Delete(I); + Dispose(P); + Break; + end; + end; +end; + +procedure TTBBackground.SetBkColor(Value: TColor); +begin + if FBkColor <> Value then begin + FBkColor := Value; + if FTransparent then + BitmapChanged(nil); + end; +end; + +procedure TTBBackground.SetBitmap(Value: TBitmap); +begin + FBitmap.Assign(Value); +end; + +procedure TTBBackground.SetTransparent(Value: Boolean); +begin + if FTransparent <> Value then begin + FTransparent := Value; + BitmapChanged(nil); + end; +end; + + +{ Global procedures } + +procedure TBCustomLoadPositions(const OwnerComponent: TComponent; + const ReadIntProc: TTBPositionReadIntProc; + const ReadStringProc: TTBPositionReadStringProc; const ExtraData: Pointer); +var + Rev: Integer; + + function FindDock(AName: String): TTBDock; + var + I: Integer; + begin + Result := nil; + for I := 0 to OwnerComponent.ComponentCount-1 do + if (OwnerComponent.Components[I] is TTBDock) and + (CompareText(OwnerComponent.Components[I].Name, AName) = 0) then begin + Result := TTBDock(OwnerComponent.Components[I]); + Break; + end; + end; + + procedure ReadValues(const Toolbar: TTBCustomDockableWindow; const NewDock: TTBDock); + var + Pos: TPoint; + Data: TTBReadPositionData; + LastDockName: String; + ADock: TTBDock; + begin + with Toolbar do begin + DockRow := ReadIntProc(Name, rvDockRow, DockRow, ExtraData); + DockPos := ReadIntProc(Name, rvDockPos, DockPos, ExtraData); + Pos.X := ReadIntProc(Name, rvFloatLeft, 0, ExtraData); + Pos.Y := ReadIntProc(Name, rvFloatTop, 0, ExtraData); + @Data.ReadIntProc := @ReadIntProc; + @Data.ReadStringProc := @ReadStringProc; + Data.ExtraData := ExtraData; + ReadPositionData(Data); + FloatingPosition := Pos; + if Assigned(NewDock) then + Parent := NewDock + else begin + //Parent := Form; + Floating := True; + MoveOnScreen(True); + if (Rev >= 3) and FUseLastDock then begin + LastDockName := ReadStringProc(Name, rvLastDock, '', ExtraData); + if LastDockName <> '' then begin + ADock := FindDock(LastDockName); + if Assigned(ADock) then + LastDock := ADock; + end; + end; + end; + Arrange; + DoneReadingPositionData(Data); + end; + end; + +var + DocksDisabled: TList; + I: Integer; + ToolWindow: TComponent; + ADock: TTBDock; + DockedToName: String; +begin + DocksDisabled := TList.Create; + try + with OwnerComponent do + for I := 0 to ComponentCount-1 do + if Components[I] is TTBDock then begin + TTBDock(Components[I]).BeginUpdate; + DocksDisabled.Add(Components[I]); + end; + + for I := 0 to OwnerComponent.ComponentCount-1 do begin + ToolWindow := OwnerComponent.Components[I]; + if ToolWindow is TTBCustomDockableWindow then + with TTBCustomDockableWindow(ToolWindow) do begin + {}{should skip over toolbars that are neither Docked nor Floating } + if Name = '' then + raise Exception.Create(STBToolWinNameNotSet); + Rev := ReadIntProc(Name, rvRev, 0, ExtraData); + if Rev = 2000 then begin + Visible := ReadIntProc(Name, rvVisible, Ord(Visible), ExtraData) <> 0; + DockedToName := ReadStringProc(Name, rvDockedTo, '', ExtraData); + if DockedToName <> '' then begin + if DockedToName <> rdDockedToFloating then begin + ADock := FindDock(DockedToName); + if (ADock <> nil) and (ADock.FAllowDrag) then + ReadValues(TTBCustomDockableWindow(ToolWindow), ADock); + end + else + ReadValues(TTBCustomDockableWindow(ToolWindow), nil); + end; + end; + end; + end; + finally + for I := DocksDisabled.Count-1 downto 0 do + TTBDock(DocksDisabled[I]).EndUpdate; + DocksDisabled.Free; + end; +end; + +procedure TBCustomSavePositions(const OwnerComponent: TComponent; + const WriteIntProc: TTBPositionWriteIntProc; + const WriteStringProc: TTBPositionWriteStringProc; const ExtraData: Pointer); +var + I: Integer; + N, L: String; + Data: TTBWritePositionData; +begin + for I := 0 to OwnerComponent.ComponentCount-1 do + if OwnerComponent.Components[I] is TTBCustomDockableWindow then + with TTBCustomDockableWindow(OwnerComponent.Components[I]) do begin + if Name = '' then + raise Exception.Create(STBToolwinNameNotSet); + if Floating then + N := rdDockedToFloating + else if Docked then begin + if CurrentDock.FAllowDrag then begin + N := CurrentDock.Name; + if N = '' then + raise Exception.Create(STBToolwinDockedToNameNotSet); + end + else + N := ''; + end + else + Continue; { skip if it's neither floating nor docked } + L := ''; + if Assigned(FLastDock) then + L := FLastDock.Name; + WriteIntProc(Name, rvRev, rdCurrentRev, ExtraData); + WriteIntProc(Name, rvVisible, Ord(Visible), ExtraData); + WriteStringProc(Name, rvDockedTo, N, ExtraData); + WriteStringProc(Name, rvLastDock, L, ExtraData); + WriteIntProc(Name, rvDockRow, FDockRow, ExtraData); + WriteIntProc(Name, rvDockPos, FDockPos, ExtraData); + WriteIntProc(Name, rvFloatLeft, FFloatingPosition.X, ExtraData); + WriteIntProc(Name, rvFloatTop, FFloatingPosition.Y, ExtraData); + @Data.WriteIntProc := @WriteIntProc; + @Data.WriteStringProc := @WriteStringProc; + Data.ExtraData := ExtraData; + WritePositionData(Data); + end; +end; + +type + PIniReadWriteData = ^TIniReadWriteData; + TIniReadWriteData = record + IniFile: TIniFile; + SectionNamePrefix: String; + end; + +function IniReadInt(const ToolbarName, Value: String; const Default: Longint; + const ExtraData: Pointer): Longint; far; +begin + Result := PIniReadWriteData(ExtraData).IniFile.ReadInteger( + PIniReadWriteData(ExtraData).SectionNamePrefix + ToolbarName, Value, Default); +end; +function IniReadString(const ToolbarName, Value, Default: String; + const ExtraData: Pointer): String; far; +begin + Result := PIniReadWriteData(ExtraData).IniFile.ReadString( + PIniReadWriteData(ExtraData).SectionNamePrefix + ToolbarName, Value, Default); +end; +procedure IniWriteInt(const ToolbarName, Value: String; const Data: Longint; + const ExtraData: Pointer); far; +begin + PIniReadWriteData(ExtraData).IniFile.WriteInteger( + PIniReadWriteData(ExtraData).SectionNamePrefix + ToolbarName, Value, Data); +end; +procedure IniWriteString(const ToolbarName, Value, Data: String; + const ExtraData: Pointer); far; +begin + PIniReadWriteData(ExtraData).IniFile.WriteString( + PIniReadWriteData(ExtraData).SectionNamePrefix + ToolbarName, Value, Data); +end; + +procedure TBIniLoadPositions(const OwnerComponent: TComponent; + const Filename, SectionNamePrefix: String); +var + Data: TIniReadWriteData; +begin + Data.IniFile := TIniFile.Create(Filename); + try + Data.SectionNamePrefix := SectionNamePrefix; + TBCustomLoadPositions(OwnerComponent, IniReadInt, IniReadString, @Data); + finally + Data.IniFile.Free; + end; +end; + +procedure TBIniSavePositions(const OwnerComponent: TComponent; + const Filename, SectionNamePrefix: String); +var + Data: TIniReadWriteData; +begin + Data.IniFile := TIniFile.Create(Filename); + try + Data.SectionNamePrefix := SectionNamePrefix; + TBCustomSavePositions(OwnerComponent, IniWriteInt, IniWriteString, @Data); + finally + Data.IniFile.Free; + end; +end; + +function RegReadInt(const ToolbarName, Value: String; const Default: Longint; + const ExtraData: Pointer): Longint; far; +begin + Result := TRegIniFile(ExtraData).ReadInteger(ToolbarName, Value, Default); +end; +function RegReadString(const ToolbarName, Value, Default: String; + const ExtraData: Pointer): String; far; +begin + Result := TRegIniFile(ExtraData).ReadString(ToolbarName, Value, Default); +end; +procedure RegWriteInt(const ToolbarName, Value: String; const Data: Longint; + const ExtraData: Pointer); far; +begin + TRegIniFile(ExtraData).WriteInteger(ToolbarName, Value, Data); +end; +procedure RegWriteString(const ToolbarName, Value, Data: String; + const ExtraData: Pointer); far; +begin + TRegIniFile(ExtraData).WriteString(ToolbarName, Value, Data); +end; + +procedure TBRegLoadPositions(const OwnerComponent: TComponent; + const RootKey: DWORD; const BaseRegistryKey: String); +var + Reg: TRegIniFile; +begin + Reg := TRegIniFile.Create(''); + try + Reg.RootKey := RootKey; + Reg.OpenKey(BaseRegistryKey, True); { assigning to RootKey resets the current key } + TBCustomLoadPositions(OwnerComponent, RegReadInt, RegReadString, Reg); + finally + Reg.Free; + end; +end; + +procedure TBRegSavePositions(const OwnerComponent: TComponent; + const RootKey: DWORD; const BaseRegistryKey: String); +var + Reg: TRegIniFile; +begin + Reg := TRegIniFile.Create(''); + try + Reg.RootKey := RootKey; + Reg.OpenKey(BaseRegistryKey, True); { assigning to RootKey resets the current key } + TBCustomSavePositions(OwnerComponent, RegWriteInt, RegWriteString, Reg); + finally + Reg.Free; + end; +end; + +end. diff --git a/official/2.1.6+2.1.beta1/Source/TB2Dock.pas.orig b/official/2.1.6+2.1.beta1/Source/TB2Dock.pas.orig new file mode 100644 index 0000000..03c6919 --- /dev/null +++ b/official/2.1.6+2.1.beta1/Source/TB2Dock.pas.orig @@ -0,0 +1,5538 @@ +unit TB2Dock; + +{ + Toolbar2000 + Copyright (C) 1998-2005 by Jordan Russell + All rights reserved. + + The contents of this file are subject to the "Toolbar2000 License"; you may + not use or distribute this file except in compliance with the + "Toolbar2000 License". A copy of the "Toolbar2000 License" may be found in + TB2k-LICENSE.txt or at: + http://www.jrsoftware.org/files/tb2k/TB2k-LICENSE.txt + + Alternatively, the contents of this file may be used under the terms of the + GNU General Public License (the "GPL"), in which case the provisions of the + GPL are applicable instead of those in the "Toolbar2000 License". A copy of + the GPL may be found in GPL-LICENSE.txt or at: + http://www.jrsoftware.org/files/tb2k/GPL-LICENSE.txt + If you wish to allow use of your version of this file only under the terms of + the GPL and not to allow others to use your version of this file under the + "Toolbar2000 License", indicate your decision by deleting the provisions + above and replace them with the notice and other provisions required by the + GPL. If you do not delete the provisions above, a recipient may use your + version of this file under either the "Toolbar2000 License" or the GPL. + + $jrsoftware: tb2k/Source/TB2Dock.pas,v 1.99 2005/07/15 19:35:03 jr Exp $ +} + +interface + +{x$DEFINE TB2Dock_DisableLock} +{ Remove the 'x' to enable the define. It will disable calls to + LockWindowUpdate, which it calls to disable screen updates while dragging. + You may want to temporarily enable the define while debugging so you are able + to see your code window while stepping through the dragging routines. } + +{$I TB2Ver.inc} + +uses + Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms; + +type + TTBCustomForm = {$IFDEF JR_D3} TCustomForm {$ELSE} TForm {$ENDIF}; + + { TTBDock } + + TTBDockBoundLinesValues = (blTop, blBottom, blLeft, blRight); + TTBDockBoundLines = set of TTBDockBoundLinesValues; + TTBDockPosition = (dpTop, dpBottom, dpLeft, dpRight); + TTBDockType = (dtNotDocked, dtFloating, dtTopBottom, dtLeftRight); + TTBDockableTo = set of TTBDockPosition; + + TTBCustomDockableWindow = class; + TTBBasicBackground = class; + + TTBInsertRemoveEvent = procedure(Sender: TObject; Inserting: Boolean; + Bar: TTBCustomDockableWindow) of object; + TTBRequestDockEvent = procedure(Sender: TObject; Bar: TTBCustomDockableWindow; + var Accept: Boolean) of object; + + TTBDock = class(TCustomControl) + private + { Property values } + FPosition: TTBDockPosition; + FAllowDrag: Boolean; + FBoundLines: TTBDockBoundLines; + FBackground: TTBBasicBackground; + FBkgOnToolbars: Boolean; + FFixAlign: Boolean; + FCommitNewPositions: Boolean; + FLimitToOneRow: Boolean; + FOnInsertRemoveBar: TTBInsertRemoveEvent; + FOnRequestDock: TTBRequestDockEvent; + {$IFNDEF JR_D4} + FOnResize: TNotifyEvent; + {$ENDIF} + + { Internal } + FDisableArrangeToolbars: Integer; { Increment to disable ArrangeToolbars } + FArrangeToolbarsNeeded: Boolean; + FNonClientWidth, FNonClientHeight: Integer; + DockList: TList; { List of the toolbars docked, and those floating and have LastDock + pointing to the dock. Items are casted in TTBCustomDockableWindow's. } + DockVisibleList: TList; { Similar to DockList, but lists only docked and visible toolbars } + + { Property access methods } + //function GetVersion: TToolbar97Version; + procedure SetAllowDrag(Value: Boolean); + procedure SetBackground(Value: TTBBasicBackground); + procedure SetBackgroundOnToolbars(Value: Boolean); + procedure SetBoundLines(Value: TTBDockBoundLines); + procedure SetFixAlign(Value: Boolean); + procedure SetPosition(Value: TTBDockPosition); + //procedure SetVersion(const Value: TToolbar97Version); + + function GetToolbarCount: Integer; + function GetToolbars(Index: Integer): TTBCustomDockableWindow; + + { Internal } + procedure BackgroundChanged(Sender: TObject); + procedure ChangeDockList(const Insert: Boolean; const Bar: TTBCustomDockableWindow); + procedure ChangeWidthHeight(const NewWidth, NewHeight: Integer); + procedure CommitPositions; + procedure DrawNCArea(const DrawToDC: Boolean; const ADC: HDC; + const Clip: HRGN); + function GetDesignModeRowOf(const XY: Integer): Integer; + function HasVisibleToolbars: Boolean; + procedure RelayMsgToFloatingBars(var Message: TMessage); + function ToolbarVisibleOnDock(const AToolbar: TTBCustomDockableWindow): Boolean; + procedure ToolbarVisibilityChanged(const Bar: TTBCustomDockableWindow; + const ForceRemove: Boolean); + + { Messages } + procedure CMDialogChar(var Message: TCMDialogChar); message CM_DIALOGCHAR; + procedure CMDialogKey(var Message: TCMDialogKey); message CM_DIALOGKEY; + procedure CMSysColorChange(var Message: TMessage); message CM_SYSCOLORCHANGE; + procedure WMEraseBkgnd(var Message: TWMEraseBkgnd); message WM_ERASEBKGND; + procedure WMMove(var Message: TWMMove); message WM_MOVE; + {$IFNDEF JR_D4} + procedure WMSize(var Message: TWMSize); message WM_SIZE; + {$ENDIF} + procedure WMNCCalcSize(var Message: TWMNCCalcSize); message WM_NCCALCSIZE; + procedure WMNCPaint(var Message: TMessage); message WM_NCPAINT; + procedure WMPrint(var Message: TMessage); message WM_PRINT; + procedure WMPrintClient(var Message: TMessage); message WM_PRINTCLIENT; + procedure WMSysCommand(var Message: TWMSysCommand); message WM_SYSCOMMAND; + protected + procedure AlignControls(AControl: TControl; var Rect: TRect); override; + procedure DrawBackground(DC: HDC; const DrawRect: TRect); virtual; + function GetPalette: HPALETTE; override; + procedure InvalidateBackgrounds; + procedure Loaded; override; + procedure Notification(AComponent: TComponent; Operation: TOperation); override; + procedure SetParent(AParent: TWinControl); override; + procedure Paint; override; + function UsingBackground: Boolean; virtual; + public + constructor Create(AOwner: TComponent); override; + procedure CreateParams(var Params: TCreateParams); override; + destructor Destroy; override; + + procedure ArrangeToolbars; + procedure BeginUpdate; + procedure EndUpdate; + function GetCurrentRowSize(const Row: Integer; var AFullSize: Boolean): Integer; + function GetHighestRow(const HighestEffective: Boolean): Integer; + function GetMinRowSize(const Row: Integer; + const ExcludeControl: TTBCustomDockableWindow): Integer; + + property CommitNewPositions: Boolean read FCommitNewPositions write FCommitNewPositions; + property NonClientWidth: Integer read FNonClientWidth; + property NonClientHeight: Integer read FNonClientHeight; + property ToolbarCount: Integer read GetToolbarCount; + property Toolbars[Index: Integer]: TTBCustomDockableWindow read GetToolbars; + published + property AllowDrag: Boolean read FAllowDrag write SetAllowDrag default True; + property Background: TTBBasicBackground read FBackground write SetBackground; + property BackgroundOnToolbars: Boolean read FBkgOnToolbars write SetBackgroundOnToolbars default True; + property BoundLines: TTBDockBoundLines read FBoundLines write SetBoundLines default []; + property Color default clBtnFace; + property FixAlign: Boolean read FFixAlign write SetFixAlign default False; + property LimitToOneRow: Boolean read FLimitToOneRow write FLimitToOneRow default False; + property PopupMenu; + property Position: TTBDockPosition read FPosition write SetPosition default dpTop; + //property Version: TToolbar97Version read GetVersion write SetVersion stored False; + property Visible; + + {$IFDEF JR_D5} + property OnContextPopup; + {$ENDIF} + property OnInsertRemoveBar: TTBInsertRemoveEvent read FOnInsertRemoveBar write FOnInsertRemoveBar; + property OnMouseDown; + property OnMouseMove; + property OnMouseUp; + property OnRequestDock: TTBRequestDockEvent read FOnRequestDock write FOnRequestDock; + {$IFDEF JR_D4} + property OnResize; + {$ELSE} + property OnResize: TNotifyEvent read FOnResize write FOnResize; + {$ENDIF} + end; + + { TTBFloatingWindowParent - internal } + + TTBToolWindowNCRedrawWhatElement = (twrdBorder, twrdCaption, twrdCloseButton); + TTBToolWindowNCRedrawWhat = set of TTBToolWindowNCRedrawWhatElement; + + TTBFloatingWindowParentClass = class of TTBFloatingWindowParent; + TTBFloatingWindowParent = class(TCustomForm) + private + FCloseButtonDown: Boolean; { True if Close button is currently depressed } + FDockableWindow: TTBCustomDockableWindow; + FParentForm: TTBCustomForm; + FShouldShow: Boolean; + + procedure SetCloseButtonState(Pushed: Boolean); + procedure RedrawNCArea(const RedrawWhat: TTBToolWindowNCRedrawWhat); + + procedure CMShowingChanged(var Message: TMessage); message CM_SHOWINGCHANGED; + procedure CMDialogKey(var Message: TCMDialogKey); message CM_DIALOGKEY; + procedure CMTextChanged(var Message: TMessage); message CM_TEXTCHANGED; + procedure WMActivate(var Message: TWMActivate); message WM_ACTIVATE; + procedure WMClose(var Message: TWMClose); message WM_CLOSE; + procedure WMGetMinMaxInfo(var Message: TWMGetMinMaxInfo); message WM_GETMINMAXINFO; + procedure WMMouseActivate(var Message: TWMMouseActivate); message WM_MOUSEACTIVATE; + procedure WMMove(var Message: TWMMove); message WM_MOVE; + procedure WMNCCalcSize(var Message: TWMNCCalcSize); message WM_NCCALCSIZE; + procedure WMNCHitTest(var Message: TWMNCHitTest); message WM_NCHITTEST; + procedure WMNCLButtonDblClk(var Message: TWMNCLButtonDblClk); message WM_NCLBUTTONDBLCLK; + procedure WMNCLButtonDown(var Message: TWMNCLButtonDown); message WM_NCLBUTTONDOWN; + procedure WMNCPaint(var Message: TMessage); message WM_NCPAINT; + procedure WMNCRButtonUp(var Message: TWMNCRButtonUp); message WM_NCRBUTTONUP; + procedure WMPrint(var Message: TMessage); message WM_PRINT; + procedure WMPrintClient(var Message: TMessage); message WM_PRINTCLIENT; + protected + procedure AlignControls(AControl: TControl; var Rect: TRect); override; + procedure CreateParams(var Params: TCreateParams); override; + procedure DrawNCArea(const DrawToDC: Boolean; const ADC: HDC; + const Clip: HRGN; RedrawWhat: TTBToolWindowNCRedrawWhat); dynamic; + property DockableWindow: TTBCustomDockableWindow read FDockableWindow; + property CloseButtonDown: Boolean read FCloseButtonDown; + public + property ParentForm: TTBCustomForm read FParentForm; + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + end; + + { TTBCustomDockableWindow } + + TTBDockChangingEvent = procedure(Sender: TObject; Floating: Boolean; + DockingTo: TTBDock) of object; + TTBDragHandleStyle = (dhDouble, dhNone, dhSingle); + TTBDockMode = (dmCanFloat, dmCannotFloat, dmCannotFloatOrChangeDocks); + TTBFloatingMode = (fmOnTopOfParentForm, fmOnTopOfAllForms); + TTBSizeHandle = (twshLeft, twshRight, twshTop, twshTopLeft, + twshTopRight, twshBottom, twshBottomLeft, twshBottomRight); + { ^ must be in same order as HTLEFT..HTBOTTOMRIGHT } + TTBPositionReadIntProc = function(const ToolbarName, Value: String; const Default: Longint; + const ExtraData: Pointer): Longint; + TTBPositionReadStringProc = function(const ToolbarName, Value, Default: String; + const ExtraData: Pointer): String; + TTBPositionWriteIntProc = procedure(const ToolbarName, Value: String; const Data: Longint; + const ExtraData: Pointer); + TTBPositionWriteStringProc = procedure(const ToolbarName, Value, Data: String; + const ExtraData: Pointer); + TTBReadPositionData = record + ReadIntProc: TTBPositionReadIntProc; + ReadStringProc: TTBPositionReadStringProc; + ExtraData: Pointer; + end; + TTBWritePositionData = record + WriteIntProc: TTBPositionWriteIntProc; + WriteStringProc: TTBPositionWriteStringProc; + ExtraData: Pointer; + end; + TTBDockableWindowStyles = set of (tbdsResizeEightCorner, tbdsResizeClipCursor); + TTBShrinkMode = (tbsmNone, tbsmWrap, tbsmChevron); + + TTBCustomDockableWindow = class(TCustomControl) + private + { Property variables } + FAutoResize: Boolean; + FDockPos, FDockRow, FEffectiveDockPos, FEffectiveDockRow: Integer; + FDocked: Boolean; + FCurrentDock, FDefaultDock, FLastDock: TTBDock; + FCurrentSize: Integer; + FFloating: Boolean; + FOnClose, FOnDockChanged, FOnMove, FOnRecreated, + FOnRecreating, {$IFNDEF JR_D4} FOnResize, {$ENDIF} + FOnVisibleChanged: TNotifyEvent; + FOnCloseQuery: TCloseQueryEvent; + FOnDockChanging, FOnDockChangingHidden: TTBDockChangingEvent; + FActivateParent, FHideWhenInactive, FCloseButton, FCloseButtonWhenDocked, + FFullSize, FResizable, FShowCaption, FStretch, FUseLastDock: Boolean; + FBorderStyle: TBorderStyle; + FDockMode: TTBDockMode; + FDragHandleStyle: TTBDragHandleStyle; + FDockableTo: TTBDockableTo; + FFloatingMode: TTBFloatingMode; + FSmoothDrag: Boolean; + FDockableWindowStyles: TTBDockableWindowStyles; + FLastRowSize: Integer; + FInsertRowBefore: Boolean; + + { Misc. } + FUpdatingBounds, { Incremented while internally changing the bounds. This allows + it to move the toolbar freely in design mode and prevents the + SizeChanging protected method from begin called } + FDisableArrange, { Incremented to disable Arrange } + FDisableOnMove, { Incremented to prevent WM_MOVE handler from calling the OnMoved handler } + FHidden: Integer; { Incremented while the toolbar is temporarily hidden } + FArrangeNeeded, FMoved: Boolean; + FInactiveCaption: Boolean; { True when the caption of the toolbar is currently the inactive color } + FFloatingPosition: TPoint; + FDockForms: TList; + FSavedAtRunTime: Boolean; + //FNonClientWidth, FNonClientHeight: Integer; + FDragMode, FDragSplitting, FDragCanSplit: Boolean; + FSmoothDragging: Boolean; + + { When floating. These are not used in design mode } + FCloseButtonDown: Boolean; { True if Close button is currently depressed } + FCloseButtonHover: Boolean; + FFloatParent: TTBFloatingWindowParent; { Run-time only: The actual Parent of the toolbar when it is floating } + + { Property access methods } + //function GetVersion: TToolbar97Version; + function GetNonClientWidth: Integer; + function GetNonClientHeight: Integer; + function IsLastDockStored: Boolean; + function IsWidthAndHeightStored: Boolean; + procedure SetAutoResize(Value: Boolean); + procedure SetBorderStyle(Value: TBorderStyle); + procedure SetCloseButton(Value: Boolean); + procedure SetCloseButtonWhenDocked(Value: Boolean); + procedure SetCurrentDock(Value: TTBDock); + procedure SetDefaultDock(Value: TTBDock); + procedure SetDockPos(Value: Integer); + procedure SetDockRow(Value: Integer); + procedure SetDragHandleStyle(Value: TTBDragHandleStyle); + procedure SetFloating(Value: Boolean); + procedure SetFloatingMode(Value: TTBFloatingMode); + procedure SetFloatingPosition(Value: TPoint); + procedure SetFullSize(Value: Boolean); + procedure SetLastDock(Value: TTBDock); + procedure SetResizable(Value: Boolean); + procedure SetShowCaption(Value: Boolean); + procedure SetStretch(Value: Boolean); + procedure SetUseLastDock(Value: Boolean); + //procedure SetVersion(const Value: TToolbar97Version); + + { Internal } + procedure CancelNCHover; + procedure DrawDraggingOutline(const DC: HDC; const NewRect, OldRect: PRect; + const NewDocking, OldDocking: Boolean); + procedure RedrawNCArea; + procedure SetCloseButtonState(Pushed: Boolean); + procedure ShowNCContextMenu(const Pos: TSmallPoint); + procedure Moved; + function GetShowingState: Boolean; + procedure UpdateCaptionState; + procedure UpdateTopmostFlag; + procedure UpdateVisibility; + procedure ReadSavedAtRunTime(Reader: TReader); + procedure WriteSavedAtRunTime(Writer: TWriter); + + { Messages } + procedure CMColorChanged(var Message: TMessage); message CM_COLORCHANGED; + procedure CMMouseLeave(var Message: TMessage); message CM_MOUSELEAVE; + procedure CMTextChanged(var Message: TMessage); message CM_TEXTCHANGED; + procedure CMShowingChanged(var Message: TMessage); message CM_SHOWINGCHANGED; + procedure CMVisibleChanged(var Message: TMessage); message CM_VISIBLECHANGED; + {$IFDEF JR_D5} + procedure WMContextMenu(var Message: TWMContextMenu); message WM_CONTEXTMENU; + {$ENDIF} + procedure WMEnable(var Message: TWMEnable); message WM_ENABLE; + procedure WMEraseBkgnd(var Message: TWMEraseBkgnd); message WM_ERASEBKGND; + procedure WMMove(var Message: TWMMove); message WM_MOVE; + procedure WMMouseMove(var Message: TMessage); message WM_MOUSEMOVE; + procedure WMNCCalcSize(var Message: TWMNCCalcSize); message WM_NCCALCSIZE; + procedure WMNCHitTest(var Message: TWMNCHitTest); message WM_NCHITTEST; + procedure WMNCMouseLeave(var Message: TMessage); message $2A2 {WM_NCMOUSELEAVE}; + procedure WMNCMouseMove(var Message: TWMNCMouseMove); message WM_NCMOUSEMOVE; + procedure WMNCLButtonDblClk(var Message: TWMNCLButtonDblClk); message WM_NCLBUTTONDBLCLK; + procedure WMNCLButtonDown(var Message: TWMNCLButtonDown); message WM_NCLBUTTONDOWN; + procedure WMNCPaint(var Message: TMessage); message WM_NCPAINT; + procedure WMNCRButtonUp(var Message: TWMNCRButtonUp); message WM_NCRBUTTONUP; + procedure WMPrint(var Message: TMessage); message WM_PRINT; + procedure WMPrintClient(var Message: TMessage); message WM_PRINTCLIENT; + procedure WMSetCursor(var Message: TWMSetCursor); message WM_SETCURSOR; + {$IFNDEF JR_D4} + procedure WMSize(var Message: TWMSize); message WM_SIZE; + {$ENDIF} + protected + property ActivateParent: Boolean read FActivateParent write FActivateParent default True; + property AutoResize: Boolean read FAutoResize write SetAutoResize default True; + property BorderStyle: TBorderStyle read FBorderStyle write SetBorderStyle default bsSingle; + property Color default clBtnFace; + property CloseButton: Boolean read FCloseButton write SetCloseButton default True; + property CloseButtonDown: Boolean read FCloseButtonDown; + property CloseButtonHover: Boolean read FCloseButtonHover; + property CloseButtonWhenDocked: Boolean read FCloseButtonWhenDocked write SetCloseButtonWhenDocked default False; + property DefaultDock: TTBDock read FDefaultDock write SetDefaultDock; + property DockableTo: TTBDockableTo read FDockableTo write FDockableTo default [dpTop, dpBottom, dpLeft, dpRight]; + property DockableWindowStyles: TTBDockableWindowStyles read FDockableWindowStyles write FDockableWindowStyles; + property DockMode: TTBDockMode read FDockMode write FDockMode default dmCanFloat; + property DragHandleStyle: TTBDragHandleStyle read FDragHandleStyle write SetDragHandleStyle default dhSingle; + property FloatingMode: TTBFloatingMode read FFloatingMode write SetFloatingMode default fmOnTopOfParentForm; + property FullSize: Boolean read FFullSize write SetFullSize default False; + property InactiveCaption: Boolean read FInactiveCaption; + property HideWhenInactive: Boolean read FHideWhenInactive write FHideWhenInactive default True; + property Resizable: Boolean read FResizable write SetResizable default True; + property ShowCaption: Boolean read FShowCaption write SetShowCaption default True; + property SmoothDrag: Boolean read FSmoothDrag write FSmoothDrag default True; + property Stretch: Boolean read FStretch write SetStretch default False; + property UseLastDock: Boolean read FUseLastDock write SetUseLastDock default True; + //property Version: TToolbar97Version read GetVersion write SetVersion stored False; + + property OnClose: TNotifyEvent read FOnClose write FOnClose; + property OnCloseQuery: TCloseQueryEvent read FOnCloseQuery write FOnCloseQuery; + property OnDockChanged: TNotifyEvent read FOnDockChanged write FOnDockChanged; + property OnDockChanging: TTBDockChangingEvent read FOnDockChanging write FOnDockChanging; + property OnDockChangingHidden: TTBDockChangingEvent read FOnDockChangingHidden write FOnDockChangingHidden; + property OnMove: TNotifyEvent read FOnMove write FOnMove; + property OnRecreated: TNotifyEvent read FOnRecreated write FOnRecreated; + property OnRecreating: TNotifyEvent read FOnRecreating write FOnRecreating; + {$IFNDEF JR_D4} + property OnResize: TNotifyEvent read FOnResize write FOnResize; + {$ENDIF} + property OnVisibleChanged: TNotifyEvent read FOnVisibleChanged write FOnVisibleChanged; + + { Overridden methods } + procedure CreateParams(var Params: TCreateParams); override; + procedure DefineProperties(Filer: TFiler); override; + function GetPalette: HPALETTE; override; + procedure Loaded; override; + procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override; + procedure Notification(AComponent: TComponent; Operation: TOperation); override; + function PaletteChanged(Foreground: Boolean): Boolean; override; + procedure SetParent(AParent: TWinControl); override; + + { Methods accessible to descendants } + procedure Arrange; + function CalcNCSizes: TPoint; virtual; + procedure ChangeSize(AWidth, AHeight: Integer); + function ChildControlTransparent(Ctl: TControl): Boolean; dynamic; + procedure Close; + procedure ControlExistsAtPos(const P: TPoint; var ControlExists: Boolean); virtual; + function DoArrange(CanMoveControls: Boolean; PreviousDockType: TTBDockType; + NewFloating: Boolean; NewDock: TTBDock): TPoint; virtual; abstract; + procedure DoDockChangingHidden(NewFloating: Boolean; DockingTo: TTBDock); dynamic; + procedure DoubleClick; + procedure DrawNCArea(const DrawToDC: Boolean; const ADC: HDC; + const Clip: HRGN); virtual; + procedure GetBaseSize(var ASize: TPoint); virtual; abstract; + function GetDockedCloseButtonRect(LeftRight: Boolean): TRect; virtual; + function GetFloatingWindowParentClass: TTBFloatingWindowParentClass; dynamic; + procedure GetMinShrinkSize(var AMinimumSize: Integer); virtual; + procedure GetMinMaxSize(var AMinClientWidth, AMinClientHeight, + AMaxClientWidth, AMaxClientHeight: Integer); virtual; + function GetShrinkMode: TTBShrinkMode; virtual; + procedure InitializeOrdering; dynamic; + function IsAutoResized: Boolean; + procedure ResizeBegin(SizeHandle: TTBSizeHandle); dynamic; + procedure ResizeEnd; dynamic; + procedure ResizeTrack(var Rect: TRect; const OrigRect: TRect); dynamic; + procedure ResizeTrackAccept; dynamic; + procedure SizeChanging(const AWidth, AHeight: Integer); virtual; + public + property Docked: Boolean read FDocked; + property Canvas; + property CurrentDock: TTBDock read FCurrentDock write SetCurrentDock stored False; + property CurrentSize: Integer read FCurrentSize write FCurrentSize; + property DockPos: Integer read FDockPos write SetDockPos default -1; + property DockRow: Integer read FDockRow write SetDockRow default 0; + property DragMode: Boolean read FDragMode; + property DragSplitting: Boolean read FDragSplitting; + property EffectiveDockPos: Integer read FEffectiveDockPos; + property EffectiveDockRow: Integer read FEffectiveDockRow; + property Floating: Boolean read FFloating write SetFloating default False; + property FloatingPosition: TPoint read FFloatingPosition write SetFloatingPosition; + property LastDock: TTBDock read FLastDock write SetLastDock stored IsLastDockStored; + property NonClientWidth: Integer read GetNonClientWidth; + property NonClientHeight: Integer read GetNonClientHeight; + + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + function GetParentComponent: TComponent; override; + function HasParent: Boolean; override; + procedure SetBounds(ALeft, ATop, AWidth, AHeight: Integer); override; + + procedure AddDockForm(const Form: TTBCustomForm); + procedure AddDockedNCAreaToSize(var S: TPoint; const LeftRight: Boolean); + procedure AddFloatingNCAreaToSize(var S: TPoint); + procedure BeginMoving(const InitX, InitY: Integer); + procedure BeginSizing(const ASizeHandle: TTBSizeHandle); + procedure BeginUpdate; + procedure DoneReadingPositionData(const Data: TTBReadPositionData); dynamic; + procedure EndUpdate; + procedure GetDockedNCArea(var TopLeft, BottomRight: TPoint; + const LeftRight: Boolean); + function GetFloatingBorderSize: TPoint; virtual; + procedure GetFloatingNCArea(var TopLeft, BottomRight: TPoint); + function IsMovable: Boolean; + procedure MoveOnScreen(const OnlyIfFullyOffscreen: Boolean); + procedure ReadPositionData(const Data: TTBReadPositionData); dynamic; + procedure RemoveDockForm(const Form: TTBCustomForm); + procedure WritePositionData(const Data: TTBWritePositionData); dynamic; + published + property Height stored IsWidthAndHeightStored; + property Width stored IsWidthAndHeightStored; + end; + + TTBBasicBackground = class(TComponent) + protected + procedure Draw(DC: HDC; const DrawRect: TRect); virtual; abstract; + function GetPalette: HPALETTE; virtual; abstract; + procedure RegisterChanges(Proc: TNotifyEvent); virtual; abstract; + procedure SysColorChanged; virtual; abstract; + procedure UnregisterChanges(Proc: TNotifyEvent); virtual; abstract; + function UsingBackground: Boolean; virtual; abstract; + end; + + TTBBackground = class(TTBBasicBackground) + private + FBitmap, FBitmapCache: TBitmap; + FBkColor: TColor; + FNotifyList: TList; + FTransparent: Boolean; + procedure BitmapChanged(Sender: TObject); + procedure SetBitmap(Value: TBitmap); + procedure SetBkColor(Value: TColor); + procedure SetTransparent(Value: Boolean); + protected + procedure Draw(DC: HDC; const DrawRect: TRect); override; + function GetPalette: HPALETTE; override; + procedure RegisterChanges(Proc: TNotifyEvent); override; + procedure SysColorChanged; override; + procedure UnregisterChanges(Proc: TNotifyEvent); override; + function UsingBackground: Boolean; override; + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + published + property Bitmap: TBitmap read FBitmap write SetBitmap; + property BkColor: TColor read FBkColor write SetBkColor default clBtnFace; + property Transparent: Boolean read FTransparent write SetTransparent default False; + end; + +procedure TBRegLoadPositions(const OwnerComponent: TComponent; + const RootKey: DWORD; const BaseRegistryKey: String); +procedure TBRegSavePositions(const OwnerComponent: TComponent; + const RootKey: DWORD; const BaseRegistryKey: String); +procedure TBIniLoadPositions(const OwnerComponent: TComponent; + const Filename, SectionNamePrefix: String); +procedure TBIniSavePositions(const OwnerComponent: TComponent; + const Filename, SectionNamePrefix: String); + +procedure TBCustomLoadPositions(const OwnerComponent: TComponent; + const ReadIntProc: TTBPositionReadIntProc; + const ReadStringProc: TTBPositionReadStringProc; const ExtraData: Pointer); +procedure TBCustomSavePositions(const OwnerComponent: TComponent; + const WriteIntProc: TTBPositionWriteIntProc; + const WriteStringProc: TTBPositionWriteStringProc; const ExtraData: Pointer); + +function TBGetDockTypeOf(const Control: TTBDock; const Floating: Boolean): TTBDockType; +function TBGetToolWindowParentForm(const ToolWindow: TTBCustomDockableWindow): + TTBCustomForm; +function TBValidToolWindowParentForm(const ToolWindow: TTBCustomDockableWindow): + TTBCustomForm; + +implementation + +uses + Registry, IniFiles, Consts, Menus, + TB2Common, TB2Hook, TB2Consts; + +type + TControlAccess = class(TControl); + +const + DockedBorderSize = 2; + DockedBorderSize2 = DockedBorderSize*2; + DragHandleSizes: array[Boolean, TTBDragHandleStyle] of Integer = + ((9, 0, 6), (14, 14, 14)); + DragHandleXOffsets: array[Boolean, TTBDragHandleStyle] of Integer = + ((2, 0, 1), (3, 0, 5)); + HT_TB2k_Border = 2000; + HT_TB2k_Close = 2001; + HT_TB2k_Caption = 2002; + + DefaultBarWidthHeight = 8; + + ForceDockAtTopRow = 0; + ForceDockAtLeftPos = -8; + + PositionLeftOrRight = [dpLeft, dpRight]; + + twrdAll = [Low(TTBToolWindowNCRedrawWhatElement)..High(TTBToolWindowNCRedrawWhatElement)]; + + { Constants for TTBCustomDockableWindow registry values/data. + Don't localize any of these names! } + rvRev = 'Rev'; + rdCurrentRev = 2000; + rvVisible = 'Visible'; + rvDockedTo = 'DockedTo'; + rdDockedToFloating = '+'; + rvLastDock = 'LastDock'; + rvDockRow = 'DockRow'; + rvDockPos = 'DockPos'; + rvFloatLeft = 'FloatLeft'; + rvFloatTop = 'FloatTop'; + +threadvar + FloatingToolWindows: TList; + + +{ Misc. functions } + +function GetSmallCaptionHeight: Integer; +{ Returns height of the caption of a small window } +begin + Result := GetSystemMetrics(SM_CYSMCAPTION); +end; + +function GetMDIParent(const Form: TTBCustomForm): TTBCustomForm; +{ Returns the parent of the specified MDI child form. But, if Form isn't a + MDI child, it simply returns Form. } +var + I, J: Integer; +begin + Result := Form; + if Form = nil then Exit; + if {$IFDEF JR_D3} (Form is TForm) and {$ENDIF} + (TForm(Form).FormStyle = fsMDIChild) then + for I := 0 to Screen.FormCount-1 do + with Screen.Forms[I] do begin + if FormStyle <> fsMDIForm then Continue; + for J := 0 to MDIChildCount-1 do + if MDIChildren[J] = Form then begin + Result := Screen.Forms[I]; + Exit; + end; + end; +end; + +function TBGetDockTypeOf(const Control: TTBDock; const Floating: Boolean): TTBDockType; +begin + if Floating then + Result := dtFloating + else + if Control = nil then + Result := dtNotDocked + else begin + if not(Control.Position in PositionLeftOrRight) then + Result := dtTopBottom + else + Result := dtLeftRight; + end; +end; + +function TBGetToolWindowParentForm(const ToolWindow: TTBCustomDockableWindow): TTBCustomForm; +var + Ctl: TWinControl; +begin + Result := nil; + Ctl := ToolWindow; + while Assigned(Ctl.Parent) do begin + if Ctl.Parent is TTBCustomForm then + Result := TTBCustomForm(Ctl.Parent); + Ctl := Ctl.Parent; + end; + { ^ for compatibility with ActiveX controls, that code is used instead of + GetParentForm because it returns nil unless the form is the *topmost* + parent } + if Result is TTBFloatingWindowParent then + Result := TTBFloatingWindowParent(Result).ParentForm; +end; + +function TBValidToolWindowParentForm(const ToolWindow: TTBCustomDockableWindow): TTBCustomForm; +begin + Result := TBGetToolWindowParentForm(ToolWindow); + if Result = nil then + raise EInvalidOperation.{$IFDEF JR_D3}CreateFmt{$ELSE}CreateResFmt{$ENDIF} + (SParentRequired, [ToolWindow.Name]); +end; + +procedure ToolbarHookProc(Code: THookProcCode; Wnd: HWND; WParam: WPARAM; LParam: LPARAM); +var + I: Integer; + ToolWindow: TTBCustomDockableWindow; + Form: TTBCustomForm; +begin + case Code of + hpSendActivate, + hpSendActivateApp: begin + if Assigned(FloatingToolWindows) then + for I := 0 to FloatingToolWindows.Count-1 do + with TTBCustomDockableWindow(FloatingToolWindows.List[I]) do + { Hide or restore toolbars when a form or the application is + deactivated or activated, and/or update their caption state + (active/inactive) } + UpdateVisibility; + end; + hpSendWindowPosChanged: begin + if Assigned(FloatingToolWindows) then + for I := 0 to FloatingToolWindows.Count-1 do begin + ToolWindow := TTBCustomDockableWindow(FloatingToolWindows.List[I]); + with ToolWindow do begin + if (FFloatingMode = fmOnTopOfParentForm) and HandleAllocated then begin + with PWindowPos(LParam)^ do + { Call UpdateVisibility if parent form's visibility has + changed, or if it has been minimized or restored } + if ((flags and (SWP_SHOWWINDOW or SWP_HIDEWINDOW) <> 0) or + (flags and SWP_FRAMECHANGED <> 0)) then begin + Form := TBGetToolWindowParentForm(ToolWindow); + if Assigned(Form) and Form.HandleAllocated and ((Wnd = Form.Handle) or IsChild(Wnd, Form.Handle)) then + UpdateVisibility; + end; + end; + end; + end; + end; + hpPreDestroy: begin + if Assigned(FloatingToolWindows) then + for I := 0 to FloatingToolWindows.Count-1 do begin + with TTBCustomDockableWindow(FloatingToolWindows.List[I]) do + { It must remove the form window's ownership of the tool window + *before* the form gets destroyed, otherwise Windows will destroy + the tool window's handle. } + if Assigned(Parent) and Parent.HandleAllocated and + (HWND(GetWindowLong(Parent.Handle, GWL_HWNDPARENT)) = Wnd) then + SetWindowLong(Parent.Handle, GWL_HWNDPARENT, Longint(Application.Handle)); + { ^ Restore GWL_HWNDPARENT back to Application.Handle } + end; + end; + end; +end; + +type + PFindWindowData = ^TFindWindowData; + TFindWindowData = record + TaskActiveWindow, TaskFirstWindow, TaskFirstTopMost: HWND; + end; + +function DoFindWindow(Wnd: HWND; Param: Longint): Bool; stdcall; +begin + with PFindWindowData(Param)^ do + if (Wnd <> TaskActiveWindow) and (Wnd <> Application.Handle) and + IsWindowVisible(Wnd) and IsWindowEnabled(Wnd) then begin + if GetWindowLong(Wnd, GWL_EXSTYLE) and WS_EX_TOPMOST = 0 then begin + if TaskFirstWindow = 0 then TaskFirstWindow := Wnd; + end + else begin + if TaskFirstTopMost = 0 then TaskFirstTopMost := Wnd; + end; + end; + Result := True; +end; + +function FindTopLevelWindow(ActiveWindow: HWND): HWND; +var + FindData: TFindWindowData; +begin + with FindData do begin + TaskActiveWindow := ActiveWindow; + TaskFirstWindow := 0; + TaskFirstTopMost := 0; + EnumThreadWindows(GetCurrentThreadID, @DoFindWindow, Longint(@FindData)); + if TaskFirstWindow <> 0 then + Result := TaskFirstWindow + else + Result := TaskFirstTopMost; + end; +end; + +function IsAncestorOfWindow(const ParentWnd: HWND; Wnd: HWND): Boolean; +{ Returns True if Wnd is a child of, is owned by, or is the same window as + ParentWnd } +begin + while Wnd <> 0 do begin + if Wnd = ParentWnd then begin + Result := True; + Exit; + end; + Wnd := GetParent(Wnd); + end; + Result := False; +end; + +procedure RecalcNCArea(const Ctl: TWinControl); +begin + if Ctl.HandleAllocated then + SetWindowPos(Ctl.Handle, 0, 0, 0, 0, 0, SWP_FRAMECHANGED or + SWP_NOACTIVATE or SWP_NOMOVE or SWP_NOSIZE or SWP_NOZORDER); +end; + +procedure InvalidateAll(const Ctl: TWinControl); +{ Invalidate both non-client and client area, and erase. } +begin + if Ctl.HandleAllocated then + RedrawWindow(Ctl.Handle, nil, 0, RDW_FRAME or RDW_INVALIDATE or + RDW_ERASE or RDW_NOCHILDREN); +end; + +type + TSetCloseButtonStateProc = procedure(Pushed: Boolean) of object; + +function CloseButtonLoop(const Wnd: HWND; const ButtonRect: TRect; + const SetCloseButtonStateProc: TSetCloseButtonStateProc): Boolean; + function MouseInButton: Boolean; + var + P: TPoint; + begin + GetCursorPos(P); + Result := PtInRect(ButtonRect, P); + end; +var + Msg: TMsg; +begin + Result := False; + + SetCloseButtonStateProc(MouseInButton); + + SetCapture(Wnd); + + try + while GetCapture = Wnd do begin + case Integer(GetMessage(Msg, 0, 0, 0)) of + -1: Break; { if GetMessage failed } + 0: begin + { Repost WM_QUIT messages } + PostQuitMessage(Msg.WParam); + Break; + end; + end; + + case Msg.Message of + WM_KEYDOWN, WM_KEYUP: + { Ignore all keystrokes while in a close button loop } + ; + WM_MOUSEMOVE: begin + { Note to self: WM_MOUSEMOVE messages should never be dispatched + here to ensure no hints get shown } + SetCloseButtonStateProc(MouseInButton); + end; + WM_LBUTTONDOWN, WM_LBUTTONDBLCLK: + { Make sure it doesn't begin another loop } + Break; + WM_LBUTTONUP: begin + if MouseInButton then + Result := True; + Break; + end; + WM_RBUTTONDOWN..WM_MBUTTONDBLCLK: + { Ignore all other mouse up/down messages } + ; + else + TranslateMessage(Msg); + DispatchMessage(Msg); + end; + end; + finally + if GetCapture = Wnd then + ReleaseCapture; + SetCloseButtonStateProc(False); + end; +end; + + +{ TTBDock - internal } + +constructor TTBDock.Create(AOwner: TComponent); +begin + inherited; + + ControlStyle := ControlStyle + [csAcceptsControls, csMenuEvents] - + [csClickEvents, csCaptureMouse, csOpaque]; + FAllowDrag := True; + FBkgOnToolbars := True; + DockList := TList.Create; + DockVisibleList := TList.Create; + Color := clBtnFace; + Position := dpTop; +end; + +procedure TTBDock.CreateParams(var Params: TCreateParams); +begin + inherited; + { Disable complete redraws when size changes. CS_H/VREDRAW cause flicker + and are not necessary for this control at run time } + if not(csDesigning in ComponentState) then + with Params.WindowClass do + Style := Style and not(CS_HREDRAW or CS_VREDRAW); +end; + +destructor TTBDock.Destroy; +begin + if Assigned(FBackground) then + FBackground.UnregisterChanges(BackgroundChanged); + inherited; + DockVisibleList.Free; + DockList.Free; +end; + +procedure TTBDock.SetParent(AParent: TWinControl); +begin + if (AParent is TTBCustomDockableWindow) or (AParent is TTBDock) then + raise EInvalidOperation.Create(STBDockParentNotAllowed); + + inherited; +end; + +procedure TTBDock.BeginUpdate; +begin + Inc(FDisableArrangeToolbars); +end; + +procedure TTBDock.EndUpdate; +begin + Dec(FDisableArrangeToolbars); + if FArrangeToolbarsNeeded and (FDisableArrangeToolbars = 0) then + ArrangeToolbars; +end; + +function TTBDock.HasVisibleToolbars: Boolean; +var + I: Integer; +begin + Result := False; + for I := 0 to DockList.Count-1 do + if ToolbarVisibleOnDock(TTBCustomDockableWindow(DockList[I])) then begin + Result := True; + Break; + end; +end; + +function TTBDock.ToolbarVisibleOnDock(const AToolbar: TTBCustomDockableWindow): Boolean; +begin + Result := (AToolbar.Parent = Self) and + (AToolbar.Visible or (csDesigning in AToolbar.ComponentState)); +end; + +function TTBDock.GetCurrentRowSize(const Row: Integer; + var AFullSize: Boolean): Integer; +var + I, J: Integer; + T: TTBCustomDockableWindow; +begin + Result := 0; + AFullSize := False; + if Row < 0 then Exit; + for I := 0 to DockList.Count-1 do begin + T := DockList[I]; + if (T.FEffectiveDockRow = Row) and ToolbarVisibleOnDock(T) then begin + AFullSize := T.FullSize; + if not(Position in PositionLeftOrRight) then + J := T.Height + else + J := T.Width; + if J > Result then + Result := J; + end; + end; +end; + +function TTBDock.GetMinRowSize(const Row: Integer; + const ExcludeControl: TTBCustomDockableWindow): Integer; +var + I, J: Integer; + T: TTBCustomDockableWindow; +begin + Result := 0; + if Row < 0 then Exit; + for I := 0 to DockList.Count-1 do begin + T := DockList[I]; + if (T <> ExcludeControl) and (T.FEffectiveDockRow = Row) and + ToolbarVisibleOnDock(T) then begin + J := T.FLastRowSize; + if J > Result then + Result := J; + end; + end; +end; + +function TTBDock.GetDesignModeRowOf(const XY: Integer): Integer; +{ Similar to GetRowOf, but is a little different to accomidate design mode + better } +var + HighestRowPlus1, R, CurY, CurRowSize: Integer; + FullSize: Boolean; +begin + Result := 0; + HighestRowPlus1 := GetHighestRow(True)+1; + CurY := 0; + for R := 0 to HighestRowPlus1 do begin + Result := R; + if R = HighestRowPlus1 then Break; + CurRowSize := GetCurrentRowSize(R, FullSize); + if CurRowSize = 0 then Continue; + Inc(CurY, CurRowSize); + if XY < CurY then + Break; + end; +end; + +function TTBDock.GetHighestRow(const HighestEffective: Boolean): Integer; +{ Returns highest used row number, or -1 if no rows are used } +var + I, J: Integer; +begin + Result := -1; + for I := 0 to DockList.Count-1 do + with TTBCustomDockableWindow(DockList[I]) do begin + if HighestEffective then + J := FEffectiveDockRow + else + J := FDockRow; + if J > Result then + Result := J; + end; +end; + +procedure TTBDock.ChangeWidthHeight(const NewWidth, NewHeight: Integer); +{ Same as setting Width/Height directly, but does not lose Align position. } +begin + case Align of + alNone, alTop, alLeft: + SetBounds(Left, Top, NewWidth, NewHeight); + alBottom: + SetBounds(Left, Top-NewHeight+Height, NewWidth, NewHeight); + alRight: + SetBounds(Left-NewWidth+Width, Top, NewWidth, NewHeight); + end; +end; + +procedure TTBDock.AlignControls(AControl: TControl; var Rect: TRect); +begin + ArrangeToolbars; +end; + +function CompareDockRowPos(const Item1, Item2, ExtraData: Pointer): Integer; far; +begin + if TTBCustomDockableWindow(Item1).FDockRow <> TTBCustomDockableWindow(Item2).FDockRow then + Result := TTBCustomDockableWindow(Item1).FDockRow - TTBCustomDockableWindow(Item2).FDockRow + else + Result := TTBCustomDockableWindow(Item1).FDockPos - TTBCustomDockableWindow(Item2).FDockPos; +end; + +procedure TTBDock.ArrangeToolbars; +{ The main procedure to arrange all the toolbars docked to it } +type + PPosDataRec = ^TPosDataRec; + TPosDataRec = record + Row, ActualRow, PrecSpace, FullSize, MinimumSize, Size, Overlap, Pos: Integer; + ShrinkMode: TTBShrinkMode; + NeedArrange: Boolean; + end; + PPosDataArray = ^TPosDataArray; + TPosDataArray = array[0..$7FFFFFFF div SizeOf(TPosDataRec)-1] of TPosDataRec; +var + NewDockList: TList; + PosData: PPosDataArray; + + function IndexOfDraggingToolbar(const List: TList): Integer; + { Returns index of toolbar in List that's currently being dragged, or -1 } + var + I: Integer; + begin + for I := 0 to List.Count-1 do + if TTBCustomDockableWindow(List[I]).FDragMode then begin + Result := I; + Exit; + end; + Result := -1; + end; + + function ShiftLeft(const Row, StartIndex, MaxSize: Integer): Integer; + { Removes PrecSpace pixels from toolbars at or before StartIndex until the + right edge of the toolbar at StartIndex is <= MaxSize. + Returns the total number of PrecSpace pixels removed from toolbars. } + var + PixelsOffEdge, I, J: Integer; + P: PPosDataRec; + begin + Result := 0; + PixelsOffEdge := -MaxSize; + for I := 0 to StartIndex do begin + P := @PosData[I]; + if P.Row = Row then begin + Inc(PixelsOffEdge, P.PrecSpace); + Inc(PixelsOffEdge, P.Size); + end; + end; + if PixelsOffEdge > 0 then + for I := StartIndex downto 0 do begin + P := @PosData[I]; + if P.Row = Row then begin + J := PixelsOffEdge; + if P.PrecSpace < J then + J := P.PrecSpace; + Dec(P.PrecSpace, J); + Dec(PixelsOffEdge, J); + Inc(Result, J); + if PixelsOffEdge = 0 then + Break; + end; + end; + end; + + function GetNextToolbar(const GoForward: Boolean; const Row: Integer; + const StartIndex: Integer): Integer; + var + I: Integer; + begin + Result := -1; + I := StartIndex; + while True do begin + if GoForward then begin + Inc(I); + if I >= NewDockList.Count then + Break; + end + else begin + Dec(I); + if I < 0 then + Break; + end; + if PosData[I].Row = Row then begin + Result := I; + Break; + end; + end; + end; + +var + LeftRight: Boolean; + EmptySize, HighestRow, R, CurPos, CurRowPixel, I, J, K, L, ClientW, + ClientH, MaxSize, TotalSize, PixelsPastMaxSize, Offset, CurRealPos, DragIndex, + MinRealPos, DragIndexPos, ToolbarsOnRow, CurRowSize: Integer; + P: PPosDataRec; + T: TTBCustomDockableWindow; + S: TPoint; + RowIsEmpty: Boolean; +label FoundNextToolbar; +begin + if (FDisableArrangeToolbars > 0) or (csLoading in ComponentState) then begin + FArrangeToolbarsNeeded := True; + Exit; + end; + + NewDockList := nil; + PosData := nil; + Inc(FDisableArrangeToolbars); + try + { Work around VCL alignment bug when docking toolbars taller or wider than + the client height or width of the form. } + {if not(csDesigning in ComponentState) and HandleAllocated then + SetWindowPos(Handle, HWND_TOP, 0, 0, 0, 0, + SWP_NOACTIVATE or SWP_NOMOVE or SWP_NOSIZE);} + + LeftRight := Position in PositionLeftOrRight; + + if not HasVisibleToolbars then begin + EmptySize := Ord(FFixAlign); + if csDesigning in ComponentState then + EmptySize := 9; + if not LeftRight then + ChangeWidthHeight(Width, EmptySize) + else + ChangeWidthHeight(EmptySize, Height); + Exit; + end; + + { It can't read the ClientWidth and ClientHeight properties because they + attempt to create a handle, which requires Parent to be set. "ClientW" + and "ClientH" are calculated instead. } + ClientW := Width - FNonClientWidth; + if ClientW < 0 then ClientW := 0; + ClientH := Height - FNonClientHeight; + if ClientH < 0 then ClientH := 0; + + { Remove toolbars from DockList & DockVisibleList that are destroying, so + that no methods on these toolbars will be called. + This is needed because in certain rare cases ArrangeToolbars can be + indirectly called while a docked toolbar is being destroyed. } + for I := DockList.Count-1 downto 0 do begin + T := DockList[I]; + if csDestroying in T.ComponentState then begin + DockList.Delete(I); + DockVisibleList.Remove(T); + end; + end; + + { If LimitToOneRow is True, only use the first row } + if FLimitToOneRow then + for I := 0 to DockList.Count-1 do + with TTBCustomDockableWindow(DockList[I]) do + FDockRow := 0; + + { Copy DockList to NewDockList, and ensure it is in correct ordering + according to DockRow/DockPos } + NewDockList := TList.Create; + NewDockList.Count := DockList.Count; + for I := 0 to NewDockList.Count-1 do + NewDockList[I] := DockList[I]; + I := IndexOfDraggingToolbar(NewDockList); + ListSortEx(NewDockList, CompareDockRowPos, nil); + DragIndex := IndexOfDraggingToolbar(NewDockList); + if (I <> -1) and TTBCustomDockableWindow(NewDockList[DragIndex]).FDragSplitting then begin + { When splitting, don't allow the toolbar being dragged to change + positions in the dock list } + NewDockList.Move(DragIndex, I); + DragIndex := I; + end; + ListSortEx(DockVisibleList, CompareDockRowPos, nil); + { Find highest row number } + HighestRow := GetHighestRow(False); + + { Create a temporary array that holds new position data for the toolbars } + PosData := AllocMem(NewDockList.Count * SizeOf(TPosDataRec)); + for I := 0 to NewDockList.Count-1 do begin + P := @PosData[I]; + T := NewDockList[I]; + P.ActualRow := T.FDockRow; + if ToolbarVisibleOnDock(T) then + P.Row := T.FDockRow + else + P.Row := -1; + P.Pos := T.FDockPos; + end; + + { Find FInsertRowBefore=True and FullSize=True toolbars and make sure there + aren't any other toolbars on the same row. If there are, shift them down + a row. } + for L := 0 to 1 do begin + R := 0; + while R <= HighestRow do begin + for I := 0 to NewDockList.Count-1 do begin + T := NewDockList[I]; + if (PosData[I].ActualRow = R) and + (((L = 0) and T.FInsertRowBefore and not LimitToOneRow) or + ((L = 1) and T.FullSize)) then + for J := 0 to NewDockList.Count-1 do + if (J <> I) and (PosData[J].ActualRow = R) then begin + for K := 0 to NewDockList.Count-1 do begin + if K <> I then begin + P := @PosData[K]; + if P.ActualRow >= R then + Inc(P.ActualRow); + if P.Row >= R then + Inc(P.Row); + end; + end; + Inc(HighestRow); + Break; + end; + end; + Inc(R); + end; + end; + + { Remove blank rows. + Note that rows that contain only invisible or currently floating toolbars + are intentionally not removed, so that when the toolbars are shown again, + they stay on their own row. } + R := 0; + while R <= HighestRow do begin + RowIsEmpty := True; + for I := 0 to NewDockList.Count-1 do + if PosData[I].ActualRow = R then begin + RowIsEmpty := False; + Break; + end; + if RowIsEmpty then begin + { Shift all ones higher than R back one } + for I := 0 to NewDockList.Count-1 do begin + if PosData[I].ActualRow > R then + Dec(PosData[I].ActualRow); + if PosData[I].Row > R then + Dec(PosData[I].Row); + end; + Dec(HighestRow); + end + else + Inc(R); + end; + + { Calculate positions and sizes of each row } + R := 0; + while R <= HighestRow do begin + if not LeftRight then + MaxSize := ClientW + else + MaxSize := ClientH; + + { Set initial sizes } + TotalSize := 0; + ToolbarsOnRow := 0; + MinRealPos := 0; + for I := 0 to NewDockList.Count-1 do begin + P := @PosData[I]; + if P.Row = R then begin + T := NewDockList[I]; + T.GetBaseSize(S); + if not LeftRight then + J := S.X + T.NonClientWidth + else + J := S.Y + T.NonClientHeight; + P.FullSize := J; + P.Size := J; + P.ShrinkMode := T.GetShrinkMode; + P.MinimumSize := 0; + T.GetMinShrinkSize(P.MinimumSize); + if P.MinimumSize > P.FullSize then + { don't allow minimum shrink size to be less than full size } + P.MinimumSize := P.FullSize; + if P.ShrinkMode = tbsmChevron then + Inc(MinRealPos, P.MinimumSize) + else + Inc(MinRealPos, P.FullSize); + { If the toolbar isn't the first toolbar on the row, and the toolbar + would go off the edge even after it's shrunk, then move it onto a + row of its own } + if (ToolbarsOnRow > 0) and (MinRealPos > MaxSize) and + not LimitToOneRow then begin + for K := I to NewDockList.Count-1 do begin + P := @PosData[K]; + if P.ActualRow >= R then + Inc(P.ActualRow); + if P.Row >= R then + Inc(P.Row); + end; + Inc(HighestRow); + Break; + end; + Inc(TotalSize, J); + Inc(ToolbarsOnRow); + end; + end; + PixelsPastMaxSize := TotalSize - MaxSize; + + { Set initial arrangement; don't shrink toolbars yet } + DragIndexPos := 0; + CurPos := 0; + CurRealPos := 0; + MinRealPos := 0; + for I := 0 to NewDockList.Count-1 do begin + P := @PosData[I]; + T := NewDockList[I]; + if P.Row = R then begin + if (CurPos = 0) and (T.FullSize or T.Stretch) then + { Force to left } + J := 0 + else + J := T.FDockPos; + if I = DragIndex then + DragIndexPos := J; + { Don't let this toolbar overlap preceding toolbars by more than + the sum of their minimum sizes } + if J < MinRealPos then + J := MinRealPos; + if J > CurPos then begin + { There's a gap between the left edge or previous toolbar and + this toolbar } + if PixelsPastMaxSize <= 0 then begin + P.PrecSpace := J - CurPos; + CurPos := J; + end + else + { Don't allow a gap if exceeding MaxSize } + J := CurPos; + end + else begin + if J < CurRealPos then + P.Overlap := CurRealPos - J; + end; + + Inc(CurPos, P.Size); + CurRealPos := J + P.Size; + Inc(MinRealPos, P.MinimumSize); + end; + end; + + { If we aren't exceeding MaxSize, allow the toolbar being dragged + to push other toolbars to the left } + if (PixelsPastMaxSize < 0) and (DragIndex <> -1) and + (PosData[DragIndex].Row = R) then begin + I := GetNextToolbar(False, R, DragIndex); + if I <> -1 then begin + J := ShiftLeft(R, I, DragIndexPos); + if J > 0 then begin + { Ensure that toolbars that follow the toolbar being dragged stay + at the same place by increasing PrecSpace on the next toolbar } + I := GetNextToolbar(True, R, DragIndex); + if I <> -1 then + Inc(PosData[I].PrecSpace, J); + end; + end; + end; + + { If any toolbars are going off the edge of the dock, try to make them + at least partially visible by shifting preceding toolbars left } + I := GetNextToolbar(False, R, NewDockList.Count); + if I <> -1 then + ShiftLeft(R, I, MaxSize); + + { Shrink toolbars that overlap other toolbars (Overlaps[x] > 0) } + if PixelsPastMaxSize > 0 then begin + Offset := 0; + for I := 0 to NewDockList.Count-1 do begin + if PosData[I].Row <> R then + Continue; + T := NewDockList[I]; + if (ToolbarsOnRow > 1) and T.FDragMode then + T.FDragCanSplit := True; + Inc(Offset, PosData[I].Overlap); + if Offset > PixelsPastMaxSize then + Offset := PixelsPastMaxSize; + if Offset > 0 then + for J := I-1 downto 0 do begin + P := @PosData[J]; + if P.Row <> R then + Continue; + { How much can we shrink this toolbar J to get toolbar I to + its preferred position? } + if P.ShrinkMode = tbsmChevron then + L := Offset + else + L := 0; + K := -(P.Size - L - P.MinimumSize); { the number of pixels that exceed the minimum size } + if K > 0 then + { Don't shrink a toolbar below its minimum allowed size } + Dec(L, K); + Dec(P.Size, L); + Dec(PixelsPastMaxSize, L); + Dec(Offset, L); + if (Offset = 0) or + { This is needed so toolbars can push other toolbars to the + right when splitting: } + (J = DragIndex) then + Break; + end; + end; + end; + + { Still exceeding MaxSize? Make sure the rightmost toolbar(s) are + at least partially visible with a width of MinimumSize } + if PixelsPastMaxSize > 0 then begin + for I := NewDockList.Count-1 downto 0 do begin + P := @PosData[I]; + if (P.Row <> R) or (P.ShrinkMode = tbsmNone) or + ((P.ShrinkMode = tbsmWrap) and (ToolbarsOnRow > 1)) then + Continue; + J := P.Size - P.MinimumSize; + if J > 0 then begin { can we shrink this toolbar any? } + if J > PixelsPastMaxSize then + J := PixelsPastMaxSize; + Dec(P.Size, J); + Dec(PixelsPastMaxSize, J); + end; + if PixelsPastMaxSize = 0 then + Break; + end; + end; + + { Set Poses, and adjust size of FullSize & Stretch toolbars } + CurPos := 0; + for I := 0 to NewDockList.Count-1 do begin + P := @PosData[I]; + T := NewDockList[I]; + if P.Row = R then begin + if T.FullSize or T.Stretch then begin + { Remove any preceding space from this toolbar } + Inc(P.Size, P.PrecSpace); + P.PrecSpace := 0; + end; + Inc(CurPos, P.PrecSpace); + if T.FullSize then begin + { Claim all space } + if P.Size < MaxSize then + P.Size := MaxSize; + end + else if T.Stretch then begin + { Steal any preceding space from the next toolbar } + for J := I+1 to NewDockList.Count-1 do + if PosData[J].Row = R then begin + Inc(P.Size, PosData[J].PrecSpace); + PosData[J].PrecSpace := 0; + goto FoundNextToolbar; + end; + { or claim any remaining space } + if P.Size < MaxSize - CurPos then + P.Size := MaxSize - CurPos; + FoundNextToolbar: + end; + P.Pos := CurPos; + Inc(CurPos, P.Size); + end; + end; + + Inc(R); + end; + + for I := 0 to NewDockList.Count-1 do begin + T := NewDockList[I]; + T.FEffectiveDockRow := PosData[I].ActualRow; + T.FEffectiveDockPos := PosData[I].Pos; + { If FCommitNewPositions is True, update all the toolbars' DockPos and + DockRow properties to match the actual positions. + Also update the ordering of DockList to match NewDockList } + if FCommitNewPositions then begin + T.FDockRow := T.FEffectiveDockRow; + T.FDockPos := T.FEffectiveDockPos; + DockList[I] := NewDockList[I]; + end; + end; + + { Now actually move the toolbars } + CurRowPixel := 0; + for R := 0 to HighestRow do begin + CurRowSize := 0; + for I := 0 to NewDockList.Count-1 do begin + P := @PosData[I]; + T := NewDockList[I]; + if P.Row = R then begin + K := T.FCurrentSize; + T.FCurrentSize := P.Size; + if P.Size >= P.FullSize then begin + T.FCurrentSize := 0; + { Reason: so that if new items are added to a non-shrunk toolbar + at run-time (causing its width to increase), the toolbar won't + shrink unnecessarily } + end; + if (P.ShrinkMode <> tbsmNone) and (T.FCurrentSize <> K) then begin + { If Size is changing and we are to display a chevron or wrap, + call DoArrange to get an accurate row size } + S := T.DoArrange(False, TBGetDockTypeOf(Self, False), False, Self); + { Force a rearrange in case the actual size isn't changing but the + chevron visibility might have changed (which can happen if + items are added to a FullSize=True toolbar at run-time) } + P.NeedArrange := True; + end + else begin + if (P.ShrinkMode = tbsmWrap) and (P.Size < P.FullSize) then begin + { Preserve existing height (or width) on a wrapped toolbar + whose size isn't changing now } + S.X := T.Width - T.NonClientWidth; + S.Y := T.Height - T.NonClientHeight; + end + else + T.GetBaseSize(S); + end; + if not LeftRight then + K := S.Y + else + K := S.X; + T.FLastRowSize := K; + if K > CurRowSize then + CurRowSize := K; + end; + end; + if CurRowSize <> 0 then + Inc(CurRowSize, DockedBorderSize2); + for I := 0 to NewDockList.Count-1 do begin + P := @PosData[I]; + T := NewDockList[I]; + if P.Row = R then begin + Inc(T.FUpdatingBounds); + try + K := T.FCurrentSize; + if P.NeedArrange then + T.FArrangeNeeded := True; + if not LeftRight then + T.SetBounds(P.Pos, CurRowPixel, P.Size, CurRowSize) + else + T.SetBounds(CurRowPixel, P.Pos, CurRowSize, P.Size); + if T.FArrangeNeeded then + { ^ don't arrange again if SetBounds call already caused one } + T.Arrange; + { Restore FCurrentSize since TTBToolbarView.DoUpdatePositions + clears it } + T.FCurrentSize := K; + finally + Dec(T.FUpdatingBounds); + end; + end; + end; + Inc(CurRowPixel, CurRowSize); + end; + + { Set the size of the dock } + if not LeftRight then + ChangeWidthHeight(Width, CurRowPixel + FNonClientHeight) + else + ChangeWidthHeight(CurRowPixel + FNonClientWidth, Height); + finally + Dec(FDisableArrangeToolbars); + FArrangeToolbarsNeeded := False; + FCommitNewPositions := False; + FreeMem(PosData); + NewDockList.Free; + end; +end; + +procedure TTBDock.CommitPositions; +{ Copies docked toolbars' EffectiveDockRow and EffectiveDockPos properties + into DockRow and DockPos respectively. + Note that this does not reorder DockList like ArrangeToolbars does when + FCommitNewPositions=True. } +var + I: Integer; + T: TTBCustomDockableWindow; +begin + for I := 0 to DockVisibleList.Count-1 do begin + T := DockVisibleList[I]; + T.FDockRow := T.FEffectiveDockRow; + T.FDockPos := T.FEffectiveDockPos; + end; +end; + +procedure TTBDock.ChangeDockList(const Insert: Boolean; + const Bar: TTBCustomDockableWindow); +{ Inserts or removes Bar from DockList } +var + I: Integer; +begin + I := DockList.IndexOf(Bar); + if Insert then begin + if I = -1 then begin + Bar.FreeNotification(Self); + DockList.Add(Bar); + end; + end + else begin + if I <> -1 then + DockList.Delete(I); + end; + ToolbarVisibilityChanged(Bar, False); +end; + +procedure TTBDock.ToolbarVisibilityChanged(const Bar: TTBCustomDockableWindow; + const ForceRemove: Boolean); +var + Modified, VisibleOnDock: Boolean; + I: Integer; +begin + Modified := False; + I := DockVisibleList.IndexOf(Bar); + VisibleOnDock := not ForceRemove and ToolbarVisibleOnDock(Bar); + if VisibleOnDock then begin + if I = -1 then begin + DockVisibleList.Add(Bar); + Modified := True; + end; + end + else begin + if I <> -1 then begin + DockVisibleList.Remove(Bar); + Modified := True; + end; + end; + + if Modified then begin + ArrangeToolbars; + + if Assigned(FOnInsertRemoveBar) then + FOnInsertRemoveBar(Self, VisibleOnDock, Bar); + end; +end; + +procedure TTBDock.Loaded; +begin + inherited; + { Rearranging is disabled while the component is loading, so now that it's + loaded, rearrange it. } + ArrangeToolbars; +end; + +procedure TTBDock.Notification(AComponent: TComponent; Operation: TOperation); +begin + inherited; + if Operation = opRemove then begin + if AComponent = FBackground then + Background := nil + else if AComponent is TTBCustomDockableWindow then begin + DockList.Remove(AComponent); + DockVisibleList.Remove(AComponent); + end; + end; +end; + +function TTBDock.GetPalette: HPALETTE; +begin + if UsingBackground and Assigned(FBackground) then + { ^ by default UsingBackground returns False if FBackground isn't assigned, + but UsingBackground may be overridden and return True when it isn't } + Result := FBackground.GetPalette + else + Result := 0; +end; + +procedure TTBDock.WMEraseBkgnd(var Message: TWMEraseBkgnd); +var + R, R2: TRect; + P1, P2: TPoint; + SaveIndex: Integer; +begin + { Draw the Background if there is one, otherwise use default erasing + behavior } + if UsingBackground then begin + R := ClientRect; + R2 := R; + { Make up for nonclient area } + P1 := ClientToScreen(Point(0, 0)); + P2 := Parent.ClientToScreen(BoundsRect.TopLeft); + Dec(R2.Left, Left + (P1.X-P2.X)); + Dec(R2.Top, Top + (P1.Y-P2.Y)); + SaveIndex := SaveDC(Message.DC); + IntersectClipRect(Message.DC, R.Left, R.Top, R.Right, R.Bottom); + DrawBackground(Message.DC, R2); + RestoreDC(Message.DC, SaveIndex); + Message.Result := 1; + end + else + inherited; +end; + +procedure TTBDock.Paint; +var + R: TRect; +begin + inherited; + { Draw dotted border in design mode } + if csDesigning in ComponentState then begin + R := ClientRect; + with Canvas do begin + Pen.Style := psDot; + Pen.Color := clBtnShadow; + Brush.Style := bsClear; + Rectangle(R.Left, R.Top, R.Right, R.Bottom); + Pen.Style := psSolid; + end; + end; +end; + +procedure TTBDock.WMMove(var Message: TWMMove); +begin + inherited; + if UsingBackground then + InvalidateBackgrounds; +end; + +{$IFNDEF JR_D4} +procedure TTBDock.WMSize(var Message: TWMSize); +begin + inherited; + if not(csLoading in ComponentState) and Assigned(FOnResize) then + FOnResize(Self); +end; +{$ENDIF} + +procedure TTBDock.WMNCCalcSize(var Message: TWMNCCalcSize); +begin + inherited; + { note to self: non-client size is stored in FNonClientWidth & + FNonClientHeight } + with Message.CalcSize_Params^.rgrc[0] do begin + if blTop in BoundLines then Inc(Top); + if blBottom in BoundLines then Dec(Bottom); + if blLeft in BoundLines then Inc(Left); + if blRight in BoundLines then Dec(Right); + end; +end; + +procedure TTBDock.DrawNCArea(const DrawToDC: Boolean; const ADC: HDC; + const Clip: HRGN); + + procedure DrawLine(const DC: HDC; const X1, Y1, X2, Y2: Integer); + begin + MoveToEx(DC, X1, Y1, nil); LineTo(DC, X2, Y2); + end; +var + RW, R, R2, RC: TRect; + DC: HDC; + HighlightPen, ShadowPen, SavePen: HPEN; + FillBrush: HBRUSH; +label 1; +begin + { This works around WM_NCPAINT problem described at top of source code } + {no! R := Rect(0, 0, Width, Height);} + GetWindowRect(Handle, RW); + R := RW; + OffsetRect(R, -R.Left, -R.Top); + + if not DrawToDC then + DC := GetWindowDC(Handle) + else + DC := ADC; + try + { Use update region } + if not DrawToDC then + SelectNCUpdateRgn(Handle, DC, Clip); + + { Draw BoundLines } + R2 := R; + if (BoundLines <> []) and + ((csDesigning in ComponentState) or HasVisibleToolbars) then begin + HighlightPen := CreatePen(PS_SOLID, 1, GetSysColor(COLOR_BTNHIGHLIGHT)); + ShadowPen := CreatePen(PS_SOLID, 1, GetSysColor(COLOR_BTNSHADOW)); + SavePen := SelectObject(DC, ShadowPen); + if blTop in BoundLines then begin + DrawLine(DC, R.Left, R.Top, R.Right, R.Top); + Inc(R2.Top); + end; + if blLeft in BoundLines then begin + DrawLine(DC, R.Left, R.Top, R.Left, R.Bottom); + Inc(R2.Left); + end; + SelectObject(DC, HighlightPen); + if blBottom in BoundLines then begin + DrawLine(DC, R.Left, R.Bottom-1, R.Right, R.Bottom-1); + Dec(R2.Bottom); + end; + if blRight in BoundLines then begin + DrawLine(DC, R.Right-1, R.Top, R.Right-1, R.Bottom); + Dec(R2.Right); + end; + SelectObject(DC, SavePen); + DeleteObject(ShadowPen); + DeleteObject(HighlightPen); + end; + Windows.GetClientRect(Handle, RC); + if not IsRectEmpty(RC) then begin + { ^ ExcludeClipRect can't be passed rectangles that have (Bottom < Top) or + (Right < Left) since it doesn't treat them as empty } + MapWindowPoints(Handle, 0, RC, 2); + OffsetRect(RC, -RW.Left, -RW.Top); + if EqualRect(RC, R2) then + { Skip FillRect because there would be nothing left after ExcludeClipRect } + goto 1; + ExcludeClipRect(DC, RC.Left, RC.Top, RC.Right, RC.Bottom); + end; + FillBrush := CreateSolidBrush(ColorToRGB(Color)); + FillRect(DC, R2, FillBrush); + DeleteObject(FillBrush); + 1: + finally + if not DrawToDC then + ReleaseDC(Handle, DC); + end; +end; + +procedure TTBDock.WMNCPaint(var Message: TMessage); +begin + DrawNCArea(False, 0, HRGN(Message.WParam)); +end; + +procedure DockNCPaintProc(Wnd: HWND; DC: HDC; AppData: Longint); +begin + TTBDock(AppData).DrawNCArea(True, DC, 0); +end; + +procedure TTBDock.WMPrint(var Message: TMessage); +begin + HandleWMPrint(Handle, Message, DockNCPaintProc, Longint(Self)); +end; + +procedure TTBDock.WMPrintClient(var Message: TMessage); +begin + HandleWMPrintClient(Self, Message); +end; + +procedure TTBDock.CMSysColorChange(var Message: TMessage); +begin + inherited; + if Assigned(FBackground) then + FBackground.SysColorChanged; +end; + +procedure TTBDock.RelayMsgToFloatingBars(var Message: TMessage); +var + I: Integer; + T: TTBCustomDockableWindow; +begin + for I := 0 to DockList.Count-1 do begin + T := DockList[I]; + if (csMenuEvents in T.ControlStyle) and T.Floating and T.Showing and + T.Enabled then begin + Message.Result := T.Perform(Message.Msg, Message.WParam, Message.LParam); + if Message.Result <> 0 then + Exit; + end; + end; +end; + +procedure TTBDock.WMSysCommand(var Message: TWMSysCommand); +begin + { Relay WM_SYSCOMMAND messages to floating toolbars which were formerly + docked. That way, items on floating menu bars can be accessed with Alt. } + RelayMsgToFloatingBars(TMessage(Message)); +end; + +procedure TTBDock.CMDialogKey(var Message: TCMDialogKey); +begin + RelayMsgToFloatingBars(TMessage(Message)); + if Message.Result = 0 then + inherited; +end; + +procedure TTBDock.CMDialogChar(var Message: TCMDialogChar); +begin + RelayMsgToFloatingBars(TMessage(Message)); + if Message.Result = 0 then + inherited; +end; + +{ TTBDock - property access methods } + +procedure TTBDock.SetAllowDrag(Value: Boolean); +var + I: Integer; +begin + if FAllowDrag <> Value then begin + FAllowDrag := Value; + for I := 0 to ControlCount-1 do + if Controls[I] is TTBCustomDockableWindow then + RecalcNCArea(TTBCustomDockableWindow(Controls[I])); + end; +end; + +function TTBDock.UsingBackground: Boolean; +begin + Result := Assigned(FBackground) and FBackground.UsingBackground; +end; + +procedure TTBDock.DrawBackground(DC: HDC; const DrawRect: TRect); +begin + FBackground.Draw(DC, DrawRect); +end; + +procedure TTBDock.InvalidateBackgrounds; +{ Called after background is changed } +var + I: Integer; + T: TTBCustomDockableWindow; +begin + Invalidate; + { Synchronize child toolbars also } + for I := 0 to DockList.Count-1 do begin + T := TTBCustomDockableWindow(DockList[I]); + if ToolbarVisibleOnDock(T) then + { Invalidate both non-client and client area } + InvalidateAll(T); + end; +end; + +procedure TTBDock.SetBackground(Value: TTBBasicBackground); +begin + if FBackground <> Value then begin + if Assigned(FBackground) then + FBackground.UnregisterChanges(BackgroundChanged); + FBackground := Value; + if Assigned(Value) then begin + Value.FreeNotification(Self); + Value.RegisterChanges(BackgroundChanged); + end; + InvalidateBackgrounds; + end; +end; + +procedure TTBDock.BackgroundChanged(Sender: TObject); +begin + InvalidateBackgrounds; +end; + +procedure TTBDock.SetBackgroundOnToolbars(Value: Boolean); +begin + if FBkgOnToolbars <> Value then begin + FBkgOnToolbars := Value; + InvalidateBackgrounds; + end; +end; + +procedure TTBDock.SetBoundLines(Value: TTBDockBoundLines); +var + X, Y: Integer; + B: TTBDockBoundLines; +begin + if FBoundLines <> Value then begin + FBoundLines := Value; + X := 0; + Y := 0; + B := BoundLines; { optimization } + if blTop in B then Inc(Y); + if blBottom in B then Inc(Y); + if blLeft in B then Inc(X); + if blRight in B then Inc(X); + FNonClientWidth := X; + FNonClientHeight := Y; + RecalcNCArea(Self); + end; +end; + +procedure TTBDock.SetFixAlign(Value: Boolean); +begin + if FFixAlign <> Value then begin + FFixAlign := Value; + ArrangeToolbars; + end; +end; + +procedure TTBDock.SetPosition(Value: TTBDockPosition); +begin + if (FPosition <> Value) and (ControlCount <> 0) then + raise EInvalidOperation.Create(STBDockCannotChangePosition); + FPosition := Value; + case Position of + dpTop: Align := alTop; + dpBottom: Align := alBottom; + dpLeft: Align := alLeft; + dpRight: Align := alRight; + end; +end; + +function TTBDock.GetToolbarCount: Integer; +begin + Result := DockVisibleList.Count; +end; + +function TTBDock.GetToolbars(Index: Integer): TTBCustomDockableWindow; +begin + Result := TTBCustomDockableWindow(DockVisibleList[Index]); +end; + +(*function TTBDock.GetVersion: TToolbar97Version; +begin + Result := Toolbar97VersionPropText; +end; + +procedure TTBDock.SetVersion(const Value: TToolbar97Version); +begin + { write method required for the property to show up in Object Inspector } +end;*) + + +{ TTBFloatingWindowParent - Internal } + +constructor TTBFloatingWindowParent.Create(AOwner: TComponent); +begin + { Don't use TForm's Create since it attempts to load a form resource, which + TTBFloatingWindowParent doesn't have. } + CreateNew(AOwner {$IFDEF VER93} , 0 {$ENDIF}); +end; + +destructor TTBFloatingWindowParent.Destroy; +begin + inherited; +end; + +procedure TTBFloatingWindowParent.CreateParams(var Params: TCreateParams); +const + ThickFrames: array[Boolean] of DWORD = (0, WS_THICKFRAME); +begin + inherited; + + { Disable complete redraws when size changes. CS_H/VREDRAW cause flicker + and are not necessary for this control at run time } + if not(csDesigning in ComponentState) then + with Params.WindowClass do + Style := Style and not(CS_HREDRAW or CS_VREDRAW); + + with Params do begin + { Note: WS_THICKFRAME and WS_BORDER styles are included to ensure that + sizing grips are displayed on child controls with scrollbars. The + thick frame or border is not drawn by Windows; TCustomToolWindow97 + handles all border drawing by itself. } + if not(csDesigning in ComponentState) then + Style := WS_POPUP or WS_BORDER or ThickFrames[FDockableWindow.FResizable] + else + Style := Style or WS_BORDER or ThickFrames[FDockableWindow.FResizable]; + { The WS_EX_TOOLWINDOW style is needed so there isn't a taskbar button + for the toolbar when FloatingMode = fmOnTopOfAllForms. } + ExStyle := WS_EX_TOOLWINDOW; + end; +end; + +procedure TTBFloatingWindowParent.AlignControls(AControl: TControl; var Rect: TRect); +begin + { ignore Align setting of the child toolbar } +end; + +procedure TTBFloatingWindowParent.WMGetMinMaxInfo(var Message: TWMGetMinMaxInfo); +begin + inherited; + { Because the window uses the WS_THICKFRAME style (but not for the usual + purpose), it must process the WM_GETMINMAXINFO message to remove the + minimum and maximum size limits it imposes by default. } + with Message.MinMaxInfo^ do begin + with ptMinTrackSize do begin + X := 1; + Y := 1; + { Note to self: Don't put GetMinimumSize code here, since + ClientWidth/Height values are sometimes invalid during a RecreateWnd } + end; + with ptMaxTrackSize do begin + { Because of the 16-bit (signed) size limitations of Windows 95, + Smallints must be used instead of Integers or Longints } + X := High(Smallint); + Y := High(Smallint); + end; + end; +end; + +procedure TTBFloatingWindowParent.CMShowingChanged(var Message: TMessage); +const + ShowFlags: array[Boolean] of UINT = ( + SWP_NOSIZE or SWP_NOMOVE or SWP_NOZORDER or SWP_NOACTIVATE or SWP_HIDEWINDOW, + SWP_NOSIZE or SWP_NOMOVE or SWP_NOZORDER or SWP_NOACTIVATE or SWP_SHOWWINDOW); +begin + { Must override TCustomForm/TForm's CM_SHOWINGCHANGED handler so that the + form doesn't get activated when Visible is set to True. } + SetWindowPos(WindowHandle, 0, 0, 0, 0, 0, ShowFlags[Showing and FShouldShow]); +end; + +procedure TTBFloatingWindowParent.CMDialogKey(var Message: TCMDialogKey); +begin + { If Escape if pressed on a floating toolbar, return focus to the form } + if (Message.CharCode = VK_ESCAPE) and (KeyDataToShiftState(Message.KeyData) = []) and + Assigned(ParentForm) then begin + ParentForm.SetFocus; + Message.Result := 1; + end + else + inherited; +end; + +procedure TTBFloatingWindowParent.CMTextChanged(var Message: TMessage); +begin + inherited; + RedrawNCArea([twrdCaption]); +end; + +function GetCaptionRect(const Control: TTBFloatingWindowParent; + const AdjustForBorder, MinusCloseButton: Boolean): TRect; +begin + Result := Rect(0, 0, Control.ClientWidth, GetSmallCaptionHeight-1); + if MinusCloseButton then + Dec(Result.Right, Result.Bottom); + if AdjustForBorder then + with Control.FDockableWindow.GetFloatingBorderSize do + OffsetRect(Result, X, Y); +end; + +function GetCloseButtonRect(const Control: TTBFloatingWindowParent; + const AdjustForBorder: Boolean): TRect; +begin + Result := GetCaptionRect(Control, AdjustForBorder, False); + Result.Left := Result.Right - (GetSmallCaptionHeight-1); +end; + +procedure TTBFloatingWindowParent.WMNCCalcSize(var Message: TWMNCCalcSize); +var + TL, BR: TPoint; +begin + { Doesn't call inherited since it overrides the normal NC sizes } + Message.Result := 0; + with Message.CalcSize_Params^ do begin + FDockableWindow.GetFloatingNCArea(TL, BR); + with rgrc[0] do begin + Inc(Left, TL.X); + Inc(Top, TL.Y); + Dec(Right, BR.X); + Dec(Bottom, BR.Y); + end; + end; +end; + +procedure TTBFloatingWindowParent.WMNCPaint(var Message: TMessage); +begin + { Don't call inherited because it overrides the default NC painting } + DrawNCArea(False, 0, HRGN(Message.WParam), twrdAll); +end; + +procedure FloatingWindowParentNCPaintProc(Wnd: HWND; DC: HDC; AppData: Longint); +begin + with TTBFloatingWindowParent(AppData) do + DrawNCArea(True, DC, 0, twrdAll); +end; + +procedure TTBFloatingWindowParent.WMPrint(var Message: TMessage); +begin + HandleWMPrint(Handle, Message, FloatingWindowParentNCPaintProc, Longint(Self)); +end; + +procedure TTBFloatingWindowParent.WMPrintClient(var Message: TMessage); +begin + HandleWMPrintClient(Self, Message); +end; + +procedure TTBFloatingWindowParent.WMNCHitTest(var Message: TWMNCHitTest); +var + P: TPoint; + R: TRect; + BorderSize: TPoint; + C: Integer; +begin + inherited; + with Message do begin + P := SmallPointToPoint(Pos); + GetWindowRect(Handle, R); + Dec(P.X, R.Left); Dec(P.Y, R.Top); + if Result <> HTCLIENT then begin + Result := HTNOWHERE; + if FDockableWindow.ShowCaption and PtInRect(GetCaptionRect(Self, True, False), P) then begin + if FDockableWindow.FCloseButton and PtInRect(GetCloseButtonRect(Self, True), P) then + Result := HT_TB2k_Close + else + Result := HT_TB2k_Caption; + end + else + if FDockableWindow.Resizable then begin + BorderSize := FDockableWindow.GetFloatingBorderSize; + if not(tbdsResizeEightCorner in FDockableWindow.FDockableWindowStyles) then begin + if (P.Y >= 0) and (P.Y < BorderSize.Y) then Result := HTTOP else + if (P.Y < Height) and (P.Y >= Height-BorderSize.Y-1) then Result := HTBOTTOM else + if (P.X >= 0) and (P.X < BorderSize.X) then Result := HTLEFT else + if (P.X < Width) and (P.X >= Width-BorderSize.X-1) then Result := HTRIGHT; + end + else begin + C := BorderSize.X + (GetSmallCaptionHeight-1); + if (P.X >= 0) and (P.X < BorderSize.X) then begin + Result := HTLEFT; + if (P.Y < C) then Result := HTTOPLEFT else + if (P.Y >= Height-C) then Result := HTBOTTOMLEFT; + end + else + if (P.X < Width) and (P.X >= Width-BorderSize.X-1) then begin + Result := HTRIGHT; + if (P.Y < C) then Result := HTTOPRIGHT else + if (P.Y >= Height-C) then Result := HTBOTTOMRIGHT; + end + else + if (P.Y >= 0) and (P.Y < BorderSize.Y) then begin + Result := HTTOP; + if (P.X < C) then Result := HTTOPLEFT else + if (P.X >= Width-C) then Result := HTTOPRIGHT; + end + else + if (P.Y < Height) and (P.Y >= Height-BorderSize.Y-1) then begin + Result := HTBOTTOM; + if (P.X < C) then Result := HTBOTTOMLEFT else + if (P.X >= Width-C) then Result := HTBOTTOMRIGHT; + end; + end; + end; + end; + end; +end; + +procedure TTBFloatingWindowParent.SetCloseButtonState(Pushed: Boolean); +begin + if FCloseButtonDown <> Pushed then begin + FCloseButtonDown := Pushed; + RedrawNCArea([twrdCloseButton]); + end; +end; + +procedure TTBFloatingWindowParent.WMNCLButtonDown(var Message: TWMNCLButtonDown); +var + P: TPoint; + R, BR: TRect; +begin + case Message.HitTest of + HT_TB2k_Caption: begin + P := FDockableWindow.ScreenToClient(Point(Message.XCursor, Message.YCursor)); + FDockableWindow.BeginMoving(P.X, P.Y); + end; + HTLEFT..HTBOTTOMRIGHT: + if FDockableWindow.Resizable then + FDockableWindow.BeginSizing(TTBSizeHandle(Message.HitTest - HTLEFT)); + HT_TB2k_Close: begin + GetWindowRect(Handle, R); + BR := GetCloseButtonRect(Self, True); + OffsetRect(BR, R.Left, R.Top); + if CloseButtonLoop(Handle, BR, SetCloseButtonState) then + FDockableWindow.Close; + end; + else + inherited; + end; +end; + +procedure TTBFloatingWindowParent.WMNCLButtonDblClk(var Message: TWMNCLButtonDblClk); +begin + if Message.HitTest = HT_TB2k_Caption then + FDockableWindow.DoubleClick; +end; + +procedure TTBFloatingWindowParent.WMNCRButtonUp(var Message: TWMNCRButtonUp); +begin + FDockableWindow.ShowNCContextMenu(TSmallPoint(TMessage(Message).LParam)); +end; + +procedure TTBFloatingWindowParent.WMClose(var Message: TWMClose); +var + MDIParentForm: TTBCustomForm; +begin + { A floating toolbar does not use WM_CLOSE messages when its close button + is clicked, but Windows still sends a WM_CLOSE message if the user + presses Alt+F4 while one of the toolbar's controls is focused. Inherited + is not called since we do not want Windows' default processing - which + destroys the window. Instead, relay the message to the parent form. } + MDIParentForm := GetMDIParent(TBGetToolWindowParentForm(FDockableWindow)); + if Assigned(MDIParentForm) and MDIParentForm.HandleAllocated then + SendMessage(MDIParentForm.Handle, WM_CLOSE, 0, 0); + { Note to self: MDIParentForm is used instead of OwnerForm since MDI + childs don't process Alt+F4 as Close } +end; + +procedure TTBFloatingWindowParent.WMActivate(var Message: TWMActivate); +var + ParentForm: TTBCustomForm; +begin + if csDesigning in ComponentState then begin + inherited; + Exit; + end; + + ParentForm := GetMDIParent(TBGetToolWindowParentForm(FDockableWindow)); + + if Assigned(ParentForm) and ParentForm.HandleAllocated then + SendMessage(ParentForm.Handle, WM_NCACTIVATE, Ord(Message.Active <> WA_INACTIVE), 0); + + if Message.Active <> WA_INACTIVE then begin + { This works around a "gotcha" in TCustomForm.CMShowingChanged. When a form + is hidden, it uses the internal VCL function FindTopMostWindow to + find a new active window. The problem is that handles of floating + toolbars on the form being hidden can be returned by + FindTopMostWindow, so the following code is used to prevent floating + toolbars on the hidden form from being left active. } + if not IsWindowVisible(Handle) then + { ^ Calling IsWindowVisible with a floating toolbar handle will + always return False if its parent form is hidden since the + WH_CALLWNDPROC hook automatically updates the toolbars' + visibility. } + { Find and activate a window besides this toolbar } + SetActiveWindow(FindTopLevelWindow(Handle)) + else + { If the toolbar is being activated and the previous active window wasn't + its parent form, the form is activated instead. This is done so that if + the application is deactivated while a floating toolbar was active and + the application is reactivated again, it returns focus to the form. } + if Assigned(ParentForm) and ParentForm.HandleAllocated and + (Message.ActiveWindow <> ParentForm.Handle) then + SetActiveWindow(ParentForm.Handle); + end; +end; + +procedure TTBFloatingWindowParent.WMMouseActivate(var Message: TWMMouseActivate); +var + ParentForm, MDIParentForm: TTBCustomForm; +begin + if csDesigning in ComponentState then begin + inherited; + Exit; + end; + + { When floating, prevent the toolbar from activating when clicked. + This is so it doesn't take the focus away from the window that had it } + Message.Result := MA_NOACTIVATE; + + { Similar to calling BringWindowToTop, but doesn't activate it } + SetWindowPos(Handle, HWND_TOP, 0, 0, 0, 0, + SWP_NOACTIVATE or SWP_NOMOVE or SWP_NOSIZE); + + { Since it is returning MA_NOACTIVATE, activate the form instead. } + ParentForm := TBGetToolWindowParentForm(FDockableWindow); + MDIParentForm := GetMDIParent(ParentForm); + if (FDockableWindow.FFloatingMode = fmOnTopOfParentForm) and + FDockableWindow.FActivateParent and + Assigned(MDIParentForm) and (GetActiveWindow <> Handle) then begin + { ^ Note to self: The GetActiveWindow check must be in there so that + double-clicks work properly on controls like Edits } + if MDIParentForm.HandleAllocated then + SetActiveWindow(MDIParentForm.Handle); + if (MDIParentForm <> ParentForm) and { if it's an MDI child form } + ParentForm.HandleAllocated then + BringWindowToTop(ParentForm.Handle); + end; +end; + +procedure TTBFloatingWindowParent.WMMove(var Message: TWMMove); +begin + inherited; + FDockableWindow.Moved; +end; + +procedure TTBFloatingWindowParent.DrawNCArea(const DrawToDC: Boolean; + const ADC: HDC; const Clip: HRGN; RedrawWhat: TTBToolWindowNCRedrawWhat); +{ Redraws all the non-client area (the border, title bar, and close button) of + the toolbar when it is floating. } +const + COLOR_GRADIENTACTIVECAPTION = 27; + COLOR_GRADIENTINACTIVECAPTION = 28; + CaptionBkColors: array[Boolean, Boolean] of Integer = + ((COLOR_ACTIVECAPTION, COLOR_INACTIVECAPTION), + (COLOR_GRADIENTACTIVECAPTION, COLOR_GRADIENTINACTIVECAPTION)); + CaptionTextColors: array[Boolean] of Integer = + (COLOR_CAPTIONTEXT, COLOR_INACTIVECAPTIONTEXT); + + function GradientCaptionsEnabled: Boolean; + const + SPI_GETGRADIENTCAPTIONS = $1008; { Win98/NT5 only } + var + S: BOOL; + begin + Result := SystemParametersInfo(SPI_GETGRADIENTCAPTIONS, 0, @S, 0) and S; + end; + +const + CloseButtonState: array[Boolean] of UINT = (0, DFCS_PUSHED); + ActiveCaptionFlags: array[Boolean] of UINT = (DC_ACTIVE, 0); + DC_GRADIENT = $20; + GradientCaptionFlags: array[Boolean] of UINT = (0, DC_GRADIENT); +var + DC: HDC; + R, R2: TRect; + Gradient: Boolean; + SavePen: HPEN; + SaveIndex: Integer; + S: TPoint; +begin + if not HandleAllocated then Exit; + + if not DrawToDC then + DC := GetWindowDC(Handle) + else + DC := ADC; + try + { Use update region } + if not DrawToDC then + SelectNCUpdateRgn(Handle, DC, Clip); + + { Work around an apparent NT 4.0 & 2000 bug. If the width of the DC is + greater than the width of the screen, then any call to ExcludeClipRect + inexplicably shrinks the clipping rectangle to the screen width. I've + found that calling IntersectClipRect as done below magically fixes the + problem (but I'm not sure why). } + GetWindowRect(Handle, R); OffsetRect(R, -R.Left, -R.Top); + IntersectClipRect(DC, R.Left, R.Top, R.Right, R.Bottom); + + Gradient := GradientCaptionsEnabled; + + { Border } + if twrdBorder in RedrawWhat then begin + { This works around WM_NCPAINT problem described at top of source code } + {no! R := Rect(0, 0, Width, Height);} + GetWindowRect(Handle, R); OffsetRect(R, -R.Left, -R.Top); + DrawEdge(DC, R, EDGE_RAISED, BF_RECT); + SaveIndex := SaveDC(DC); + S := FDockableWindow.GetFloatingBorderSize; + with R do + ExcludeClipRect(DC, Left + S.X, Top + S.Y, Right - S.X, Bottom - S.Y); + InflateRect(R, -2, -2); + FillRect(DC, R, GetSysColorBrush(COLOR_BTNFACE)); + RestoreDC(DC, SaveIndex); + end; + + if FDockableWindow.ShowCaption then begin + if (twrdCaption in RedrawWhat) and FDockableWindow.FCloseButton and + (twrdCloseButton in RedrawWhat) then + SaveIndex := SaveDC(DC) + else + SaveIndex := 0; + try + if SaveIndex <> 0 then + with GetCloseButtonRect(Self, True) do + { Reduces flicker } + ExcludeClipRect(DC, Left, Top, Right, Bottom); + + { Caption } + if twrdCaption in RedrawWhat then begin + R := GetCaptionRect(Self, True, FDockableWindow.FCloseButton); + { Note that Delphi's Win32 help for DrawCaption is totally wrong! + I got updated info from www.microsoft.com/msdn/sdk/ } + DrawCaption(Handle, DC, R, DC_TEXT or DC_SMALLCAP or + ActiveCaptionFlags[FDockableWindow.FInactiveCaption] or + GradientCaptionFlags[Gradient]); + + { Line below caption } + R := GetCaptionRect(Self, True, False); + SavePen := SelectObject(DC, CreatePen(PS_SOLID, 1, GetSysColor(COLOR_BTNFACE))); + MoveToEx(DC, R.Left, R.Bottom, nil); + LineTo(DC, R.Right, R.Bottom); + DeleteObject(SelectObject(DC, SavePen)); + end; + finally + if SaveIndex <> 0 then + RestoreDC(DC, SaveIndex); + end; + + { Close button } + if FDockableWindow.FCloseButton then begin + R := GetCloseButtonRect(Self, True); + R2 := R; + InflateRect(R2, 0, -2); + Dec(R2.Right, 2); + if twrdCaption in RedrawWhat then begin + SaveIndex := SaveDC(DC); + ExcludeClipRect(DC, R2.Left, R2.Top, R2.Right, R2.Bottom); + FillRect(DC, R, GetSysColorBrush(CaptionBkColors[Gradient, + FDockableWindow.FInactiveCaption])); + RestoreDC(DC, SaveIndex); + end; + if twrdCloseButton in RedrawWhat then + DrawFrameControl(DC, R2, DFC_CAPTION, DFCS_CAPTIONCLOSE or + CloseButtonState[FCloseButtonDown]); + end; + end; + finally + if not DrawToDC then + ReleaseDC(Handle, DC); + end; +end; + +procedure TTBFloatingWindowParent.RedrawNCArea(const RedrawWhat: TTBToolWindowNCRedrawWhat); +begin + { Note: IsWindowVisible is called as an optimization. There's no need to + draw on invisible windows. } + if HandleAllocated and IsWindowVisible(Handle) then + DrawNCArea(False, 0, 0, RedrawWhat); +end; + + +{ TTBCustomDockableWindow } + +constructor TTBCustomDockableWindow.Create(AOwner: TComponent); +begin + inherited; + + ControlStyle := ControlStyle + + [csAcceptsControls, csClickEvents, csDoubleClicks, csSetCaption] - + [csCaptureMouse{capturing is done manually}, csOpaque]; + FAutoResize := True; + FActivateParent := True; + FBorderStyle := bsSingle; + FCloseButton := True; + FDockableTo := [dpTop, dpBottom, dpLeft, dpRight]; + FDockableWindowStyles := [tbdsResizeEightCorner, tbdsResizeClipCursor]; + FDockPos := -1; + FDragHandleStyle := dhSingle; + FEffectiveDockRow := -1; + FHideWhenInactive := True; + FResizable := True; + FShowCaption := True; + FSmoothDrag := True; + FUseLastDock := True; + + Color := clBtnFace; + + if not(csDesigning in ComponentState) then + InstallHookProc(Self, ToolbarHookProc, [hpSendActivate, hpSendActivateApp, + hpSendWindowPosChanged, hpPreDestroy]); + InitTrackMouseEvent; +end; + +destructor TTBCustomDockableWindow.Destroy; +begin + inherited; + FDockForms.Free; { must be done after 'inherited' because Notification accesses FDockForms } + FFloatParent.Free; + UninstallHookProc(Self, ToolbarHookProc); +end; + +function TTBCustomDockableWindow.HasParent: Boolean; +begin + if Parent is TTBFloatingWindowParent then + Result := False + else + Result := inherited HasParent; +end; + +function TTBCustomDockableWindow.GetParentComponent: TComponent; +begin + if Parent is TTBFloatingWindowParent then + Result := nil + else + Result := inherited GetParentComponent; +end; + +procedure TTBCustomDockableWindow.Moved; +begin + if not(csLoading in ComponentState) and Assigned(FOnMove) and (FDisableOnMove <= 0) then + FOnMove(Self); +end; + +procedure TTBCustomDockableWindow.WMMove(var Message: TWMMove); + + procedure Redraw; + { Redraws the control using an off-screen bitmap to avoid flicker } + var + CR, R: TRect; + W: HWND; + DC, BmpDC: HDC; + Bmp: HBITMAP; + begin + if not HandleAllocated then Exit; + CR := ClientRect; + W := Handle; + if GetUpdateRect(W, R, False) and EqualRect(R, CR) then begin + { The client area is already completely invalid, so don't bother using + an off-screen bitmap } + InvalidateAll(Self); + Exit; + end; + BmpDC := 0; + Bmp := 0; + DC := GetDC(W); + try + BmpDC := CreateCompatibleDC(DC); + Bmp := CreateCompatibleBitmap(DC, CR.Right, CR.Bottom); + SelectObject(BmpDC, Bmp); + SendMessage(W, WM_NCPAINT, 0, 0); + SendMessage(W, WM_ERASEBKGND, WPARAM(BmpDC), 0); + SendMessage(W, WM_PAINT, WPARAM(BmpDC), 0); + BitBlt(DC, 0, 0, CR.Right, CR.Bottom, BmpDC, 0, 0, SRCCOPY); + finally + if BmpDC <> 0 then DeleteDC(BmpDC); + if Bmp <> 0 then DeleteObject(Bmp); + ReleaseDC(W, DC); + end; + ValidateRect(W, nil); + end; + +begin + inherited; + FMoved := True; + if Docked and CurrentDock.UsingBackground then begin + { Needs to redraw so that the background is lined up with the dock at the + new position. } + Redraw; + end; + Moved; +end; + +{$IFNDEF JR_D4} +procedure TTBCustomDockableWindow.WMSize(var Message: TWMSize); +begin + inherited; + if not(csLoading in ComponentState) and Assigned(FOnResize) then + FOnResize(Self); +end; +{$ENDIF} + +procedure TTBCustomDockableWindow.WMEnable(var Message: TWMEnable); +begin + inherited; + { When a modal dialog is displayed and the toolbar window gets disabled as + a result, remove its topmost flag. } + if FFloatingMode = fmOnTopOfAllForms then + UpdateTopmostFlag; +end; + +procedure TTBCustomDockableWindow.UpdateCaptionState; +{ Updates the caption active/inactive state of a floating tool window. + Called when the tool window is visible or is about to be shown. } + + function IsPopupWindowActive: Boolean; + const + IID_ITBPopupWindow: TGUID = '{E45CBE74-1ECF-44CB-B064-6D45B1924708}'; + var + Ctl: TWinControl; + begin + Ctl := FindControl(GetActiveWindow); + { Instead of using "is TTBPopupWindow", which would require linking to the + TB2Item unit, check if the control implements the ITBPopupWindow + interface. This will tell us if it's a TTBPopupWindow or descendant. } + Result := Assigned(Ctl) and Assigned(Ctl.GetInterfaceEntry(IID_ITBPopupWindow)); + end; + + function GetActiveFormWindow: HWND; + var + Ctl: TWinControl; + begin + Result := GetActiveWindow; + { If the active window is a TTBFloatingWindowParent (i.e. a control on a + floating toolbar is focused), return the parent form handle instead } + Ctl := FindControl(Result); + if Assigned(Ctl) and (Ctl is TTBFloatingWindowParent) then begin + Ctl := TTBFloatingWindowParent(Ctl).ParentForm; + if Assigned(Ctl) and Ctl.HandleAllocated then + Result := Ctl.Handle; + end; + end; + +var + Inactive: Boolean; + ActiveWnd: HWND; +begin + { Update caption state if floating, but not if a control on a popup window + (e.g. a TTBEditItem) is currently focused; we don't want the captions on + all floating toolbars to turn gray in that case. (The caption state will + get updated when we're called the next time the active window changes, + i.e. when the user dismisses the popup window.) } + if (Parent is TTBFloatingWindowParent) and Parent.HandleAllocated and + not IsPopupWindowActive then begin + Inactive := False; + if not ApplicationIsActive then + Inactive := True + else if (FFloatingMode = fmOnTopOfParentForm) and + (HWND(GetWindowLong(Parent.Handle, GWL_HWNDPARENT)) <> Application.Handle) then begin + { Use inactive caption if the active window doesn't own the float parent + (directly or indirectly). Note: For compatibility with browser-embedded + TActiveForms, we use IsAncestorOfWindow instead of checking + TBGetToolWindowParentForm. } + ActiveWnd := GetActiveFormWindow; + if (ActiveWnd = 0) or not IsAncestorOfWindow(ActiveWnd, Parent.Handle) then + Inactive := True; + end; + if FInactiveCaption <> Inactive then begin + FInactiveCaption := Inactive; + TTBFloatingWindowParent(Parent).RedrawNCArea(twrdAll); + end; + end; +end; + +function TTBCustomDockableWindow.GetShowingState: Boolean; + + function IsWindowVisibleAndNotMinimized(Wnd: HWND): Boolean; + begin + Result := IsWindowVisible(Wnd); + if Result then begin + { Wnd may not be a top-level window (e.g. in the case of an MDI child + form, or an ActiveForm embedded in a web page), so go up the chain of + parent windows and see if any of them are minimized } + repeat + if IsIconic(Wnd) then begin + Result := False; + Break; + end; + { Stop if we're at a top-level window (no need to check owner windows) } + if GetWindowLong(Wnd, GWL_STYLE) and WS_CHILD = 0 then + Break; + Wnd := GetParent(Wnd); + until Wnd = 0; + end; + end; + +var + HideFloatingToolbars: Boolean; + ParentForm: TTBCustomForm; +begin + Result := Showing and (FHidden = 0); + if Floating and not(csDesigning in ComponentState) then begin + HideFloatingToolbars := FFloatingMode = fmOnTopOfParentForm; + if HideFloatingToolbars then begin + ParentForm := TBGetToolWindowParentForm(Self); + if Assigned(ParentForm) and ParentForm.HandleAllocated and + IsWindowVisibleAndNotMinimized(ParentForm.Handle) then + HideFloatingToolbars := False; + end; + Result := Result and not (HideFloatingToolbars or (FHideWhenInactive and not ApplicationIsActive)); + end; +end; + +procedure TTBCustomDockableWindow.UpdateVisibility; +{ Updates the visibility of the tool window, and additionally the caption + state if floating and showing } +var + IsVisible: Boolean; +begin + if HandleAllocated then begin + IsVisible := IsWindowVisible(Handle); + if IsVisible <> GetShowingState then begin + Perform(CM_SHOWINGCHANGED, 0, 0); + { Note: CMShowingChanged will call UpdateCaptionState automatically + when floating and showing } + end + else if IsVisible and Floating then begin + { If we're floating and we didn't send the CM_SHOWINGCHANGED message + then we have to call UpdateCaptionState manually } + UpdateCaptionState; + end; + end; +end; + +function IsTopmost(const Wnd: HWND): Boolean; +begin + Result := GetWindowLong(Wnd, GWL_EXSTYLE) and WS_EX_TOPMOST <> 0; +end; + +procedure TTBCustomDockableWindow.UpdateTopmostFlag; +const + Wnds: array[Boolean] of HWND = (HWND_NOTOPMOST, HWND_TOPMOST); +var + ShouldBeTopmost: Boolean; +begin + if HandleAllocated then begin + if FFloatingMode = fmOnTopOfAllForms then + ShouldBeTopmost := IsWindowEnabled(Handle) + else + ShouldBeTopmost := IsTopmost(HWND(GetWindowLong(Parent.Handle, GWL_HWNDPARENT))); + if ShouldBeTopmost <> IsTopmost(Parent.Handle) then + { ^ it must check if it already was topmost or non-topmost or else + it causes problems on Win95/98 for some reason } + SetWindowPos(Parent.Handle, Wnds[ShouldBeTopmost], 0, 0, 0, 0, + SWP_NOACTIVATE or SWP_NOMOVE or SWP_NOSIZE); + end; +end; + +procedure TTBCustomDockableWindow.CMShowingChanged(var Message: TMessage); + + function GetPrevWnd(W: HWND): HWND; + var + WasTopmost, Done: Boolean; + ParentWnd: HWND; + begin + WasTopmost := IsTopmost(Parent.Handle); + Result := W; + repeat + Done := True; + Result := GetWindow(Result, GW_HWNDPREV); + ParentWnd := Result; + while ParentWnd <> 0 do begin + if WasTopmost and not IsTopmost(ParentWnd) then begin + Done := False; + Break; + end; + ParentWnd := HWND(GetWindowLong(ParentWnd, GWL_HWNDPARENT)); + if ParentWnd = W then begin + Done := False; + Break; + end; + end; + until Done; + end; + +const + ShowFlags: array[Boolean] of UINT = ( + SWP_NOSIZE or SWP_NOMOVE or SWP_NOZORDER or SWP_NOACTIVATE or SWP_HIDEWINDOW, + SWP_NOSIZE or SWP_NOMOVE or SWP_NOZORDER or SWP_NOACTIVATE or SWP_SHOWWINDOW); +var + Show: Boolean; + Form: TTBCustomForm; +begin + { inherited isn't called since TTBCustomDockableWindow handles CM_SHOWINGCHANGED + itself. For reference, the original TWinControl implementation is: + const + ShowFlags: array[Boolean] of Word = ( + SWP_NOSIZE + SWP_NOMOVE + SWP_NOZORDER + SWP_NOACTIVATE + SWP_HIDEWINDOW, + SWP_NOSIZE + SWP_NOMOVE + SWP_NOZORDER + SWP_NOACTIVATE + SWP_SHOWWINDOW); + begin + SetWindowPos(FHandle, 0, 0, 0, 0, 0, ShowFlags[FShowing]); + end; + } + if HandleAllocated then begin + Show := GetShowingState; + if Parent is TTBFloatingWindowParent then begin + if Show then begin + { If the toolbar is floating, set its "owner window" to the parent form + so that the toolbar window always stays on top of the form } + if FFloatingMode = fmOnTopOfParentForm then begin + Form := GetMDIParent(TBGetToolWindowParentForm(Self)); + if Assigned(Form) and Form.HandleAllocated and + (HWND(GetWindowLong(Parent.Handle, GWL_HWNDPARENT)) <> Form.Handle) then begin + SetWindowLong(Parent.Handle, GWL_HWNDPARENT, Longint(Form.Handle)); + { Following is necessarily to make it immediately realize the + GWL_HWNDPARENT change } + SetWindowPos(Parent.Handle, GetPrevWnd(Form.Handle), 0, 0, 0, 0, SWP_NOACTIVATE or + SWP_NOMOVE or SWP_NOSIZE); + end; + end + else begin + SetWindowLong(Parent.Handle, GWL_HWNDPARENT, Longint(Application.Handle)); + end; + { Initialize caption state after setting owner but before showing } + UpdateCaptionState; + end; + UpdateTopmostFlag; + { Show/hide the TTBFloatingWindowParent. The following lines had to be + added to fix a problem that was in 1.65d/e. In 1.65d/e, it always + kept TTBFloatingWindowParent visible (this change was made to improve + compatibility with D4's Actions), but this for some odd reason would + cause a Stack Overflow error if the program's main form was closed + while a floating toolwindow was focused. (This problem did not occur + on NT.) } + TTBFloatingWindowParent(Parent).FShouldShow := Show; + Parent.Perform(CM_SHOWINGCHANGED, 0, 0); + end; + SetWindowPos(Handle, 0, 0, 0, 0, 0, ShowFlags[Show]); + if not Show and (GetActiveWindow = Handle) then + { If the window is hidden but is still active, find and activate a + different window } + SetActiveWindow(FindTopLevelWindow(Handle)); + end; +end; + +procedure TTBCustomDockableWindow.CreateParams(var Params: TCreateParams); +begin + inherited; + + { Disable complete redraws when size changes. CS_H/VREDRAW cause flicker + and are not necessary for this control at run time } + if not(csDesigning in ComponentState) then + with Params.WindowClass do + Style := Style and not(CS_HREDRAW or CS_VREDRAW); +end; + +procedure TTBCustomDockableWindow.Notification(AComponent: TComponent; Operation: TOperation); +begin + inherited; + if Operation = opRemove then begin + if AComponent = FDefaultDock then + FDefaultDock := nil + else + if AComponent = FLastDock then + FLastDock := nil + else begin + RemoveFromList(FDockForms, AComponent); + if Assigned(FFloatParent) and (csDestroying in FFloatParent.ComponentState) and + (AComponent = FFloatParent.FParentForm) then begin + { ^ Note: Must check csDestroying so that we are sure that FFloatParent + is actually being destroyed and not just being removed from its + Owner's component list } + if Parent = FFloatParent then begin + if FFloatingMode = fmOnTopOfParentForm then + Parent := nil + else + FFloatParent.FParentForm := nil; + end + else begin + FFloatParent.Free; + FFloatParent := nil; + end; + end; + end; + end; +end; + +procedure TTBCustomDockableWindow.MoveOnScreen(const OnlyIfFullyOffscreen: Boolean); +{ Moves the (floating) toolbar so that it is fully (or at least mostly) in + view on the screen } +var + R, S, Test: TRect; +begin + if Floating then begin + R := Parent.BoundsRect; + S := GetRectOfMonitorContainingRect(R, True); + + if OnlyIfFullyOffscreen and IntersectRect(Test, R, S) then + Exit; + + if R.Right > S.Right then + OffsetRect(R, S.Right - R.Right, 0); + if R.Bottom > S.Bottom then + OffsetRect(R, 0, S.Bottom - R.Bottom); + if R.Left < S.Left then + OffsetRect(R, S.Left - R.Left, 0); + if R.Top < S.Top then + OffsetRect(R, 0, S.Top - R.Top); + Parent.BoundsRect := R; + end; +end; + +procedure TTBCustomDockableWindow.ReadPositionData(const Data: TTBReadPositionData); +begin +end; + +procedure TTBCustomDockableWindow.DoneReadingPositionData(const Data: TTBReadPositionData); +begin +end; + +procedure TTBCustomDockableWindow.WritePositionData(const Data: TTBWritePositionData); +begin +end; + +procedure TTBCustomDockableWindow.InitializeOrdering; +begin +end; + +procedure TTBCustomDockableWindow.SizeChanging(const AWidth, AHeight: Integer); +begin +end; + +procedure TTBCustomDockableWindow.ReadSavedAtRunTime(Reader: TReader); +begin + FSavedAtRunTime := Reader.ReadBoolean; +end; + +procedure TTBCustomDockableWindow.WriteSavedAtRunTime(Writer: TWriter); +begin + { WriteSavedAtRunTime only called when not(csDesigning in ComponentState) } + Writer.WriteBoolean(True); +end; + +procedure TTBCustomDockableWindow.DefineProperties(Filer: TFiler); +begin + inherited; + Filer.DefineProperty('SavedAtRunTime', ReadSavedAtRunTime, + WriteSavedAtRunTime, not(csDesigning in ComponentState)); +end; + +procedure TTBCustomDockableWindow.Loaded; +var + R: TRect; +begin + inherited; + { Adjust coordinates if it was initially floating } + if not FSavedAtRunTime and not(csDesigning in ComponentState) and + (Parent is TTBFloatingWindowParent) then begin + R := BoundsRect; + MapWindowPoints(TBValidToolWindowParentForm(Self).Handle, 0, R, 2); + BoundsRect := R; + MoveOnScreen(False); + end; + InitializeOrdering; + { Arranging is disabled while component was loading, so arrange now } + Arrange; +end; + +procedure TTBCustomDockableWindow.BeginUpdate; +begin + Inc(FDisableArrange); +end; + +procedure TTBCustomDockableWindow.EndUpdate; +begin + Dec(FDisableArrange); + if FArrangeNeeded and (FDisableArrange = 0) then + Arrange; +end; + +procedure TTBCustomDockableWindow.AddDockForm(const Form: TTBCustomForm); +begin + if Form = nil then Exit; + if AddToList(FDockForms, Form) then + Form.FreeNotification(Self); +end; + +procedure TTBCustomDockableWindow.RemoveDockForm(const Form: TTBCustomForm); +begin + RemoveFromList(FDockForms, Form); +end; + +function TTBCustomDockableWindow.IsAutoResized: Boolean; +begin + Result := AutoResize or Assigned(CurrentDock) or Floating; +end; + +procedure TTBCustomDockableWindow.ChangeSize(AWidth, AHeight: Integer); +var + S: TPoint; +begin + if Docked then + CurrentDock.ArrangeToolbars + else begin + S := CalcNCSizes; + Inc(AWidth, S.X); + Inc(AHeight, S.Y); + { Leave the width and/or height alone if the control is Anchored + (or Aligned) } + if not Floating then begin + if (akLeft in Anchors) and (akRight in Anchors) then + AWidth := Width; + if (akTop in Anchors) and (akBottom in Anchors) then + AHeight := Height; + end; + Inc(FUpdatingBounds); + try + SetBounds(Left, Top, AWidth, AHeight); + finally + Dec(FUpdatingBounds); + end; + end; +end; + +procedure TTBCustomDockableWindow.Arrange; +var + Size: TPoint; +begin + if (FDisableArrange > 0) or + { Prevent flicker while loading } + (csLoading in ComponentState) or + { Don't call DoArrangeControls when Parent is nil. The VCL sets Parent to + 'nil' during destruction of a component; we can't have an OrderControls + call after a descendant control has freed its data. } + (Parent = nil) then begin + FArrangeNeeded := True; + Exit; + end; + + FArrangeNeeded := False; + + Size := DoArrange(True, TBGetDockTypeOf(CurrentDock, Floating), Floating, + CurrentDock); + if IsAutoResized then + ChangeSize(Size.X, Size.Y); +end; + +procedure TTBCustomDockableWindow.SetBounds(ALeft, ATop, AWidth, AHeight: Integer); +begin + if not(csDesigning in ComponentState) and Floating then begin + { Force Top & Left to 0 if floating } + ALeft := 0; + ATop := 0; + if Parent is TTBFloatingWindowParent then + with Parent do + SetBounds(Left, Top, (Width-ClientWidth) + AWidth, + (Height-ClientHeight) + AHeight); + end; + if (FUpdatingBounds = 0) and ((AWidth <> Width) or (AHeight <> Height)) then + SizeChanging(AWidth, AHeight); + { This allows you to drag the toolbar around the dock at design time } + if (csDesigning in ComponentState) and not(csLoading in ComponentState) and + Docked and (FUpdatingBounds = 0) and ((ALeft <> Left) or (ATop <> Top)) then begin + if not(CurrentDock.Position in PositionLeftOrRight) then begin + FDockRow := CurrentDock.GetDesignModeRowOf(ATop+(Height div 2)); + FDockPos := ALeft; + end + else begin + FDockRow := CurrentDock.GetDesignModeRowOf(ALeft+(Width div 2)); + FDockPos := ATop; + end; + inherited SetBounds(Left, Top, AWidth, AHeight); { only pass any size changes } + CurrentDock.ArrangeToolbars; { let ArrangeToolbars take care of position changes } + end + else begin + inherited; + {if not(csLoading in ComponentState) and Floating and (FUpdatingBounds = 0) then + FFloatingPosition := BoundsRect.TopLeft;} + end; +end; + +procedure TTBCustomDockableWindow.SetParent(AParent: TWinControl); + procedure UpdateFloatingToolWindows; + begin + if Parent is TTBFloatingWindowParent then begin + AddToList(FloatingToolWindows, Self); + Parent.SetBounds(FFloatingPosition.X, FFloatingPosition.Y, + Parent.Width, Parent.Height); + end + else + RemoveFromList(FloatingToolWindows, Self); + end; + function ParentToCurrentDock(const Ctl: TWinControl): TTBDock; + begin + if Ctl is TTBDock then + Result := TTBDock(Ctl) + else + Result := nil; + end; +var + OldCurrentDock, NewCurrentDock: TTBDock; + NewFloating: Boolean; + OldParent: TWinControl; + SaveHandle: HWND; +begin + OldCurrentDock := ParentToCurrentDock(Parent); + NewCurrentDock := ParentToCurrentDock(AParent); + NewFloating := AParent is TTBFloatingWindowParent; + + if AParent = Parent then begin + { Even though AParent is the same as the current Parent, this code is + necessary because when the VCL destroys the parent of the tool window, + it calls TWinControl.Remove to set FParent instead of using SetParent. + However TControl.Destroy does call SetParent(nil), so it is + eventually notified of the change before it is destroyed. } + FCurrentDock := NewCurrentDock; + FFloating := NewFloating; + FDocked := Assigned(FCurrentDock); + UpdateFloatingToolWindows; + end + else begin + if not(csDestroying in ComponentState) and Assigned(AParent) then begin + if Assigned(FOnDockChanging) then + FOnDockChanging(Self, NewFloating, NewCurrentDock); + if Assigned(FOnRecreating) then + FOnRecreating(Self); + end; + + { Before changing between docked and floating state (and vice-versa) + or between docks, increment FHidden and call UpdateVisibility to hide the + toolbar. This prevents any flashing while it's being moved } + Inc(FHidden); + Inc(FDisableOnMove); + try + UpdateVisibility; + if Assigned(OldCurrentDock) then + OldCurrentDock.BeginUpdate; + if Assigned(NewCurrentDock) then + NewCurrentDock.BeginUpdate; + Inc(FUpdatingBounds); + try + if Assigned(AParent) then + DoDockChangingHidden(NewFloating, NewCurrentDock); + BeginUpdate; + try + { FCurrentSize probably won't be valid after changing Parents, so + reset it to zero } + FCurrentSize := 0; + + if Parent is TTBDock then begin + if not FUseLastDock or (FLastDock <> Parent) then + TTBDock(Parent).ChangeDockList(False, Self); + TTBDock(Parent).ToolbarVisibilityChanged(Self, True); + end; + + OldParent := Parent; + + SaveHandle := 0; + if Assigned(AParent) then begin + //AParent.HandleNeeded; + SaveHandle := WindowHandle; + WindowHandle := 0; + end; + { Ensure that the handle is destroyed now so that any messages in the queue + get flushed. This is neccessary since existing messages may reference + FDockedTo or FDocked, which is changed below. } + inherited SetParent(nil); + { ^ Note to self: SetParent is used instead of DestroyHandle because it does + additional processing } + FCurrentDock := NewCurrentDock; + FFloating := NewFloating; + FDocked := Assigned(FCurrentDock); + try + if SaveHandle <> 0 then begin + WindowHandle := SaveHandle; + Windows.SetParent(SaveHandle, AParent.Handle); + SetWindowPos(SaveHandle, 0, 0, 0, 0, 0, SWP_FRAMECHANGED or + SWP_NOACTIVATE or SWP_NOMOVE or SWP_NOSIZE or SWP_NOZORDER); + end; + inherited; + except + { Failure is rare, but just in case, restore FDockedTo and FDocked back. } + FCurrentDock := ParentToCurrentDock(Parent); + FFloating := Parent is TTBFloatingWindowParent; + FDocked := Assigned(FCurrentDock); + raise; + end; + + { FEffectiveDockRow probably won't be valid on the new Parent, so + reset it to -1 so that GetMinRowSize will temporarily ignore this + toolbar } + FEffectiveDockRow := -1; + + if not FSmoothDragging and (OldParent is TTBFloatingWindowParent) then begin + if FFloatParent = OldParent then FFloatParent := nil; + OldParent.Free; + end; + + if Parent is TTBDock then begin + if FUseLastDock and not FSmoothDragging then begin + LastDock := TTBDock(Parent); { calls ChangeDockList if LastDock changes } + TTBDock(Parent).ToolbarVisibilityChanged(Self, False); + end + else + TTBDock(Parent).ChangeDockList(True, Self); + end; + + UpdateFloatingToolWindows; + + { Schedule an arrange } + Arrange; + finally + EndUpdate; + end; + finally + Dec(FUpdatingBounds); + if Assigned(NewCurrentDock) then + NewCurrentDock.EndUpdate; + if Assigned(OldCurrentDock) then + OldCurrentDock.EndUpdate; + end; + finally + Dec(FDisableOnMove); + Dec(FHidden); + UpdateVisibility; + { ^ The above UpdateVisibility call not only updates the tool window's + visibility after decrementing FHidden, it also sets the + active/inactive state of the caption. } + end; + if Assigned(Parent) then + Moved; + + if not(csDestroying in ComponentState) and Assigned(AParent) then begin + if Assigned(FOnRecreated) then + FOnRecreated(Self); + if Assigned(FOnDockChanged) then + FOnDockChanged(Self); + end; + end; +end; + +procedure TTBCustomDockableWindow.AddDockedNCAreaToSize(var S: TPoint; + const LeftRight: Boolean); +var + TopLeft, BottomRight: TPoint; +begin + GetDockedNCArea(TopLeft, BottomRight, LeftRight); + Inc(S.X, TopLeft.X + BottomRight.X); + Inc(S.Y, TopLeft.Y + BottomRight.Y); +end; + +procedure TTBCustomDockableWindow.AddFloatingNCAreaToSize(var S: TPoint); +var + TopLeft, BottomRight: TPoint; +begin + GetFloatingNCArea(TopLeft, BottomRight); + Inc(S.X, TopLeft.X + BottomRight.X); + Inc(S.Y, TopLeft.Y + BottomRight.Y); +end; + +procedure TTBCustomDockableWindow.GetDockedNCArea(var TopLeft, BottomRight: TPoint; + const LeftRight: Boolean); +var + Z: Integer; +begin + Z := DockedBorderSize; { code optimization... } + TopLeft.X := Z; + TopLeft.Y := Z; + BottomRight.X := Z; + BottomRight.Y := Z; + if not LeftRight then begin + Inc(TopLeft.X, DragHandleSizes[CloseButtonWhenDocked, DragHandleStyle]); + //if FShowChevron then + // Inc(BottomRight.X, tbChevronSize); + end + else begin + Inc(TopLeft.Y, DragHandleSizes[CloseButtonWhenDocked, DragHandleStyle]); + //if FShowChevron then + // Inc(BottomRight.Y, tbChevronSize); + end; +end; + +function TTBCustomDockableWindow.GetFloatingBorderSize: TPoint; +{ Returns size of a thick border. Note that, depending on the Windows version, + this may not be the same as the actual window metrics since it draws its + own border } +const + XMetrics: array[Boolean] of Integer = (SM_CXDLGFRAME, SM_CXFRAME); + YMetrics: array[Boolean] of Integer = (SM_CYDLGFRAME, SM_CYFRAME); +begin + Result.X := GetSystemMetrics(XMetrics[Resizable]); + Result.Y := GetSystemMetrics(YMetrics[Resizable]); +end; + +procedure TTBCustomDockableWindow.GetFloatingNCArea(var TopLeft, BottomRight: TPoint); +begin + with GetFloatingBorderSize do begin + TopLeft.X := X; + TopLeft.Y := Y; + if ShowCaption then + Inc(TopLeft.Y, GetSmallCaptionHeight); + BottomRight.X := X; + BottomRight.Y := Y; + end; +end; + +function TTBCustomDockableWindow.GetDockedCloseButtonRect(LeftRight: Boolean): TRect; +var + X, Y, Z: Integer; +begin + Z := DragHandleSizes[CloseButtonWhenDocked, FDragHandleStyle] - 3; + if not LeftRight then begin + X := DockedBorderSize+1; + Y := DockedBorderSize; + end + else begin + X := (ClientWidth + DockedBorderSize) - Z; + Y := DockedBorderSize+1; + end; + Result := Bounds(X, Y, Z, Z); +end; + +function TTBCustomDockableWindow.CalcNCSizes: TPoint; +var + Z: Integer; +begin + if not Docked then begin + Result.X := 0; + Result.Y := 0; + end + else begin + Result.X := DockedBorderSize2; + Result.Y := DockedBorderSize2; + if CurrentDock.FAllowDrag then begin + Z := DragHandleSizes[FCloseButtonWhenDocked, FDragHandleStyle]; + if not(CurrentDock.Position in PositionLeftOrRight) then + Inc(Result.X, Z) + else + Inc(Result.Y, Z); + end; + end; +end; + +procedure TTBCustomDockableWindow.WMNCCalcSize(var Message: TWMNCCalcSize); +var + Z: Integer; +begin + { Doesn't call inherited since it overrides the normal NC sizes } + Message.Result := 0; + if Docked then + with Message.CalcSize_Params^ do begin + InflateRect(rgrc[0], -DockedBorderSize, -DockedBorderSize); + if CurrentDock.FAllowDrag then begin + Z := DragHandleSizes[FCloseButtonWhenDocked, FDragHandleStyle]; + if not(CurrentDock.Position in PositionLeftOrRight) then + Inc(rgrc[0].Left, Z) + else + Inc(rgrc[0].Top, Z); + end; + end; +end; + +procedure TTBCustomDockableWindow.WMSetCursor(var Message: TWMSetCursor); +var + P: TPoint; + R: TRect; + I: Integer; +begin + if Docked and CurrentDock.FAllowDrag and + (Message.CursorWnd = WindowHandle) and + (Smallint(Message.HitTest) = HT_TB2k_Border) and + (DragHandleStyle <> dhNone) then begin + GetCursorPos(P); + GetWindowRect(Handle, R); + if not(CurrentDock.Position in PositionLeftOrRight) then + I := P.X - R.Left + else + I := P.Y - R.Top; + if I < DockedBorderSize + DragHandleSizes[CloseButtonWhenDocked, DragHandleStyle] then begin + SetCursor(LoadCursor(0, IDC_SIZEALL)); + Message.Result := 1; + Exit; + end; + end; + inherited; +end; + +procedure TTBCustomDockableWindow.DrawNCArea(const DrawToDC: Boolean; + const ADC: HDC; const Clip: HRGN); +{ Redraws all the non-client area of the toolbar when it is docked. } +var + DC: HDC; + R: TRect; + VerticalDock: Boolean; + X, Y, Y2, Y3, YO, S, SaveIndex: Integer; + R2, R3, R4: TRect; + P1, P2: TPoint; + Brush: HBRUSH; + Clr: TColorRef; + UsingBackground, B: Boolean; + + procedure DrawRaisedEdge(R: TRect; const FillInterior: Boolean); + const + FillMiddle: array[Boolean] of UINT = (0, BF_MIDDLE); + begin + DrawEdge(DC, R, BDR_RAISEDINNER, BF_RECT or FillMiddle[FillInterior]); + end; + + function CreateCloseButtonBitmap: HBITMAP; + const + Pattern: array[0..15] of Byte = + (0, 0, $CC, 0, $78, 0, $30, 0, $78, 0, $CC, 0, 0, 0, 0, 0); + begin + Result := CreateBitmap(8, 8, 1, 1, @Pattern); + end; + + procedure DrawButtonBitmap(const Bmp: HBITMAP); + var + TempBmp: TBitmap; + begin + TempBmp := TBitmap.Create; + try + TempBmp.Handle := Bmp; + SetTextColor(DC, clBlack); + SetBkColor(DC, clWhite); + SelectObject(DC, GetSysColorBrush(COLOR_BTNTEXT)); + BitBlt(DC, R2.Left, R2.Top, R2.Right - R2.Left, R2.Bottom - R2.Top, + TempBmp.Canvas.Handle, 0, 0, $00E20746 {ROP_DSPDxax}); + finally + TempBmp.Free; + end; + end; + +const + CloseButtonState: array[Boolean] of UINT = (0, DFCS_PUSHED); +begin + if not Docked or not HandleAllocated then Exit; + + if not DrawToDC then + DC := GetWindowDC(Handle) + else + DC := ADC; + try + { Use update region } + if not DrawToDC then + SelectNCUpdateRgn(Handle, DC, Clip); + + { This works around WM_NCPAINT problem described at top of source code } + {no! R := Rect(0, 0, Width, Height);} + GetWindowRect(Handle, R); OffsetRect(R, -R.Left, -R.Top); + + VerticalDock := CurrentDock.Position in PositionLeftOrRight; + + Brush := CreateSolidBrush(ColorToRGB(Color)); + + UsingBackground := CurrentDock.UsingBackground and CurrentDock.FBkgOnToolbars; + + { Border } + if BorderStyle = bsSingle then + DrawRaisedEdge(R, False) + else + FrameRect(DC, R, Brush); + R2 := R; + InflateRect(R2, -1, -1); + if not UsingBackground then + FrameRect(DC, R2, Brush); + + { Draw the Background } + if UsingBackground then begin + R2 := R; + P1 := CurrentDock.ClientToScreen(Point(0, 0)); + P2 := CurrentDock.Parent.ClientToScreen(CurrentDock.BoundsRect.TopLeft); + Dec(R2.Left, Left + CurrentDock.Left + (P1.X-P2.X)); + Dec(R2.Top, Top + CurrentDock.Top + (P1.Y-P2.Y)); + InflateRect(R, -1, -1); + GetWindowRect(Handle, R4); + R3 := ClientRect; + with ClientToScreen(Point(0, 0)) do + OffsetRect(R3, X-R4.Left, Y-R4.Top); + SaveIndex := SaveDC(DC); + IntersectClipRect(DC, R.Left, R.Top, R.Right, R.Bottom); + ExcludeClipRect(DC, R3.Left, R3.Top, R3.Right, R3.Bottom); + CurrentDock.DrawBackground(DC, R2); + RestoreDC(DC, SaveIndex); + end; + + { The drag handle at the left, or top } + if CurrentDock.FAllowDrag then begin + SaveIndex := SaveDC(DC); + if not VerticalDock then + Y2 := ClientHeight + else + Y2 := ClientWidth; + Inc(Y2, DockedBorderSize); + S := DragHandleSizes[FCloseButtonWhenDocked, FDragHandleStyle]; + if FDragHandleStyle <> dhNone then begin + Y3 := Y2; + X := DockedBorderSize + DragHandleXOffsets[FCloseButtonWhenDocked, FDragHandleStyle]; + Y := DockedBorderSize; + YO := Ord(FDragHandleStyle = dhSingle); + if FCloseButtonWhenDocked then begin + if not VerticalDock then + Inc(Y, S - 2) + else + Dec(Y3, S - 2); + end; + Clr := GetSysColor(COLOR_BTNHIGHLIGHT); + for B := False to (FDragHandleStyle = dhDouble) do begin + if not VerticalDock then + R2 := Rect(X, Y+YO, X+3, Y2-YO) + else + R2 := Rect(Y+YO, X, Y3-YO, X+3); + DrawRaisedEdge(R2, True); + if not VerticalDock then + SetPixelV(DC, X, Y2-1-YO, Clr) + else + SetPixelV(DC, Y3-1-YO, X, Clr); + ExcludeClipRect(DC, R2.Left, R2.Top, R2.Right, R2.Bottom); + Inc(X, 3); + end; + end; + if not UsingBackground then begin + if not VerticalDock then + R2 := Rect(DockedBorderSize, DockedBorderSize, + DockedBorderSize+S, Y2) + else + R2 := Rect(DockedBorderSize, DockedBorderSize, + Y2, DockedBorderSize+S); + FillRect(DC, R2, Brush); + end; + RestoreDC(DC, SaveIndex); + { Close button } + if FCloseButtonWhenDocked then begin + R2 := GetDockedCloseButtonRect(VerticalDock); + if FCloseButtonDown then + DrawEdge(DC, R2, BDR_SUNKENOUTER, BF_RECT) + else if FCloseButtonHover then + DrawRaisedEdge(R2, False); + InflateRect(R2, -2, -2); + if FCloseButtonDown then + OffsetRect(R2, 1, 1); + DrawButtonBitmap(CreateCloseButtonBitmap); + end; + end; + + DeleteObject(Brush); + finally + if not DrawToDC then + ReleaseDC(Handle, DC); + end; +end; + +procedure TTBCustomDockableWindow.RedrawNCArea; +begin + { Note: IsWindowVisible is called as an optimization. There's no need to + draw on invisible windows. } + if HandleAllocated and IsWindowVisible(Handle) then + DrawNCArea(False, 0, 0); +end; + +procedure TTBCustomDockableWindow.WMNCPaint(var Message: TMessage); +begin + { Don't call inherited because it overrides the default NC painting } + DrawNCArea(False, 0, HRGN(Message.WParam)); +end; + +procedure DockableWindowNCPaintProc(Wnd: HWND; DC: HDC; AppData: Longint); +begin + with TTBCustomDockableWindow(AppData) do + DrawNCArea(True, DC, 0) +end; + +procedure TTBCustomDockableWindow.WMPrint(var Message: TMessage); +begin + HandleWMPrint(Handle, Message, DockableWindowNCPaintProc, Longint(Self)); +end; + +procedure TTBCustomDockableWindow.WMPrintClient(var Message: TMessage); +begin + HandleWMPrintClient(Self, Message); +end; + +procedure TTBCustomDockableWindow.WMEraseBkgnd(var Message: TWMEraseBkgnd); +var + R, R2, R3: TRect; + P1, P2: TPoint; + SaveIndex: Integer; +begin + if Docked and CurrentDock.UsingBackground and CurrentDock.FBkgOnToolbars then begin + R := ClientRect; + R2 := R; + P1 := CurrentDock.ClientToScreen(Point(0, 0)); + P2 := CurrentDock.Parent.ClientToScreen(CurrentDock.BoundsRect.TopLeft); + Dec(R2.Left, Left + CurrentDock.Left + (P1.X-P2.X)); + Dec(R2.Top, Top + CurrentDock.Top + (P1.Y-P2.Y)); + GetWindowRect(Handle, R3); + with ClientToScreen(Point(0, 0)) do begin + Inc(R2.Left, R3.Left-X); + Inc(R2.Top, R3.Top-Y); + end; + SaveIndex := SaveDC(Message.DC); + IntersectClipRect(Message.DC, R.Left, R.Top, R.Right, R.Bottom); + CurrentDock.DrawBackground(Message.DC, R2); + RestoreDC(Message.DC, SaveIndex); + Message.Result := 1; + end + else + inherited; +end; + +function TTBCustomDockableWindow.GetPalette: HPALETTE; +begin + if Docked then + Result := CurrentDock.GetPalette + else + Result := 0; +end; + +function TTBCustomDockableWindow.PaletteChanged(Foreground: Boolean): Boolean; +begin + Result := inherited PaletteChanged(Foreground); + if Result and not Foreground then begin + { There seems to be a bug in Delphi's palette handling. When the form is + inactive and another window realizes a palette, docked TToolbar97s + weren't getting redrawn. So this workaround code was added. } + InvalidateAll(Self); + end; +end; + +procedure TTBCustomDockableWindow.DrawDraggingOutline(const DC: HDC; + const NewRect, OldRect: PRect; const NewDocking, OldDocking: Boolean); +var + NewSize, OldSize: TSize; +begin + with GetFloatingBorderSize do begin + if NewDocking then NewSize.cx := 1 else NewSize.cx := X; + NewSize.cy := NewSize.cx; + if OldDocking then OldSize.cx := 1 else OldSize.cx := X; + OldSize.cy := OldSize.cx; + end; + DrawHalftoneInvertRect(DC, NewRect, OldRect, NewSize, OldSize); +end; + +procedure TTBCustomDockableWindow.CMColorChanged(var Message: TMessage); +begin + { Make sure non-client area is redrawn } + InvalidateAll(Self); + inherited; { the inherited handler calls Invalidate } +end; + +procedure TTBCustomDockableWindow.CMTextChanged(var Message: TMessage); +begin + inherited; + if Parent is TTBFloatingWindowParent then + TTBFloatingWindowParent(Parent).Caption := Caption; +end; + +procedure TTBCustomDockableWindow.CMVisibleChanged(var Message: TMessage); +begin + if not(csDesigning in ComponentState) and Docked then + CurrentDock.ToolbarVisibilityChanged(Self, False); + inherited; + if Assigned(FOnVisibleChanged) then + FOnVisibleChanged(Self); +end; + +procedure TTBCustomDockableWindow.BeginMoving(const InitX, InitY: Integer); +type + PDockedSize = ^TDockedSize; + TDockedSize = record + Dock: TTBDock; + BoundsRect: TRect; + Size: TPoint; + RowSizes: TList; + end; +const + SplitCursors: array[Boolean] of PChar = (IDC_SIZEWE, IDC_SIZENS); +var + UseSmoothDrag: Boolean; + DockList: TList; + NewDockedSizes: TList; {items are pointers to TDockedSizes} + OriginalDock, MouseOverDock: TTBDock; + MoveRect: TRect; + StartDocking, PreventDocking, PreventFloating, WatchForSplit, SplitVertical: Boolean; + ScreenDC: HDC; + OldCursor: HCURSOR; + NPoint, DPoint: TPoint; + OriginalDockRow, OriginalDockPos: Integer; + FirstPos, LastPos, CurPos: TPoint; + + function FindDockedSize(const ADock: TTBDock): PDockedSize; + var + I: Integer; + begin + for I := 0 to NewDockedSizes.Count-1 do begin + Result := NewDockedSizes[I]; + if Result.Dock = ADock then + Exit; + end; + Result := nil; + end; + + function GetRowOf(const RowSizes: TList; const XY: Integer; + var Before: Boolean): Integer; + { Returns row number of the specified coordinate. Before is set to True if it + was in the top (or left) quarter of the row. } + var + HighestRow, R, CurY, NextY, CurRowSize, EdgeSize: Integer; + FullSizeRow: Boolean; + begin + Before := False; + HighestRow := RowSizes.Count-1; + CurY := 0; + for R := 0 to HighestRow do begin + CurRowSize := Integer(RowSizes[R]); + FullSizeRow := FullSize or (CurRowSize and $10000 <> 0); + CurRowSize := Smallint(CurRowSize); + if CurRowSize = 0 then + Continue; + NextY := CurY + CurRowSize; + if not FullSizeRow then + EdgeSize := CurRowSize div 4 + else + EdgeSize := CurRowSize div 2; + if XY < CurY + EdgeSize then begin + Result := R; + Before := True; + Exit; + end; + if not FullSizeRow and (XY < NextY - EdgeSize) then begin + Result := R; + Exit; + end; + CurY := NextY; + end; + Result := HighestRow+1; + end; + + procedure Dropped; + var + NewDockRow: Integer; + Before: Boolean; + MoveRectClient: TRect; + C: Integer; + DockedSize: PDockedSize; + begin + if MouseOverDock <> nil then begin + DockedSize := FindDockedSize(MouseOverDock); + MoveRectClient := MoveRect; + OffsetRect(MoveRectClient, -DockedSize.BoundsRect.Left, + -DockedSize.BoundsRect.Top); + if not FDragSplitting then begin + if not(MouseOverDock.Position in PositionLeftOrRight) then + C := (MoveRectClient.Top+MoveRectClient.Bottom) div 2 + else + C := (MoveRectClient.Left+MoveRectClient.Right) div 2; + NewDockRow := GetRowOf(DockedSize.RowSizes, C, Before); + if Before then + WatchForSplit := False; + end + else begin + NewDockRow := FDockRow; + Before := False; + end; + if WatchForSplit then begin + if (MouseOverDock <> OriginalDock) or (NewDockRow <> OriginalDockRow) then + WatchForSplit := False + else begin + if not SplitVertical then + C := FirstPos.X - LastPos.X + else + C := FirstPos.Y - LastPos.Y; + if Abs(C) >= 10 then begin + WatchForSplit := False; + FDragSplitting := True; + SetCursor(LoadCursor(0, SplitCursors[SplitVertical])); + end; + end; + end; + FDockRow := NewDockRow; + if not(MouseOverDock.Position in PositionLeftOrRight) then + FDockPos := MoveRectClient.Left + else + FDockPos := MoveRectClient.Top; + Parent := MouseOverDock; + if not FSmoothDragging then + CurrentDock.CommitNewPositions := True; + FInsertRowBefore := Before; + try + CurrentDock.ArrangeToolbars; + finally + FInsertRowBefore := False; + end; + end + else begin + WatchForSplit := False; + FloatingPosition := MoveRect.TopLeft; + Floating := True; + { Make sure it doesn't go completely off the screen } + MoveOnScreen(True); + end; + + { Make sure it's repainted immediately (looks better on really slow + computers when smooth dragging is enabled) } + Update; + end; + + procedure MouseMoved; + var + OldMouseOverDock: TTBDock; + OldMoveRect: TRect; + Pos: TPoint; + + function GetDockRect(Control: TTBDock): TRect; + var + I: Integer; + begin + for I := 0 to NewDockedSizes.Count-1 do + with PDockedSize(NewDockedSizes[I])^ do begin + if Dock <> Control then Continue; + Result := Bounds(Pos.X-MulDiv(Size.X-1, NPoint.X, DPoint.X), + Pos.Y-MulDiv(Size.Y-1, NPoint.Y, DPoint.Y), + Size.X, Size.Y); + Exit; + end; + SetRectEmpty(Result); + end; + + function CheckIfCanDockTo(Control: TTBDock; R: TRect): Boolean; + const + DockSensX = 25; + DockSensY = 25; + var + S, Temp: TRect; + Sens: Integer; + begin + with Control do begin + Result := False; + + InflateRect(R, 3, 3); + S := GetDockRect(Control); + + { Like Office, distribute ~25 pixels of extra dock detection area + to the left side if the toolbar was grabbed at the left, both sides + if the toolbar was grabbed at the middle, or the right side if + toolbar was grabbed at the right. If outside, don't try to dock. } + Sens := MulDiv(DockSensX, NPoint.X, DPoint.X); + if (Pos.X < R.Left-(DockSensX-Sens)) or (Pos.X >= R.Right+Sens) then + Exit; + + { Don't try to dock to the left or right if pointer is above or below + the boundaries of the dock } + if (Control.Position in PositionLeftOrRight) and + ((Pos.Y < R.Top) or (Pos.Y >= R.Bottom)) then + Exit; + + { And also distribute ~25 pixels of extra dock detection area to + the top or bottom side } + Sens := MulDiv(DockSensY, NPoint.Y, DPoint.Y); + if (Pos.Y < R.Top-(DockSensY-Sens)) or (Pos.Y >= R.Bottom+Sens) then + Exit; + + Result := IntersectRect(Temp, R, S); + end; + end; + + var + R, R2: TRect; + I: Integer; + Dock: TTBDock; + Accept: Boolean; + TL, BR: TPoint; + begin + OldMouseOverDock := MouseOverDock; + OldMoveRect := MoveRect; + + GetCursorPos(Pos); + + if FDragSplitting then + MouseOverDock := CurrentDock + else begin + { Check if it can dock } + MouseOverDock := nil; + if StartDocking and not PreventDocking then + for I := 0 to DockList.Count-1 do begin + Dock := DockList[I]; + if CheckIfCanDockTo(Dock, FindDockedSize(Dock).BoundsRect) then begin + MouseOverDock := Dock; + Accept := True; + if Assigned(MouseOverDock.FOnRequestDock) then + MouseOverDock.FOnRequestDock(MouseOverDock, Self, Accept); + if Accept then + Break + else + MouseOverDock := nil; + end; + end; + end; + + { If not docking, clip the point so it doesn't get dragged under the + taskbar } + if MouseOverDock = nil then begin + R := GetRectOfMonitorContainingPoint(Pos, True); + if Pos.X < R.Left then Pos.X := R.Left; + if Pos.X > R.Right then Pos.X := R.Right; + if Pos.Y < R.Top then Pos.Y := R.Top; + if Pos.Y > R.Bottom then Pos.Y := R.Bottom; + end; + + MoveRect := GetDockRect(MouseOverDock); + + { Make sure title bar (or at least part of the toolbar) is still accessible + if it's dragged almost completely off the screen. This prevents the + problem seen in Office 97 where you drag it offscreen so that only the + border is visible, sometimes leaving you no way to move it back short of + resetting the toolbar. } + if MouseOverDock = nil then begin + R2 := GetRectOfMonitorContainingPoint(Pos, True); + R := R2; + with GetFloatingBorderSize do + InflateRect(R, -(X+4), -(Y+4)); + if MoveRect.Bottom < R.Top then + OffsetRect(MoveRect, 0, R.Top-MoveRect.Bottom); + if MoveRect.Top > R.Bottom then + OffsetRect(MoveRect, 0, R.Bottom-MoveRect.Top); + if MoveRect.Right < R.Left then + OffsetRect(MoveRect, R.Left-MoveRect.Right, 0); + if MoveRect.Left > R.Right then + OffsetRect(MoveRect, R.Right-MoveRect.Left, 0); + + GetFloatingNCArea(TL, BR); + I := R2.Top + 4 - TL.Y; + if MoveRect.Top < I then + OffsetRect(MoveRect, 0, I-MoveRect.Top); + end; + + { Empty MoveRect if it's wanting to float but it's not allowed to, and + set the mouse cursor accordingly. } + if PreventFloating and not Assigned(MouseOverDock) then begin + SetRectEmpty(MoveRect); + SetCursor(LoadCursor(0, IDC_NO)); + end + else begin + if FDragSplitting then + SetCursor(LoadCursor(0, SplitCursors[SplitVertical])) + else + SetCursor(OldCursor); + end; + + { Update the dragging outline } + if not UseSmoothDrag then + DrawDraggingOutline(ScreenDC, @MoveRect, @OldMoveRect, MouseOverDock <> nil, + OldMouseOverDock <> nil) + else + if not IsRectEmpty(MoveRect) then + Dropped; + end; + + procedure BuildDockList; + + function AcceptableDock(const D: TTBDock): Boolean; + begin + Result := D.FAllowDrag and (D.Position in DockableTo); + end; + + procedure Recurse(const ParentCtl: TWinControl); + var + D: TTBDockPosition; + I: Integer; + begin + if ContainsControl(ParentCtl) or not ParentCtl.Showing then + Exit; + with ParentCtl do begin + for D := Low(D) to High(D) do + for I := 0 to ParentCtl.ControlCount-1 do + if (Controls[I] is TTBDock) and (TTBDock(Controls[I]).Position = D) then + Recurse(TWinControl(Controls[I])); + for I := 0 to ParentCtl.ControlCount-1 do + if (Controls[I] is TWinControl) and not(Controls[I] is TTBDock) then + Recurse(TWinControl(Controls[I])); + end; + if (ParentCtl is TTBDock) and AcceptableDock(TTBDock(ParentCtl)) and + (DockList.IndexOf(ParentCtl) = -1) then + DockList.Add(ParentCtl); + end; + + var + ParentForm: TTBCustomForm; + DockFormsList: TList; + I, J: Integer; + begin + { Manually add CurrentDock to the DockList first so that it gets priority + over other docks } + if Assigned(CurrentDock) and AcceptableDock(CurrentDock) then + DockList.Add(CurrentDock); + ParentForm := TBGetToolWindowParentForm(Self); + DockFormsList := TList.Create; + try + if Assigned(FDockForms) then begin + for I := 0 to Screen.{$IFDEF JR_D3}CustomFormCount{$ELSE}FormCount{$ENDIF}-1 do begin + J := FDockForms.IndexOf(Screen.{$IFDEF JR_D3}CustomForms{$ELSE}Forms{$ENDIF}[I]); + if (J <> -1) and (FDockForms[J] <> ParentForm) then + DockFormsList.Add(FDockForms[J]); + end; + end; + if Assigned(ParentForm) then + DockFormsList.Insert(0, ParentForm); + for I := 0 to DockFormsList.Count-1 do + Recurse(DockFormsList[I]); + finally + DockFormsList.Free; + end; + end; + +var + Accept, FullSizeRow: Boolean; + R: TRect; + Msg: TMsg; + NewDockedSize: PDockedSize; + I, J, S: Integer; +begin + Accept := False; + SplitVertical := False; + WatchForSplit := False; + OriginalDock := CurrentDock; + OriginalDockRow := FDockRow; + OriginalDockPos := FDockPos; + try + FDragMode := True; + FDragSplitting := False; + if Docked then begin + FDragCanSplit := False; + CurrentDock.CommitNewPositions := True; + CurrentDock.ArrangeToolbars; { needed for WatchForSplit assignment below } + SplitVertical := CurrentDock.Position in PositionLeftOrRight; + WatchForSplit := FDragCanSplit; + end; + DockList := nil; + NewDockedSizes := nil; + try + UseSmoothDrag := FSmoothDrag; + FSmoothDragging := UseSmoothDrag; + + NPoint := Point(InitX, InitY); + { Adjust for non-client area } + if not(Parent is TTBFloatingWindowParent) then begin + GetWindowRect(Handle, R); + R.BottomRight := ClientToScreen(Point(0, 0)); + DPoint := Point(Width-1, Height-1); + end + else begin + GetWindowRect(Parent.Handle, R); + R.BottomRight := Parent.ClientToScreen(Point(0, 0)); + DPoint := Point(Parent.Width-1, Parent.Height-1); + end; + Dec(NPoint.X, R.Left-R.Right); + Dec(NPoint.Y, R.Top-R.Bottom); + + PreventDocking := GetKeyState(VK_CONTROL) < 0; + PreventFloating := DockMode <> dmCanFloat; + + { Build list of all TTBDock's on the form } + DockList := TList.Create; + if DockMode <> dmCannotFloatOrChangeDocks then + BuildDockList + else + if Docked then + DockList.Add(CurrentDock); + + { Ensure positions of each possible dock are committed } + for I := 0 to DockList.Count-1 do + TTBDock(DockList[I]).CommitPositions; + + { Set up potential sizes for each dock type } + NewDockedSizes := TList.Create; + for I := -1 to DockList.Count-1 do begin + New(NewDockedSize); + NewDockedSize.RowSizes := nil; + try + with NewDockedSize^ do begin + if I = -1 then begin + { -1 adds the floating size } + Dock := nil; + SetRectEmpty(BoundsRect); + Size := DoArrange(False, TBGetDockTypeOf(CurrentDock, Floating), True, nil); + AddFloatingNCAreaToSize(Size); + end + else begin + Dock := TTBDock(DockList[I]); + GetWindowRect(Dock.Handle, BoundsRect); + if Dock <> CurrentDock then begin + Size := DoArrange(False, TBGetDockTypeOf(CurrentDock, Floating), False, Dock); + AddDockedNCAreaToSize(Size, Dock.Position in PositionLeftOrRight); + end + else + Size := Point(Width, Height); + end; + end; + if Assigned(NewDockedSize.Dock) then begin + NewDockedSize.RowSizes := TList.Create; + for J := 0 to NewDockedSize.Dock.GetHighestRow(True) do begin + S := Smallint(NewDockedSize.Dock.GetCurrentRowSize(J, FullSizeRow)); + if FullSizeRow then + S := S or $10000; + NewDockedSize.RowSizes.Add(Pointer(S)); + end; + end; + NewDockedSizes.Add(NewDockedSize); + except + NewDockedSize.RowSizes.Free; + Dispose(NewDockedSize); + raise; + end; + end; + + { Before locking, make sure all pending paint messages are processed } + ProcessPaintMessages; + + { Save the original mouse cursor } + OldCursor := GetCursor; + + if not UseSmoothDrag then begin + { This uses LockWindowUpdate to suppress all window updating so the + dragging outlines doesn't sometimes get garbled. (This is safe, and in + fact, is the main purpose of the LockWindowUpdate function) + IMPORTANT! While debugging you might want to enable the 'TB2Dock_DisableLock' + conditional define (see top of the source code). } + {$IFNDEF TB2Dock_DisableLock} + LockWindowUpdate(GetDesktopWindow); + {$ENDIF} + { Get a DC of the entire screen. Works around the window update lock + by specifying DCX_LOCKWINDOWUPDATE. } + ScreenDC := GetDCEx(GetDesktopWindow, 0, + DCX_LOCKWINDOWUPDATE or DCX_CACHE or DCX_WINDOW); + end + else + ScreenDC := 0; + try + SetCapture(Handle); + + { Initialize } + StartDocking := Docked; + MouseOverDock := nil; + SetRectEmpty(MoveRect); + GetCursorPos(FirstPos); + LastPos := FirstPos; + MouseMoved; + StartDocking := True; + + { Stay in message loop until capture is lost. Capture is removed either + by this procedure manually doing it, or by an outside influence (like + a message box or menu popping up) } + while GetCapture = Handle do begin + case Integer(GetMessage(Msg, 0, 0, 0)) of + -1: Break; { if GetMessage failed } + 0: begin + { Repost WM_QUIT messages } + PostQuitMessage(Msg.WParam); + Break; + end; + end; + + case Msg.Message of + WM_KEYDOWN, WM_KEYUP: + { Ignore all keystrokes while dragging. But process Ctrl and Escape } + case Msg.WParam of + VK_CONTROL: + if PreventDocking <> (Msg.Message = WM_KEYDOWN) then begin + PreventDocking := Msg.Message = WM_KEYDOWN; + MouseMoved; + end; + VK_ESCAPE: + Break; + end; + WM_MOUSEMOVE: begin + { Note to self: WM_MOUSEMOVE messages should never be dispatched + here to ensure no hints get shown during the drag process } + CurPos := SmallPointToPoint(TSmallPoint(DWORD(GetMessagePos))); + if (LastPos.X <> CurPos.X) or (LastPos.Y <> CurPos.Y) then begin + MouseMoved; + LastPos := CurPos; + end; + end; + WM_LBUTTONDOWN, WM_LBUTTONDBLCLK: + { Make sure it doesn't begin another loop } + Break; + WM_LBUTTONUP: begin + Accept := True; + Break; + end; + WM_RBUTTONDOWN..WM_MBUTTONDBLCLK: + { Ignore all other mouse up/down messages } + ; + else + TranslateMessage(Msg); + DispatchMessage(Msg); + end; + end; + finally + { Since it sometimes breaks out of the loop without capture being + released } + if GetCapture = Handle then + ReleaseCapture; + + if not UseSmoothDrag then begin + { Hide dragging outline. Since NT will release a window update lock if + another thread comes to the foreground, it has to release the DC + and get a new one for erasing the dragging outline. Otherwise, + the DrawDraggingOutline appears to have no effect when this happens. } + ReleaseDC(GetDesktopWindow, ScreenDC); + ScreenDC := GetDCEx(GetDesktopWindow, 0, + DCX_LOCKWINDOWUPDATE or DCX_CACHE or DCX_WINDOW); + DrawDraggingOutline(ScreenDC, nil, @MoveRect, True, MouseOverDock <> nil); + ReleaseDC(GetDesktopWindow, ScreenDC); + + { Release window update lock } + {$IFNDEF TB2Dock_DisableLock} + LockWindowUpdate(0); + {$ENDIF} + end; + end; + + { Move to new position only if MoveRect isn't empty } + FSmoothDragging := False; + if Accept and not IsRectEmpty(MoveRect) then + { Note: Dropped must be called again after FSmoothDragging is reset to + False so that TTBDock.ArrangeToolbars makes the DockPos changes + permanent } + Dropped; + + { LastDock isn't automatically updated while FSmoothDragging=True, so + update it now that it's back to False } + if FUseLastDock and Assigned(CurrentDock) then + LastDock := CurrentDock; + + { Free FFloatParent if it's no longer the Parent } + if Assigned(FFloatParent) and (Parent <> FFloatParent) then begin + FFloatParent.Free; + FFloatParent := nil; + end; + finally + FSmoothDragging := False; + if not Docked then begin + { If we didn't end up docking, restore the original DockRow & DockPos + values } + FDockRow := OriginalDockRow; + FDockPos := OriginalDockPos; + end; + if Assigned(NewDockedSizes) then begin + for I := NewDockedSizes.Count-1 downto 0 do begin + NewDockedSize := NewDockedSizes[I]; + NewDockedSize.RowSizes.Free; + Dispose(NewDockedSize); + end; + NewDockedSizes.Free; + end; + DockList.Free; + end; + finally + FDragMode := False; + FDragSplitting := False; + end; +end; + +function TTBCustomDockableWindow.ChildControlTransparent(Ctl: TControl): Boolean; +begin + Result := False; +end; + +procedure TTBCustomDockableWindow.ControlExistsAtPos(const P: TPoint; + var ControlExists: Boolean); +var + I: Integer; +begin + for I := 0 to ControlCount-1 do + if not ChildControlTransparent(Controls[I]) and Controls[I].Visible and + PtInRect(Controls[I].BoundsRect, P) then begin + ControlExists := True; + Break; + end; +end; + +procedure TTBCustomDockableWindow.DoubleClick; +begin + if Docked then begin + if DockMode = dmCanFloat then begin + Floating := True; + MoveOnScreen(True); + end; + end + else + if Assigned(LastDock) then + Parent := LastDock + else + if Assigned(DefaultDock) then begin + FDockRow := ForceDockAtTopRow; + FDockPos := ForceDockAtLeftPos; + Parent := DefaultDock; + end; +end; + +function TTBCustomDockableWindow.IsMovable: Boolean; +begin + Result := (Docked and CurrentDock.FAllowDrag) or Floating; +end; + +procedure TTBCustomDockableWindow.MouseDown(Button: TMouseButton; + Shift: TShiftState; X, Y: Integer); +var + P: TPoint; + CtlExists: Boolean; +begin + inherited; + if (Button <> mbLeft) or not IsMovable then + Exit; + { Ignore message if user clicked on a child control } + P := Point(X, Y); + if PtInRect(ClientRect, P) then begin + CtlExists := False; + ControlExistsAtPos(P, CtlExists); + if CtlExists then + Exit; + end; + + if not(ssDouble in Shift) then begin + BeginMoving(X, Y); + MouseUp(mbLeft, [], -1, -1); + end + else + { Handle double click } + DoubleClick; +end; + +procedure TTBCustomDockableWindow.WMNCHitTest(var Message: TWMNCHitTest); +var + P: TPoint; + R: TRect; +begin + inherited; + if Docked then + with Message do begin + P := SmallPointToPoint(Pos); + GetWindowRect(Handle, R); + Dec(P.X, R.Left); Dec(P.Y, R.Top); + if Result <> HTCLIENT then begin + Result := HTNOWHERE; + if FCloseButtonWhenDocked and CurrentDock.FAllowDrag and + PtInRect(GetDockedCloseButtonRect( + TBGetDockTypeOf(CurrentDock, Floating) = dtLeftRight), P) then + Result := HT_TB2k_Close + else + Result := HT_TB2k_Border; + end; + end; +end; + +procedure TTBCustomDockableWindow.WMNCMouseMove(var Message: TWMNCMouseMove); +var + InArea: Boolean; +begin + inherited; + { Note: TME_NONCLIENT was introduced in Windows 98 and 2000 } + if (Win32MajorVersion >= 5) or + (Win32MajorVersion = 4) and (Win32MinorVersion >= 10) then + CallTrackMouseEvent(Handle, TME_LEAVE or $10 {TME_NONCLIENT}); + InArea := Message.HitTest = HT_TB2k_Close; + if FCloseButtonHover <> InArea then begin + FCloseButtonHover := InArea; + RedrawNCArea; + end; +end; + +procedure TTBCustomDockableWindow.WMNCMouseLeave(var Message: TMessage); +begin + if not MouseCapture then + CancelNCHover; + inherited; +end; + +procedure TTBCustomDockableWindow.CMMouseLeave(var Message: TMessage); +begin + inherited; + { On Windows versions that can't send a WM_NCMOUSELEAVE message, trap + CM_MOUSELEAVE to detect when the mouse moves from the non-client area to + another control. } + CancelNCHover; +end; + +procedure TTBCustomDockableWindow.WMMouseMove(var Message: TMessage); +begin + { On Windows versions that can't send a WM_NCMOUSELEAVE message, trap + WM_MOUSEMOVE to detect when the mouse moves from the non-client area to + the client area. + Note: We are overriding WM_MOUSEMOVE instead of MouseMove so that our + processing always gets done first. } + CancelNCHover; + inherited; +end; + +procedure TTBCustomDockableWindow.CancelNCHover; +begin + if FCloseButtonHover then begin + FCloseButtonHover := False; + RedrawNCArea; + end; +end; + +procedure TTBCustomDockableWindow.Close; +var + Accept: Boolean; +begin + Accept := True; + if Assigned(FOnCloseQuery) then + FOnCloseQuery(Self, Accept); + { Did the CloseQuery event return True? } + if Accept then begin + Hide; + if Assigned(FOnClose) then + FOnClose(Self); + end; +end; + +procedure TTBCustomDockableWindow.SetCloseButtonState(Pushed: Boolean); +begin + if FCloseButtonDown <> Pushed then begin + FCloseButtonDown := Pushed; + RedrawNCArea; + end; +end; + +procedure TTBCustomDockableWindow.WMNCLButtonDown(var Message: TWMNCLButtonDown); +var + R, BR: TRect; + P: TPoint; +begin + case Message.HitTest of + HT_TB2k_Close: begin + GetWindowRect(Handle, R); + BR := GetDockedCloseButtonRect( + TBGetDockTypeOf(CurrentDock, Floating) = dtLeftRight); + OffsetRect(BR, R.Left, R.Top); + if CloseButtonLoop(Handle, BR, SetCloseButtonState) then + Close; + end; + HT_TB2k_Border: begin + P := ScreenToClient(SmallPointToPoint(TSmallPoint(GetMessagePos()))); + if IsMovable then + BeginMoving(P.X, P.Y); + end; + else + inherited; + end; +end; + +procedure TTBCustomDockableWindow.WMNCLButtonDblClk(var Message: TWMNCLButtonDblClk); +begin + if Message.HitTest = HT_TB2k_Border then begin + if IsMovable then + DoubleClick; + end + else + inherited; +end; + +procedure TTBCustomDockableWindow.ShowNCContextMenu(const Pos: TSmallPoint); + + {$IFNDEF JR_D5} + { Note: this is identical to TControl.CheckMenuPopup (from Delphi 4), + except where noted. + TControl.CheckMenuPopup is unfortunately 'private', so it can't be called + outside of the Controls unit. } + procedure CheckMenuPopup; + var + Control: TControl; + PopupMenu: TPopupMenu; + begin + if csDesigning in ComponentState then Exit; + Control := Self; + while Control <> nil do + begin + { Added TControlAccess cast because GetPopupMenu is 'protected' } + PopupMenu := TControlAccess(Control).GetPopupMenu; + if (PopupMenu <> nil) then + begin + if not PopupMenu.AutoPopup then Exit; + SendCancelMode(nil); + PopupMenu.PopupComponent := Control; + { Changed the following. LPARAM of WM_NCRBUTTONUP is in screen + coordinates, not client coordinates } + {with ClientToScreen(SmallPointToPoint(Pos)) do + PopupMenu.Popup(X, Y);} + PopupMenu.Popup(Pos.X, Pos.Y); + Exit; + end; + Control := Control.Parent; + end; + end; + {$ENDIF} + +begin + {$IFDEF JR_D5} + { Delphi 5 and later use the WM_CONTEXTMENU message for popup menus } + SendMessage(Handle, WM_CONTEXTMENU, 0, LPARAM(Pos)); + {$ELSE} + CheckMenuPopup; + {$ENDIF} +end; + +procedure TTBCustomDockableWindow.WMNCRButtonUp(var Message: TWMNCRButtonUp); +begin + ShowNCContextMenu(TSmallPoint(TMessage(Message).LParam)); +end; + +{$IFDEF JR_D5} +procedure TTBCustomDockableWindow.WMContextMenu(var Message: TWMContextMenu); +{ Unfortunately TControl.WMContextMenu ignores clicks in the non-client area. + On docked toolbars, we need right clicks on the border, part of the + non-client area, to display the popup menu. The only way I see to have it do + that is to create a new version of WMContextMenu specifically for the + non-client area, and that is what this method is. + Note: This is identical to Delphi 5's TControl.WMContextMenu, except where + noted. } +var + Pt, Temp: TPoint; + Handled: Boolean; + PopupMenu: TPopupMenu; +begin + { Added 'inherited;' here } + inherited; + if Message.Result <> 0 then Exit; + if csDesigning in ComponentState then Exit; + + Pt := SmallPointToPoint(Message.Pos); + if Pt.X < 0 then + Temp := Pt + else + begin + Temp := ScreenToClient(Pt); + { Changed the following. We're only interested in the non-client area } + {if not PtInRect(ClientRect, Temp) then} + if PtInRect(ClientRect, Temp) then + begin + {inherited;} + Exit; + end; + end; + + Handled := False; + DoContextPopup(Temp, Handled); + Message.Result := Ord(Handled); + if Handled then Exit; + + PopupMenu := GetPopupMenu; + if (PopupMenu <> nil) and PopupMenu.AutoPopup then + begin + SendCancelMode(nil); + PopupMenu.PopupComponent := Self; + if Pt.X < 0 then + Pt := ClientToScreen(Point(0,0)); + PopupMenu.Popup(Pt.X, Pt.Y); + Message.Result := 1; + end; + + if Message.Result = 0 then + inherited; +end; +{$ENDIF} + +procedure TTBCustomDockableWindow.GetMinShrinkSize(var AMinimumSize: Integer); +begin +end; + +function TTBCustomDockableWindow.GetFloatingWindowParentClass: TTBFloatingWindowParentClass; +begin + Result := TTBFloatingWindowParent; +end; + +procedure TTBCustomDockableWindow.GetMinMaxSize(var AMinClientWidth, + AMinClientHeight, AMaxClientWidth, AMaxClientHeight: Integer); +begin +end; + +function TTBCustomDockableWindow.GetShrinkMode: TTBShrinkMode; +begin + Result := tbsmNone; +end; + +procedure TTBCustomDockableWindow.ResizeBegin; +begin +end; + +procedure TTBCustomDockableWindow.ResizeTrack(var Rect: TRect; const OrigRect: TRect); +begin +end; + +procedure TTBCustomDockableWindow.ResizeTrackAccept; +begin +end; + +procedure TTBCustomDockableWindow.ResizeEnd; +begin +end; + +procedure TTBCustomDockableWindow.BeginSizing(const ASizeHandle: TTBSizeHandle); +var + UseSmoothDrag, DragX, DragY, ReverseX, ReverseY: Boolean; + MinWidth, MinHeight, MaxWidth, MaxHeight: Integer; + DragRect, OrigDragRect: TRect; + ScreenDC: HDC; + OrigPos, OldPos: TPoint; + + procedure DoResize; + begin + BeginUpdate; + try + ResizeTrackAccept; + Parent.BoundsRect := DragRect; + SetBounds(Left, Top, Parent.ClientWidth, Parent.ClientHeight); + finally + EndUpdate; + end; + + { Make sure it doesn't go completely off the screen } + MoveOnScreen(True); + end; + + procedure MouseMoved; + var + Pos: TPoint; + OldDragRect: TRect; + begin + GetCursorPos(Pos); + { It needs to check if the cursor actually moved since last time. This is + because a call to LockWindowUpdate (apparently) generates a mouse move + message even when mouse hasn't moved. } + if (Pos.X = OldPos.X) and (Pos.Y = OldPos.Y) then Exit; + OldPos := Pos; + + OldDragRect := DragRect; + DragRect := OrigDragRect; + if DragX then begin + if not ReverseX then Inc(DragRect.Right, Pos.X-OrigPos.X) + else Inc(DragRect.Left, Pos.X-OrigPos.X); + end; + if DragY then begin + if not ReverseY then Inc(DragRect.Bottom, Pos.Y-OrigPos.Y) + else Inc(DragRect.Top, Pos.Y-OrigPos.Y); + end; + if DragRect.Right-DragRect.Left < MinWidth then begin + if not ReverseX then DragRect.Right := DragRect.Left + MinWidth + else DragRect.Left := DragRect.Right - MinWidth; + end; + if (MaxWidth > 0) and (DragRect.Right-DragRect.Left > MaxWidth) then begin + if not ReverseX then DragRect.Right := DragRect.Left + MaxWidth + else DragRect.Left := DragRect.Right - MaxWidth; + end; + if DragRect.Bottom-DragRect.Top < MinHeight then begin + if not ReverseY then DragRect.Bottom := DragRect.Top + MinHeight + else DragRect.Top := DragRect.Bottom - MinHeight; + end; + if (MaxHeight > 0) and (DragRect.Bottom-DragRect.Top > MaxHeight) then begin + if not ReverseY then DragRect.Bottom := DragRect.Top + MaxHeight + else DragRect.Top := DragRect.Bottom - MaxHeight; + end; + + ResizeTrack(DragRect, OrigDragRect); + if not UseSmoothDrag then + DrawDraggingOutline(ScreenDC, @DragRect, @OldDragRect, False, False) + else + DoResize; + end; +var + Accept: Boolean; + Msg: TMsg; + R: TRect; +begin + if not Floating then Exit; + + Accept := False; + + UseSmoothDrag := FSmoothDrag; + + MinWidth := 0; + MinHeight := 0; + MaxWidth := 0; + MaxHeight := 0; + GetMinMaxSize(MinWidth, MinHeight, MaxWidth, MaxHeight); + Inc(MinWidth, Parent.Width-Width); + Inc(MinHeight, Parent.Height-Height); + if MaxWidth > 0 then + Inc(MaxWidth, Parent.Width-Width); + if MaxHeight > 0 then + Inc(MaxHeight, Parent.Height-Height); + + DragX := ASizeHandle in [twshLeft, twshRight, twshTopLeft, twshTopRight, + twshBottomLeft, twshBottomRight]; + ReverseX := ASizeHandle in [twshLeft, twshTopLeft, twshBottomLeft]; + DragY := ASizeHandle in [twshTop, twshTopLeft, twshTopRight, twshBottom, + twshBottomLeft, twshBottomRight]; + ReverseY := ASizeHandle in [twshTop, twshTopLeft, twshTopRight]; + + ResizeBegin(ASizeHandle); + try + { Before locking, make sure all pending paint messages are processed } + ProcessPaintMessages; + + if not UseSmoothDrag then begin + { This uses LockWindowUpdate to suppress all window updating so the + dragging outlines doesn't sometimes get garbled. (This is safe, and in + fact, is the main purpose of the LockWindowUpdate function) + IMPORTANT! While debugging you might want to enable the 'TB2Dock_DisableLock' + conditional define (see top of the source code). } + {$IFNDEF TB2Dock_DisableLock} + LockWindowUpdate(GetDesktopWindow); + {$ENDIF} + { Get a DC of the entire screen. Works around the window update lock + by specifying DCX_LOCKWINDOWUPDATE. } + ScreenDC := GetDCEx(GetDesktopWindow, 0, + DCX_LOCKWINDOWUPDATE or DCX_CACHE or DCX_WINDOW); + end + else + ScreenDC := 0; + try + SetCapture(Handle); + if (tbdsResizeClipCursor in FDockableWindowStyles) and + not UsingMultipleMonitors then begin + R := GetRectOfPrimaryMonitor(False); + ClipCursor(@R); + end; + + { Initialize } + OrigDragRect := Parent.BoundsRect; + DragRect := OrigDragRect; + if not UseSmoothDrag then + DrawDraggingOutline(ScreenDC, @DragRect, nil, False, False); + GetCursorPos(OrigPos); + OldPos := OrigPos; + + { Stay in message loop until capture is lost. Capture is removed either + by this procedure manually doing it, or by an outside influence (like + a message box or menu popping up) } + while GetCapture = Handle do begin + case Integer(GetMessage(Msg, 0, 0, 0)) of + -1: Break; { if GetMessage failed } + 0: begin + { Repost WM_QUIT messages } + PostQuitMessage(Msg.WParam); + Break; + end; + end; + + case Msg.Message of + WM_KEYDOWN, WM_KEYUP: + { Ignore all keystrokes while sizing except for Escape } + if Msg.WParam = VK_ESCAPE then + Break; + WM_MOUSEMOVE: + { Note to self: WM_MOUSEMOVE messages should never be dispatched + here to ensure no hints get shown during the drag process } + MouseMoved; + WM_LBUTTONDOWN, WM_LBUTTONDBLCLK: + { Make sure it doesn't begin another loop } + Break; + WM_LBUTTONUP: begin + Accept := True; + Break; + end; + WM_RBUTTONDOWN..WM_MBUTTONDBLCLK: + { Ignore all other mouse up/down messages } + ; + else + TranslateMessage(Msg); + DispatchMessage(Msg); + end; + end; + finally + { Since it sometimes breaks out of the loop without capture being + released } + if GetCapture = Handle then + ReleaseCapture; + ClipCursor(nil); + + if not UseSmoothDrag then begin + { Hide dragging outline. Since NT will release a window update lock if + another thread comes to the foreground, it has to release the DC + and get a new one for erasing the dragging outline. Otherwise, + the DrawDraggingOutline appears to have no effect when this happens. } + ReleaseDC(GetDesktopWindow, ScreenDC); + ScreenDC := GetDCEx(GetDesktopWindow, 0, + DCX_LOCKWINDOWUPDATE or DCX_CACHE or DCX_WINDOW); + DrawDraggingOutline(ScreenDC, nil, @DragRect, False, False); + ReleaseDC(GetDesktopWindow, ScreenDC); + + { Release window update lock } + {$IFNDEF TB2Dock_DisableLock} + LockWindowUpdate(0); + {$ENDIF} + end; + end; + + if not UseSmoothDrag and Accept then + DoResize; + finally + ResizeEnd; + end; +end; + +procedure TTBCustomDockableWindow.DoDockChangingHidden(NewFloating: Boolean; + DockingTo: TTBDock); +begin + if not(csDestroying in ComponentState) and Assigned(FOnDockChangingHidden) then + FOnDockChangingHidden(Self, NewFloating, DockingTo); +end; + +{ TTBCustomDockableWindow - property access methods } + +function TTBCustomDockableWindow.GetNonClientWidth: Integer; +begin + Result := CalcNCSizes.X; +end; + +function TTBCustomDockableWindow.GetNonClientHeight: Integer; +begin + Result := CalcNCSizes.Y; +end; + +function TTBCustomDockableWindow.IsLastDockStored: Boolean; +begin + Result := FCurrentDock = nil; {}{should this be changed to 'Floating'?} +end; + +function TTBCustomDockableWindow.IsWidthAndHeightStored: Boolean; +begin + Result := (CurrentDock = nil) and not Floating; +end; + +procedure TTBCustomDockableWindow.SetCloseButton(Value: Boolean); +begin + if FCloseButton <> Value then begin + FCloseButton := Value; + + { Update the close button's visibility } + if Parent is TTBFloatingWindowParent then + TTBFloatingWindowParent(Parent).RedrawNCArea([twrdCaption, twrdCloseButton]); + end; +end; + +procedure TTBCustomDockableWindow.SetCloseButtonWhenDocked(Value: Boolean); +begin + if FCloseButtonWhenDocked <> Value then begin + FCloseButtonWhenDocked := Value; + if Docked then + RecalcNCArea(Self); + end; +end; + +procedure TTBCustomDockableWindow.SetDefaultDock(Value: TTBDock); +begin + if FDefaultDock <> Value then begin + FDefaultDock := Value; + if Assigned(Value) then + Value.FreeNotification(Self); + end; +end; + +procedure TTBCustomDockableWindow.SetCurrentDock(Value: TTBDock); +begin + if not(csLoading in ComponentState) then begin + if Assigned(Value) then + Parent := Value + else + Parent := TBValidToolWindowParentForm(Self); + end; +end; + +procedure TTBCustomDockableWindow.SetDockPos(Value: Integer); +begin + FDockPos := Value; + if Docked then + CurrentDock.ArrangeToolbars; +end; + +procedure TTBCustomDockableWindow.SetDockRow(Value: Integer); +begin + FDockRow := Value; + if Docked then + CurrentDock.ArrangeToolbars; +end; + +procedure TTBCustomDockableWindow.SetAutoResize(Value: Boolean); +begin + if FAutoResize <> Value then begin + FAutoResize := Value; + if Value then + Arrange; + end; +end; + +procedure TTBCustomDockableWindow.SetBorderStyle(Value: TBorderStyle); +begin + if FBorderStyle <> Value then begin + FBorderStyle := Value; + if Docked then + RecalcNCArea(Self); + end; +end; + +procedure TTBCustomDockableWindow.SetDragHandleStyle(Value: TTBDragHandleStyle); +begin + if FDragHandleStyle <> Value then begin + FDragHandleStyle := Value; + if Docked then + RecalcNCArea(Self); + end; +end; + +procedure TTBCustomDockableWindow.SetFloating(Value: Boolean); +var + ParentFrm: TTBCustomForm; + NewFloatParent: TTBFloatingWindowParent; +begin + if FFloating <> Value then begin + if Value and not(csDesigning in ComponentState) then begin + ParentFrm := TBValidToolWindowParentForm(Self); + if (FFloatParent = nil) or (FFloatParent.FParentForm <> ParentFrm) then begin + NewFloatParent := GetFloatingWindowParentClass.Create(nil); + try + with NewFloatParent do begin + TWinControl(FParentForm) := ParentFrm; + FDockableWindow := Self; + Name := Format('NBFloatingWindowParent_%.8x', [Longint(NewFloatParent)]); + { ^ Must assign a unique name. In previous versions, reading in + components at run-time that had no name caused them to get assigned + names like "_1" because a component with no name -- the + TTBFloatingWindowParent form -- already existed. } + Caption := Self.Caption; + BorderStyle := bsToolWindow; + SetBounds(0, 0, (Width-ClientWidth) + Self.ClientWidth, + (Height-ClientHeight) + Self.ClientHeight); + ShowHint := True; + Visible := True; + end; + except + NewFloatParent.Free; + raise; + end; + FFloatParent := NewFloatParent; + end; + ParentFrm.FreeNotification(Self); + Parent := FFloatParent; + SetBounds(0, 0, Width, Height); + end + else + Parent := TBValidToolWindowParentForm(Self); + end; +end; + +procedure TTBCustomDockableWindow.SetFloatingMode(Value: TTBFloatingMode); +begin + if FFloatingMode <> Value then begin + FFloatingMode := Value; + if HandleAllocated then + Perform(CM_SHOWINGCHANGED, 0, 0); + end; +end; + +procedure TTBCustomDockableWindow.SetFloatingPosition(Value: TPoint); +begin + FFloatingPosition := Value; + if Floating and Assigned(Parent) then + Parent.SetBounds(Value.X, Value.Y, Parent.Width, Parent.Height); +end; + +procedure TTBCustomDockableWindow.SetFullSize(Value: Boolean); +begin + if FFullSize <> Value then begin + FFullSize := Value; + if Docked then + CurrentDock.ArrangeToolbars; + end; +end; + +procedure TTBCustomDockableWindow.SetLastDock(Value: TTBDock); +begin + if FUseLastDock and Assigned(FCurrentDock) then + { When docked, LastDock must be equal to DockedTo } + Value := FCurrentDock; + if FLastDock <> Value then begin + if Assigned(FLastDock) and (FLastDock <> Parent) then + FLastDock.ChangeDockList(False, Self); + FLastDock := Value; + if Assigned(Value) then begin + FUseLastDock := True; + Value.FreeNotification(Self); + Value.ChangeDockList(True, Self); + end; + end; +end; + +procedure TTBCustomDockableWindow.SetResizable(Value: Boolean); +begin + if FResizable <> Value then begin + FResizable := Value; + if Floating and (Parent is TTBFloatingWindowParent) then begin + { Recreate the window handle because Resizable affects whether the + tool window is created with a WS_THICKFRAME style } + TTBFloatingWindowParent(Parent).RecreateWnd; + end; + end; +end; + +procedure TTBCustomDockableWindow.SetShowCaption(Value: Boolean); +begin + if FShowCaption <> Value then begin + FShowCaption := Value; + if Floating then begin + { Recalculate FloatingWindowParent's NC area, and resize the toolbar + accordingly } + RecalcNCArea(Parent); + Arrange; + end; + end; +end; + +procedure TTBCustomDockableWindow.SetStretch(Value: Boolean); +begin + if FStretch <> Value then begin + FStretch := Value; + if Docked then + CurrentDock.ArrangeToolbars; + end; +end; + +procedure TTBCustomDockableWindow.SetUseLastDock(Value: Boolean); +begin + if FUseLastDock <> Value then begin + FUseLastDock := Value; + if not Value then + LastDock := nil + else + LastDock := FCurrentDock; + end; +end; + +(*function TTBCustomDockableWindow.GetVersion: TToolbar97Version; +begin + Result := Toolbar97VersionPropText; +end; + +procedure TTBCustomDockableWindow.SetVersion(const Value: TToolbar97Version); +begin + { write method required for the property to show up in Object Inspector } +end;*) + + +{ TTBBackground } + +type + PNotifyEvent = ^TNotifyEvent; + +constructor TTBBackground.Create(AOwner: TComponent); +begin + inherited; + FBkColor := clBtnFace; + FBitmap := TBitmap.Create; + FBitmap.OnChange := BitmapChanged; +end; + +destructor TTBBackground.Destroy; +var + I: Integer; +begin + inherited; + FBitmapCache.Free; + FBitmap.Free; + if Assigned(FNotifyList) then begin + for I := FNotifyList.Count-1 downto 0 do + Dispose(PNotifyEvent(FNotifyList[I])); + FNotifyList.Free; + end; +end; + +procedure TTBBackground.BitmapChanged(Sender: TObject); +var + I: Integer; +begin + { Erase the cache and notify } + FBitmapCache.Free; + FBitmapCache := nil; + if Assigned(FNotifyList) then + for I := 0 to FNotifyList.Count-1 do + PNotifyEvent(FNotifyList[I])^(Self); +end; + +procedure TTBBackground.Draw(DC: HDC; const DrawRect: TRect); +var + UseBmp: TBitmap; + R2: TRect; + SaveIndex: Integer; + DC2: HDC; + Brush: HBRUSH; + P: TPoint; +begin + if FBitmapCache = nil then begin + FBitmapCache := TBitmap.Create; + FBitmapCache.Palette := CopyPalette(FBitmap.Palette); + FBitmapCache.Width := FBitmap.Width; + FBitmapCache.Height := FBitmap.Height; + if not FTransparent then begin + { Copy from a possible DIB to our DDB } + BitBlt(FBitmapCache.Canvas.Handle, 0, 0, FBitmapCache.Width, + FBitmapCache.Height, FBitmap.Canvas.Handle, 0, 0, SRCCOPY); + end + else begin + with FBitmapCache do begin + Canvas.Brush.Color := FBkColor; + R2 := Rect(0, 0, Width, Height); + Canvas.BrushCopy(R2, FBitmap, R2, + FBitmap.Canvas.Pixels[0, Height-1] or $02000000); + end; + end; + FBitmap.Dormant; + end; + UseBmp := FBitmapCache; + + DC2 := 0; + SaveIndex := SaveDC(DC); + try + if UseBmp.Palette <> 0 then begin + SelectPalette(DC, UseBmp.Palette, True); + RealizePalette(DC); + end; + { Note: versions of Toolbar97 prior to 1.68 used 'UseBmp.Canvas.Handle' + instead of DC2 in the BitBlt call. This was changed because there + seems to be a bug in D2/BCB1's Graphics.pas: if you called + .Background.LoadFromFile() twice the background + would not be shown. } + if (UseBmp.Width = 8) and (UseBmp.Height = 8) then begin + { Use pattern brushes to draw 8x8 bitmaps. + Note: Win9x can't use bitmaps <8x8 in size for pattern brushes } + Brush := CreatePatternBrush(UseBmp.Handle); + GetWindowOrgEx(DC, P); + SetBrushOrgEx(DC, DrawRect.Left - P.X, DrawRect.Top - P.Y, nil); + FillRect(DC, DrawRect, Brush); + DeleteObject(Brush); + end + else begin + { BitBlt is faster than pattern brushes on large bitmaps } + DC2 := CreateCompatibleDC(DC); + SelectObject(DC2, UseBmp.Handle); + R2 := DrawRect; + while R2.Left < R2.Right do begin + while R2.Top < R2.Bottom do begin + BitBlt(DC, R2.Left, R2.Top, UseBmp.Width, UseBmp.Height, + DC2, 0, 0, SRCCOPY); + Inc(R2.Top, UseBmp.Height); + end; + R2.Top := DrawRect.Top; + Inc(R2.Left, UseBmp.Width); + end; + end; + finally + if DC2 <> 0 then + DeleteDC(DC2); + { Restore the palette and brush origin back } + RestoreDC(DC, SaveIndex); + end; +end; + +function TTBBackground.GetPalette: HPALETTE; +begin + Result := FBitmap.Palette; +end; + +procedure TTBBackground.SysColorChanged; +begin + if FTransparent and (FBkColor < 0) then + BitmapChanged(nil); +end; + +function TTBBackground.UsingBackground: Boolean; +begin + Result := (FBitmap.Width <> 0) and (FBitmap.Height <> 0); +end; + +procedure TTBBackground.RegisterChanges(Proc: TNotifyEvent); +var + I: Integer; + P: PNotifyEvent; +begin + if FNotifyList = nil then + FNotifyList := TList.Create; + for I := 0 to FNotifyList.Count-1 do begin + P := FNotifyList[I]; + if (TMethod(P^).Code = TMethod(Proc).Code) and + (TMethod(P^).Data = TMethod(Proc).Data) then + Exit; + end; + FNotifyList.Expand; + New(P); + P^ := Proc; + FNotifyList.Add(P); +end; + +procedure TTBBackground.UnregisterChanges(Proc: TNotifyEvent); +var + I: Integer; + P: PNotifyEvent; +begin + if FNotifyList = nil then + Exit; + for I := 0 to FNotifyList.Count-1 do begin + P := FNotifyList[I]; + if (TMethod(P^).Code = TMethod(Proc).Code) and + (TMethod(P^).Data = TMethod(Proc).Data) then begin + FNotifyList.Delete(I); + Dispose(P); + Break; + end; + end; +end; + +procedure TTBBackground.SetBkColor(Value: TColor); +begin + if FBkColor <> Value then begin + FBkColor := Value; + if FTransparent then + BitmapChanged(nil); + end; +end; + +procedure TTBBackground.SetBitmap(Value: TBitmap); +begin + FBitmap.Assign(Value); +end; + +procedure TTBBackground.SetTransparent(Value: Boolean); +begin + if FTransparent <> Value then begin + FTransparent := Value; + BitmapChanged(nil); + end; +end; + + +{ Global procedures } + +procedure TBCustomLoadPositions(const OwnerComponent: TComponent; + const ReadIntProc: TTBPositionReadIntProc; + const ReadStringProc: TTBPositionReadStringProc; const ExtraData: Pointer); +var + Rev: Integer; + + function FindDock(AName: String): TTBDock; + var + I: Integer; + begin + Result := nil; + for I := 0 to OwnerComponent.ComponentCount-1 do + if (OwnerComponent.Components[I] is TTBDock) and + (CompareText(OwnerComponent.Components[I].Name, AName) = 0) then begin + Result := TTBDock(OwnerComponent.Components[I]); + Break; + end; + end; + + procedure ReadValues(const Toolbar: TTBCustomDockableWindow; const NewDock: TTBDock); + var + Pos: TPoint; + Data: TTBReadPositionData; + LastDockName: String; + ADock: TTBDock; + begin + with Toolbar do begin + DockRow := ReadIntProc(Name, rvDockRow, DockRow, ExtraData); + DockPos := ReadIntProc(Name, rvDockPos, DockPos, ExtraData); + Pos.X := ReadIntProc(Name, rvFloatLeft, 0, ExtraData); + Pos.Y := ReadIntProc(Name, rvFloatTop, 0, ExtraData); + @Data.ReadIntProc := @ReadIntProc; + @Data.ReadStringProc := @ReadStringProc; + Data.ExtraData := ExtraData; + ReadPositionData(Data); + FloatingPosition := Pos; + if Assigned(NewDock) then + Parent := NewDock + else begin + //Parent := Form; + Floating := True; + MoveOnScreen(True); + if (Rev >= 3) and FUseLastDock then begin + LastDockName := ReadStringProc(Name, rvLastDock, '', ExtraData); + if LastDockName <> '' then begin + ADock := FindDock(LastDockName); + if Assigned(ADock) then + LastDock := ADock; + end; + end; + end; + Arrange; + DoneReadingPositionData(Data); + end; + end; + +var + DocksDisabled: TList; + I: Integer; + ToolWindow: TComponent; + ADock: TTBDock; + DockedToName: String; +begin + DocksDisabled := TList.Create; + try + with OwnerComponent do + for I := 0 to ComponentCount-1 do + if Components[I] is TTBDock then begin + TTBDock(Components[I]).BeginUpdate; + DocksDisabled.Add(Components[I]); + end; + + for I := 0 to OwnerComponent.ComponentCount-1 do begin + ToolWindow := OwnerComponent.Components[I]; + if ToolWindow is TTBCustomDockableWindow then + with TTBCustomDockableWindow(ToolWindow) do begin + {}{should skip over toolbars that are neither Docked nor Floating } + if Name = '' then + raise Exception.Create(STBToolWinNameNotSet); + Rev := ReadIntProc(Name, rvRev, 0, ExtraData); + if Rev = 2000 then begin + Visible := ReadIntProc(Name, rvVisible, Ord(Visible), ExtraData) <> 0; + DockedToName := ReadStringProc(Name, rvDockedTo, '', ExtraData); + if DockedToName <> '' then begin + if DockedToName <> rdDockedToFloating then begin + ADock := FindDock(DockedToName); + if (ADock <> nil) and (ADock.FAllowDrag) then + ReadValues(TTBCustomDockableWindow(ToolWindow), ADock); + end + else + ReadValues(TTBCustomDockableWindow(ToolWindow), nil); + end; + end; + end; + end; + finally + for I := DocksDisabled.Count-1 downto 0 do + TTBDock(DocksDisabled[I]).EndUpdate; + DocksDisabled.Free; + end; +end; + +procedure TBCustomSavePositions(const OwnerComponent: TComponent; + const WriteIntProc: TTBPositionWriteIntProc; + const WriteStringProc: TTBPositionWriteStringProc; const ExtraData: Pointer); +var + I: Integer; + N, L: String; + Data: TTBWritePositionData; +begin + for I := 0 to OwnerComponent.ComponentCount-1 do + if OwnerComponent.Components[I] is TTBCustomDockableWindow then + with TTBCustomDockableWindow(OwnerComponent.Components[I]) do begin + if Name = '' then + raise Exception.Create(STBToolwinNameNotSet); + if Floating then + N := rdDockedToFloating + else if Docked then begin + if CurrentDock.FAllowDrag then begin + N := CurrentDock.Name; + if N = '' then + raise Exception.Create(STBToolwinDockedToNameNotSet); + end + else + N := ''; + end + else + Continue; { skip if it's neither floating nor docked } + L := ''; + if Assigned(FLastDock) then + L := FLastDock.Name; + WriteIntProc(Name, rvRev, rdCurrentRev, ExtraData); + WriteIntProc(Name, rvVisible, Ord(Visible), ExtraData); + WriteStringProc(Name, rvDockedTo, N, ExtraData); + WriteStringProc(Name, rvLastDock, L, ExtraData); + WriteIntProc(Name, rvDockRow, FDockRow, ExtraData); + WriteIntProc(Name, rvDockPos, FDockPos, ExtraData); + WriteIntProc(Name, rvFloatLeft, FFloatingPosition.X, ExtraData); + WriteIntProc(Name, rvFloatTop, FFloatingPosition.Y, ExtraData); + @Data.WriteIntProc := @WriteIntProc; + @Data.WriteStringProc := @WriteStringProc; + Data.ExtraData := ExtraData; + WritePositionData(Data); + end; +end; + +type + PIniReadWriteData = ^TIniReadWriteData; + TIniReadWriteData = record + IniFile: TIniFile; + SectionNamePrefix: String; + end; + +function IniReadInt(const ToolbarName, Value: String; const Default: Longint; + const ExtraData: Pointer): Longint; far; +begin + Result := PIniReadWriteData(ExtraData).IniFile.ReadInteger( + PIniReadWriteData(ExtraData).SectionNamePrefix + ToolbarName, Value, Default); +end; +function IniReadString(const ToolbarName, Value, Default: String; + const ExtraData: Pointer): String; far; +begin + Result := PIniReadWriteData(ExtraData).IniFile.ReadString( + PIniReadWriteData(ExtraData).SectionNamePrefix + ToolbarName, Value, Default); +end; +procedure IniWriteInt(const ToolbarName, Value: String; const Data: Longint; + const ExtraData: Pointer); far; +begin + PIniReadWriteData(ExtraData).IniFile.WriteInteger( + PIniReadWriteData(ExtraData).SectionNamePrefix + ToolbarName, Value, Data); +end; +procedure IniWriteString(const ToolbarName, Value, Data: String; + const ExtraData: Pointer); far; +begin + PIniReadWriteData(ExtraData).IniFile.WriteString( + PIniReadWriteData(ExtraData).SectionNamePrefix + ToolbarName, Value, Data); +end; + +procedure TBIniLoadPositions(const OwnerComponent: TComponent; + const Filename, SectionNamePrefix: String); +var + Data: TIniReadWriteData; +begin + Data.IniFile := TIniFile.Create(Filename); + try + Data.SectionNamePrefix := SectionNamePrefix; + TBCustomLoadPositions(OwnerComponent, IniReadInt, IniReadString, @Data); + finally + Data.IniFile.Free; + end; +end; + +procedure TBIniSavePositions(const OwnerComponent: TComponent; + const Filename, SectionNamePrefix: String); +var + Data: TIniReadWriteData; +begin + Data.IniFile := TIniFile.Create(Filename); + try + Data.SectionNamePrefix := SectionNamePrefix; + TBCustomSavePositions(OwnerComponent, IniWriteInt, IniWriteString, @Data); + finally + Data.IniFile.Free; + end; +end; + +function RegReadInt(const ToolbarName, Value: String; const Default: Longint; + const ExtraData: Pointer): Longint; far; +begin + Result := TRegIniFile(ExtraData).ReadInteger(ToolbarName, Value, Default); +end; +function RegReadString(const ToolbarName, Value, Default: String; + const ExtraData: Pointer): String; far; +begin + Result := TRegIniFile(ExtraData).ReadString(ToolbarName, Value, Default); +end; +procedure RegWriteInt(const ToolbarName, Value: String; const Data: Longint; + const ExtraData: Pointer); far; +begin + TRegIniFile(ExtraData).WriteInteger(ToolbarName, Value, Data); +end; +procedure RegWriteString(const ToolbarName, Value, Data: String; + const ExtraData: Pointer); far; +begin + TRegIniFile(ExtraData).WriteString(ToolbarName, Value, Data); +end; + +procedure TBRegLoadPositions(const OwnerComponent: TComponent; + const RootKey: DWORD; const BaseRegistryKey: String); +var + Reg: TRegIniFile; +begin + Reg := TRegIniFile.Create(''); + try + Reg.RootKey := RootKey; + Reg.OpenKey(BaseRegistryKey, True); { assigning to RootKey resets the current key } + TBCustomLoadPositions(OwnerComponent, RegReadInt, RegReadString, Reg); + finally + Reg.Free; + end; +end; + +procedure TBRegSavePositions(const OwnerComponent: TComponent; + const RootKey: DWORD; const BaseRegistryKey: String); +var + Reg: TRegIniFile; +begin + Reg := TRegIniFile.Create(''); + try + Reg.RootKey := RootKey; + Reg.OpenKey(BaseRegistryKey, True); { assigning to RootKey resets the current key } + TBCustomSavePositions(OwnerComponent, RegWriteInt, RegWriteString, Reg); + finally + Reg.Free; + end; +end; + +end. diff --git a/official/2.1.6+2.1.beta1/Source/TB2DsgnConvertOptions.dfm b/official/2.1.6+2.1.beta1/Source/TB2DsgnConvertOptions.dfm new file mode 100644 index 0000000..9d5ad45 Binary files /dev/null and b/official/2.1.6+2.1.beta1/Source/TB2DsgnConvertOptions.dfm differ diff --git a/official/2.1.6+2.1.beta1/Source/TB2DsgnConvertOptions.dfm.txt b/official/2.1.6+2.1.beta1/Source/TB2DsgnConvertOptions.dfm.txt new file mode 100644 index 0000000..a1b062f --- /dev/null +++ b/official/2.1.6+2.1.beta1/Source/TB2DsgnConvertOptions.dfm.txt @@ -0,0 +1,65 @@ +object TBConvertOptionsForm: TTBConvertOptionsForm + Left = 225 + Top = 133 + BorderIcons = [biSystemMenu, biMinimize] + BorderStyle = bsDialog + Caption = 'Convert Menu' + ClientHeight = 90 + ClientWidth = 249 + Color = clBtnFace + Font.Charset = DEFAULT_CHARSET + Font.Color = clWindowText + Font.Height = -11 + Font.Name = 'MS Sans Serif' + Font.Style = [] + OldCreateOrder = False + Position = poScreenCenter + PixelsPerInch = 96 + TextHeight = 13 + object Label1: TLabel + Left = 8 + Top = 8 + Width = 81 + Height = 13 + Caption = '&Menu to convert:' + FocusControl = MenuCombo + end + object MenuCombo: TComboBox + Left = 8 + Top = 24 + Width = 233 + Height = 21 + Style = csDropDownList + ItemHeight = 13 + TabOrder = 0 + end + object ConvertButton: TButton + Left = 8 + Top = 57 + Width = 73 + Height = 23 + Caption = '&Convert' + Default = True + ModalResult = 1 + TabOrder = 1 + end + object HelpButton: TButton + Left = 168 + Top = 57 + Width = 73 + Height = 23 + Caption = '&Help' + TabOrder = 2 + OnClick = HelpButtonClick + end + object Button1: TButton + Left = 88 + Top = 57 + Width = 73 + Height = 23 + Cancel = True + Caption = 'Cancel' + ModalResult = 2 + TabOrder = 3 + end +end diff --git a/official/2.1.6+2.1.beta1/Source/TB2DsgnConvertOptions.pas b/official/2.1.6+2.1.beta1/Source/TB2DsgnConvertOptions.pas new file mode 100644 index 0000000..5c47a46 --- /dev/null +++ b/official/2.1.6+2.1.beta1/Source/TB2DsgnConvertOptions.pas @@ -0,0 +1,67 @@ +unit TB2DsgnConvertOptions; + +{ + Toolbar2000 + Copyright (C) 1998-2005 by Jordan Russell + All rights reserved. + + The contents of this file are subject to the "Toolbar2000 License"; you may + not use or distribute this file except in compliance with the + "Toolbar2000 License". A copy of the "Toolbar2000 License" may be found in + TB2k-LICENSE.txt or at: + http://www.jrsoftware.org/files/tb2k/TB2k-LICENSE.txt + + Alternatively, the contents of this file may be used under the terms of the + GNU General Public License (the "GPL"), in which case the provisions of the + GPL are applicable instead of those in the "Toolbar2000 License". A copy of + the GPL may be found in GPL-LICENSE.txt or at: + http://www.jrsoftware.org/files/tb2k/GPL-LICENSE.txt + If you wish to allow use of your version of this file only under the terms of + the GPL and not to allow others to use your version of this file under the + "Toolbar2000 License", indicate your decision by deleting the provisions + above and replace them with the notice and other provisions required by the + GPL. If you do not delete the provisions above, a recipient may use your + version of this file under either the "Toolbar2000 License" or the GPL. + + $jrsoftware: tb2k/Source/TB2DsgnConvertOptions.pas,v 1.6 2005/01/06 03:56:50 jr Exp $ +} + +interface + +uses + Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, + StdCtrls; + +type + TTBConvertOptionsForm = class(TForm) + MenuCombo: TComboBox; + Label1: TLabel; + ConvertButton: TButton; + HelpButton: TButton; + Button1: TButton; + procedure HelpButtonClick(Sender: TObject); + private + { Private declarations } + public + { Public declarations } + end; + +implementation + +{$R *.DFM} + +procedure TTBConvertOptionsForm.HelpButtonClick(Sender: TObject); +const + SMsg1 = 'This will import the contents of a TMainMenu or TPopupMenu ' + + 'component on the form.'#13#10#13#10 + + 'The new items will take the names of the old menu ' + + 'items. The old menu items will have "_OLD" appended to the end of ' + + 'their names.'#13#10#13#10 + + 'After the conversion process completes, you should verify that ' + + 'everything was copied correctly. Afterward, you may delete the ' + + 'old menu component.'; +begin + Application.MessageBox(SMsg1, 'Convert Help', MB_OK or MB_ICONINFORMATION); +end; + +end. diff --git a/official/2.1.6+2.1.beta1/Source/TB2DsgnConverter.dfm b/official/2.1.6+2.1.beta1/Source/TB2DsgnConverter.dfm new file mode 100644 index 0000000..f684c17 Binary files /dev/null and b/official/2.1.6+2.1.beta1/Source/TB2DsgnConverter.dfm differ diff --git a/official/2.1.6+2.1.beta1/Source/TB2DsgnConverter.dfm.txt b/official/2.1.6+2.1.beta1/Source/TB2DsgnConverter.dfm.txt new file mode 100644 index 0000000..7d2cbaf --- /dev/null +++ b/official/2.1.6+2.1.beta1/Source/TB2DsgnConverter.dfm.txt @@ -0,0 +1,51 @@ +object TBConverterForm: TTBConverterForm + Left = 200 + Top = 104 + AutoScroll = False + Caption = 'Conversion Status' + ClientHeight = 218 + ClientWidth = 425 + Color = clBtnFace + Font.Charset = DEFAULT_CHARSET + Font.Color = clWindowText + Font.Height = -11 + Font.Name = 'MS Sans Serif' + Font.Style = [] + OldCreateOrder = True + Position = poScreenCenter + OnClose = FormClose + PixelsPerInch = 96 + TextHeight = 13 + object MessageList: TListBox + Left = 8 + Top = 8 + Width = 409 + Height = 169 + Anchors = [akLeft, akTop, akRight, akBottom] + ItemHeight = 13 + TabOrder = 0 + end + object CloseButton: TButton + Left = 176 + Top = 185 + Width = 73 + Height = 23 + Anchors = [akRight, akBottom] + Cancel = True + Caption = '&Close' + Enabled = False + TabOrder = 1 + OnClick = CloseButtonClick + end + object CopyButton: TButton + Left = 256 + Top = 185 + Width = 161 + Height = 23 + Anchors = [akRight, akBottom] + Caption = 'C&opy Messages to Clipboard' + Enabled = False + TabOrder = 2 + OnClick = CopyButtonClick + end +end diff --git a/official/2.1.6+2.1.beta1/Source/TB2DsgnConverter.pas b/official/2.1.6+2.1.beta1/Source/TB2DsgnConverter.pas new file mode 100644 index 0000000..e1a2456 --- /dev/null +++ b/official/2.1.6+2.1.beta1/Source/TB2DsgnConverter.pas @@ -0,0 +1,217 @@ +unit TB2DsgnConverter; + +{ + Toolbar2000 + Copyright (C) 1998-2005 by Jordan Russell + All rights reserved. + + The contents of this file are subject to the "Toolbar2000 License"; you may + not use or distribute this file except in compliance with the + "Toolbar2000 License". A copy of the "Toolbar2000 License" may be found in + TB2k-LICENSE.txt or at: + http://www.jrsoftware.org/files/tb2k/TB2k-LICENSE.txt + + Alternatively, the contents of this file may be used under the terms of the + GNU General Public License (the "GPL"), in which case the provisions of the + GPL are applicable instead of those in the "Toolbar2000 License". A copy of + the GPL may be found in GPL-LICENSE.txt or at: + http://www.jrsoftware.org/files/tb2k/GPL-LICENSE.txt + If you wish to allow use of your version of this file only under the terms of + the GPL and not to allow others to use your version of this file under the + "Toolbar2000 License", indicate your decision by deleting the provisions + above and replace them with the notice and other provisions required by the + GPL. If you do not delete the provisions above, a recipient may use your + version of this file under either the "Toolbar2000 License" or the GPL. + + $jrsoftware: tb2k/Source/TB2DsgnConverter.pas,v 1.16 2005/01/06 03:56:50 jr Exp $ +} + +interface + +{$I TB2Ver.inc} + +uses + Windows, SysUtils, Classes, Controls, Forms, Menus, StdCtrls, + TB2Item; + +type + TTBConverterForm = class(TForm) + MessageList: TListBox; + CloseButton: TButton; + CopyButton: TButton; + procedure CloseButtonClick(Sender: TObject); + procedure CopyButtonClick(Sender: TObject); + procedure FormClose(Sender: TObject; var Action: TCloseAction); + end; + +procedure DoConvert(const ParentItem: TTBCustomItem; const Owner: TComponent); + +implementation + +{$R *.DFM} + +uses + Clipbrd, TB2DsgnConvertOptions; + +procedure DoConvert(const ParentItem: TTBCustomItem; const Owner: TComponent); +const + SPropNotTransferred = 'Warning: %s property not transferred on ''%s''.'; +var + ConverterForm: TTBConverterForm; + + procedure Log(const S: String); + begin + ConverterForm.MessageList.Items.Add(S); + ConverterForm.MessageList.TopIndex := ConverterForm.MessageList.Items.Count-1; + ConverterForm.Update; + end; + + procedure Recurse(MenuItem: TMenuItem; TBItem: TTBCustomItem); + var + I: Integer; + Src: TMenuItem; + IsSep, IsSubmenu: Boolean; + Dst: TTBCustomItem; + N: String; + begin + for I := 0 to MenuItem.Count-1 do begin + Src := MenuItem[I]; + IsSep := (Src.Caption = '-'); + IsSubmenu := False; + if not IsSep then begin + if Src.Count > 0 then + IsSubmenu := True; + if not IsSubmenu then + Dst := TTBItem.Create(Owner) + else + Dst := TTBSubmenuItem.Create(Owner); + Dst.Action := Src.Action; + {$IFDEF JR_D6} + Dst.AutoCheck := Src.AutoCheck; + {$ENDIF} + Dst.Caption := Src.Caption; + Dst.Checked := Src.Checked; + if Src.Default then + Dst.Options := Dst.Options + [tboDefault]; + Dst.Enabled := Src.Enabled; + Dst.GroupIndex := Src.GroupIndex; + Dst.HelpContext := Src.HelpContext; + Dst.ImageIndex := Src.ImageIndex; + Dst.RadioItem := Src.RadioItem; + Dst.ShortCut := Src.ShortCut; + {$IFDEF JR_D5} + Dst.SubMenuImages := Src.SubMenuImages; + {$ENDIF} + Dst.OnClick := Src.OnClick; + end + else begin + Dst := TTBSeparatorItem.Create(Owner); + end; + Dst.Hint := Src.Hint; + Dst.Tag := Src.Tag; + Dst.Visible := Src.Visible; + if not IsSep then + { Temporarily clear the menu item's OnClick property, so that renaming + the menu item doesn't cause the function name to change } + Src.OnClick := nil; + try + N := Src.Name; + Src.Name := N + '_OLD'; + Dst.Name := N; + finally + if not IsSep then + Src.OnClick := Dst.OnClick; + end; + TBItem.Add(Dst); + {$IFDEF JR_D5} + if @Src.OnAdvancedDrawItem <> nil then + Log(Format(SPropNotTransferred, ['OnAdvancedDrawItem', Dst.Name])); + {$ENDIF} + if @Src.OnDrawItem <> nil then + Log(Format(SPropNotTransferred, ['OnDrawItem', Dst.Name])); + if @Src.OnMeasureItem <> nil then + Log(Format(SPropNotTransferred, ['OnMeasureItem', Dst.Name])); + if IsSubmenu then + Recurse(Src, Dst); + end; + end; + +var + OptionsForm: TTBConvertOptionsForm; + I: Integer; + C: TComponent; + Menu: TMenu; +begin + Menu := nil; + OptionsForm := TTBConvertOptionsForm.Create(Application); + try + for I := 0 to Owner.ComponentCount-1 do begin + C := Owner.Components[I]; + if (C is TMenu) and not(C is TTBPopupMenu) then + OptionsForm.MenuCombo.Items.AddObject(C.Name, C); + end; + if OptionsForm.MenuCombo.Items.Count = 0 then + raise Exception.Create('Could not find any menus on the form to convert'); + OptionsForm.MenuCombo.ItemIndex := 0; + if (OptionsForm.ShowModal <> mrOK) or (OptionsForm.MenuCombo.ItemIndex < 0) then + Exit; + Menu := TMenu(OptionsForm.MenuCombo.Items.Objects[OptionsForm.MenuCombo.ItemIndex]); + finally + OptionsForm.Free; + end; + ParentItem.SubMenuImages := Menu.Images; + ConverterForm := TTBConverterForm.Create(Application); + ConverterForm.Show; + ConverterForm.Update; + Log(Format('Converting ''%s'', please wait...', [Menu.Name])); + ParentItem.ViewBeginUpdate; + try + Recurse(Menu.Items, ParentItem); + finally + ParentItem.ViewEndUpdate; + end; + Log('Done!'); + ConverterForm.CloseButton.Enabled := True; + ConverterForm.CopyButton.Enabled := True; +end; + + +{ TTBConverterForm } + +procedure TTBConverterForm.FormClose(Sender: TObject; + var Action: TCloseAction); +begin + Action := caFree; +end; + +procedure TTBConverterForm.CloseButtonClick(Sender: TObject); +begin + Close; +end; + +procedure TTBConverterForm.CopyButtonClick(Sender: TObject); +begin + Clipboard.AsText := MessageList.Items.Text; +end; + + +procedure FreeConverterForms; +var + I: Integer; + Form: TCustomForm; +label Restart; +begin + Restart: + for I := 0 to Screen.CustomFormCount-1 do begin + Form := Screen.CustomForms[I]; + if Form is TTBConverterForm then begin + Form.Free; + goto Restart; + end; + end; +end; + +initialization +finalization + FreeConverterForms; +end. diff --git a/official/2.1.6+2.1.beta1/Source/TB2DsgnItemEditor.dfm b/official/2.1.6+2.1.beta1/Source/TB2DsgnItemEditor.dfm new file mode 100644 index 0000000..748a7cd Binary files /dev/null and b/official/2.1.6+2.1.beta1/Source/TB2DsgnItemEditor.dfm differ diff --git a/official/2.1.6+2.1.beta1/Source/TB2DsgnItemEditor.dfm.txt b/official/2.1.6+2.1.beta1/Source/TB2DsgnItemEditor.dfm.txt new file mode 100644 index 0000000..a2a3205 --- /dev/null +++ b/official/2.1.6+2.1.beta1/Source/TB2DsgnItemEditor.dfm.txt @@ -0,0 +1,184 @@ +object TBItemEditForm: TTBItemEditForm + Left = 200 + Top = 104 + AutoScroll = False + BorderIcons = [biSystemMenu, biMinimize] + ClientHeight = 247 + ClientWidth = 440 + Color = clBtnFace + Font.Charset = DEFAULT_CHARSET + Font.Color = clWindowText + Font.Height = -11 + Font.Name = 'MS Sans Serif' + Font.Style = [] + OldCreateOrder = True + Position = poScreenCenter + OnActivate = FormActivate + OnClose = FormClose + PixelsPerInch = 96 + TextHeight = 13 + object Splitter1: TSplitter + Left = 129 + Top = 19 + Width = 3 + Height = 228 + Cursor = crHSplit + ResizeStyle = rsUpdate + end + object TreeView: TTreeView + Left = 0 + Top = 19 + Width = 129 + Height = 228 + Align = alLeft + HideSelection = False + Indent = 19 + ReadOnly = True + ShowRoot = False + TabOrder = 2 + OnChange = TreeViewChange + OnDragDrop = TreeViewDragDrop + OnDragOver = TreeViewDragOver + OnEnter = TreeViewEnter + OnKeyDown = TreeViewKeyDown + OnKeyPress = TreeViewKeyPress + end + object ListView: TListView + Left = 132 + Top = 19 + Width = 308 + Height = 228 + Align = alClient + Columns = < + item + Caption = 'Caption' + Width = 160 + end + item + Caption = 'Type' + Width = 120 + end> + ColumnClick = False + DragMode = dmAutomatic + HideSelection = False + MultiSelect = True + ReadOnly = True + RowSelect = True + PopupMenu = TBPopupMenu1 + TabOrder = 1 + ViewStyle = vsReport + OnChange = ListViewChange + OnDblClick = ListViewDblClick + OnEnter = ListViewEnter + OnDragDrop = ListViewDragDrop + OnDragOver = ListViewDragOver + OnKeyDown = ListViewKeyDown + OnKeyPress = ListViewKeyPress + end + object Toolbar: TTBToolbar + Left = 0 + Top = 0 + Width = 440 + Height = 19 + Align = alTop + Caption = 'Toolbar' + DockPos = 0 + FullSize = True + LinkSubitems = ToolbarItems + ParentShowHint = False + ShowHint = True + TabOrder = 0 + end + object TBPopupMenu1: TTBPopupMenu + LinkSubitems = ToolbarItems + Left = 256 + Top = 120 + end + object TBItemContainer1: TTBItemContainer + Left = 224 + Top = 120 + object ToolbarItems: TTBSubmenuItem + object NewItemButton: TTBItem + Caption = 'New &Item' + Hint = 'New Item' + ImageIndex = 0 + ShortCut = 45 + OnClick = NewItemButtonClick + end + object NewSubmenuButton: TTBItem + Caption = 'New &Submenu' + Hint = 'New Submenu' + ImageIndex = 1 + ShortCut = 16429 + OnClick = NewSubmenuButtonClick + end + object NewSepButton: TTBItem + Caption = 'New Se¶tor' + Hint = 'New Separator' + ImageIndex = 2 + ShortCut = 189 + OnClick = NewSepButtonClick + end + object MoreMenu: TTBSubmenuItem + Caption = '&More' + Options = [tboDropdownArrow] + end + object TBSeparatorItem1: TTBSeparatorItem + end + object CutButton: TTBItem + Caption = 'Cu&t' + Enabled = False + Hint = 'Cut' + ImageIndex = 5 + OnClick = CutButtonClick + end + object CopyButton: TTBItem + Caption = '&Copy' + Enabled = False + Hint = 'Copy' + ImageIndex = 4 + OnClick = CopyButtonClick + end + object PasteButton: TTBItem + Caption = '&Paste' + Hint = 'Paste' + ImageIndex = 6 + OnClick = PasteButtonClick + end + object DeleteButton: TTBItem + Caption = '&Delete Item' + Enabled = False + Hint = 'Delete Item' + ImageIndex = 3 + ShortCut = 46 + OnClick = DeleteButtonClick + end + object TBSeparatorItem2: TTBSeparatorItem + end + object MoveUpButton: TTBItem + Caption = 'Move &Up' + Hint = 'Move Up' + ImageIndex = 7 + ShortCut = 32806 + OnClick = MoveUpButtonClick + end + object MoveDownButton: TTBItem + Caption = 'Move D&own' + Hint = 'Move Down' + ImageIndex = 8 + ShortCut = 32808 + OnClick = MoveDownButtonClick + end + object TBSeparatorItem3: TTBSeparatorItem + end + object TBSubmenuItem1: TTBSubmenuItem + Caption = '&Tools' + Options = [tboDropdownArrow] + object TConvertMenu: TTBItem + Caption = '&Convert TMainMenu/TPopupMenu...' + OnClick = TConvertMenuClick + end + end + end + end +end diff --git a/official/2.1.6+2.1.beta1/Source/TB2DsgnItemEditor.pas b/official/2.1.6+2.1.beta1/Source/TB2DsgnItemEditor.pas new file mode 100644 index 0000000..b0c824f --- /dev/null +++ b/official/2.1.6+2.1.beta1/Source/TB2DsgnItemEditor.pas @@ -0,0 +1,1401 @@ +unit TB2DsgnItemEditor; + +{ + Toolbar2000 + Copyright (C) 1998-2005 by Jordan Russell + All rights reserved. + + The contents of this file are subject to the "Toolbar2000 License"; you may + not use or distribute this file except in compliance with the + "Toolbar2000 License". A copy of the "Toolbar2000 License" may be found in + TB2k-LICENSE.txt or at: + http://www.jrsoftware.org/files/tb2k/TB2k-LICENSE.txt + + Alternatively, the contents of this file may be used under the terms of the + GNU General Public License (the "GPL"), in which case the provisions of the + GPL are applicable instead of those in the "Toolbar2000 License". A copy of + the GPL may be found in GPL-LICENSE.txt or at: + http://www.jrsoftware.org/files/tb2k/GPL-LICENSE.txt + If you wish to allow use of your version of this file only under the terms of + the GPL and not to allow others to use your version of this file under the + "Toolbar2000 License", indicate your decision by deleting the provisions + above and replace them with the notice and other provisions required by the + GPL. If you do not delete the provisions above, a recipient may use your + version of this file under either the "Toolbar2000 License" or the GPL. + + $jrsoftware: tb2k/Source/TB2DsgnItemEditor.pas,v 1.55 2005/01/27 06:48:53 jr Exp $ +} + +interface + +{$I TB2Ver.inc} + +uses + Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, + StdCtrls, ExtCtrls, Buttons, ComCtrls, ImgList, Menus, + TB2Item, TB2Toolbar, TB2Dock, + {$IFDEF JR_D6} + DesignIntf, DesignWindows, DesignEditors; + {$ELSE} + DsgnIntf, DsgnWnds, LibIntf; + {$ENDIF} + +type + TTBItemEditForm = class(TDesignWindow) + TreeView: TTreeView; + ListView: TListView; + Splitter1: TSplitter; + Toolbar: TTBToolbar; + NewSubmenuButton: TTBItem; + NewItemButton: TTBItem; + NewSepButton: TTBItem; + DeleteButton: TTBItem; + TBSeparatorItem1: TTBSeparatorItem; + TBPopupMenu1: TTBPopupMenu; + TBItemContainer1: TTBItemContainer; + ToolbarItems: TTBSubmenuItem; + CopyButton: TTBItem; + CutButton: TTBItem; + PasteButton: TTBItem; + MoreMenu: TTBSubmenuItem; + TBSeparatorItem2: TTBSeparatorItem; + TBSubmenuItem1: TTBSubmenuItem; + TConvertMenu: TTBItem; + TBSeparatorItem3: TTBSeparatorItem; + MoveUpButton: TTBItem; + MoveDownButton: TTBItem; + procedure FormClose(Sender: TObject; var Action: TCloseAction); + procedure TreeViewChange(Sender: TObject; Node: TTreeNode); + procedure NewSubmenuButtonClick(Sender: TObject); + procedure NewItemButtonClick(Sender: TObject); + procedure ListViewChange(Sender: TObject; Item: TListItem; + Change: TItemChange); + procedure DeleteButtonClick(Sender: TObject); + procedure NewSepButtonClick(Sender: TObject); + procedure ListViewDragOver(Sender, Source: TObject; X, Y: Integer; + State: TDragState; var Accept: Boolean); + procedure ListViewDragDrop(Sender, Source: TObject; X, Y: Integer); + procedure TreeViewEnter(Sender: TObject); + procedure TreeViewDragDrop(Sender, Source: TObject; X, Y: Integer); + procedure TreeViewDragOver(Sender, Source: TObject; X, Y: Integer; + State: TDragState; var Accept: Boolean); + procedure CopyButtonClick(Sender: TObject); + procedure ListViewKeyDown(Sender: TObject; var Key: Word; + Shift: TShiftState); + procedure CutButtonClick(Sender: TObject); + procedure PasteButtonClick(Sender: TObject); + procedure FormActivate(Sender: TObject); + procedure ListViewKeyPress(Sender: TObject; var Key: Char); + procedure ListViewDblClick(Sender: TObject); + procedure ListViewEnter(Sender: TObject); + procedure TreeViewKeyDown(Sender: TObject; var Key: Word; + Shift: TShiftState); + procedure TConvertMenuClick(Sender: TObject); + procedure TreeViewKeyPress(Sender: TObject; var Key: Char); + procedure MoveUpButtonClick(Sender: TObject); + procedure MoveDownButtonClick(Sender: TObject); + private + FParentComponent: TComponent; + FRootItem, FSelParentItem: TTBCustomItem; + FNotifyItemList: TList; + FSettingSel, FRebuildingTree, FRebuildingList: Integer; + function AddListViewItem(const Index: Integer; + const Item: TTBCustomItem): TListItem; + procedure Copy; + procedure CreateNewItem(const AClass: TTBCustomItemClass); + procedure Cut; + procedure Delete; + procedure DeleteItem(const Item: TTBCustomItem); + function GetItemTreeCaption(AItem: TTBCustomItem): String; + procedure GetSelItemList(const AList: TList); + procedure ItemNotification(Ancestor: TTBCustomItem; Relayed: Boolean; + Action: TTBItemChangedAction; Index: Integer; Item: TTBCustomItem); + procedure MoreItemClick(Sender: TObject); + procedure MoveItem(CurIndex, NewIndex: Integer); + procedure Paste; + procedure RebuildList; + procedure RebuildTree; + procedure SelectInObjectInspector(AList: TList); + procedure SetSelParentItem(ASelParentItem: TTBCustomItem); + function TreeViewDragHandler(Sender, Source: TObject; X, Y: Integer; + Drop: Boolean): Boolean; + procedure UnregisterAllNotifications; + protected + procedure Notification(AComponent: TComponent; Operation: TOperation); override; + function UniqueName(Component: TComponent): String; override; + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + {$IFDEF JR_D6} + function EditAction(Action: TEditAction): Boolean; override; + {$ELSE} + procedure EditAction(Action: TEditAction); override; + {$ENDIF} + function GetEditState: TEditState; override; + end; + + TTBItemsEditor = class(TDefaultEditor) + public + procedure Edit; override; + procedure ExecuteVerb(Index: Integer); override; + function GetVerb(Index: Integer): String; override; + function GetVerbCount: Integer; override; + end; + + TTBItemsPropertyEditor = class(TStringProperty) + public + procedure Edit; override; + function GetAttributes: TPropertyAttributes; override; + function GetValue: String; override; + end; + +procedure TBRegisterItemClass(AClass: TTBCustomItemClass; + const ACaption: String; ResInstance: HINST); + +type + TTBDsgnEditorHook = procedure(Sender: TTBItemEditForm) of object; + +procedure TBRegisterDsgnEditorHook(Hook: TTBDsgnEditorHook); +procedure TBUnregisterDsgnEditorHook(Hook: TTBDsgnEditorHook); + +implementation + +{$R *.DFM} + +uses + TypInfo, CommCtrl, TB2Version, TB2Common, TB2DsgnConverter; + +type + {}TTBCustomItemAccess = class(TTBCustomItem); + {}TControlAccess = class(TControl); +{$IFNDEF JR_D5} + TDesignerSelectionList = TComponentList; +{$ENDIF} +{$IFDEF JR_D6} + TDesignerSelectionList = IDesignerSelections; +{$ENDIF} + + PItemClassInfo = ^TItemClassInfo; + TItemClassInfo = record + ItemClass: TTBCustomItemClass; + Caption: String; + ImageIndex: Integer; + end; + +var + ItemClasses: TList; + ItemImageList: TImageList; + EditFormHooks: TList; + +{$IFNDEF JR_D6} +function CreateSelectionList: TDesignerSelectionList; +begin + Result := TDesignerSelectionList.Create; +end; +{$ENDIF} + +procedure FreeItemClasses; +var + I: Integer; + IC: TList; +begin + if ItemClasses = nil then Exit; + IC := ItemClasses; + ItemClasses := nil; + for I := IC.Count-1 downto 0 do + Dispose(PItemClassInfo(IC[I])); + IC.Free; +end; + +procedure UnregisterModuleItemClasses(AModule: {$IFDEF JR_D5} LongWord {$ELSE} Integer {$ENDIF}); +var + I: Integer; + Info: PItemClassInfo; +begin + I := 0; + while I < ItemClasses.Count do begin + Info := ItemClasses[I]; + if FindClassHInstance(Info.ItemClass) = AModule then begin + ItemClasses.Delete(I); + Dispose(Info); + end + else + Inc(I); + end; + { Note: TTBItemEditForm also holds references to item classes, but since + Delphi automatically closes all editor forms before compiling/removing + a package, we don't need to remove them. } +end; + +function LoadItemImage(Instance: HINST; const ResName: String): Integer; +var + Bmp: TBitmap; +begin + Bmp := TBitmap.Create; + try + Bmp.Handle := LoadBitmap(Instance, PChar(ResName)); + if Bmp.Handle = 0 then + Result := -1 + else + Result := ItemImageList.AddMasked(Bmp, Bmp.Canvas.Pixels[0, Bmp.Height-1]); + finally + Bmp.Free; + end; +end; + +procedure TBRegisterItemClass(AClass: TTBCustomItemClass; + const ACaption: String; ResInstance: HINST); +var + Info: PItemClassInfo; + I: Integer; +begin + if ItemClasses <> nil then + for I := ItemClasses.Count - 1 downto 0 do + begin + Info := ItemClasses[I]; + if Info.ItemClass = AClass then + begin + Dispose(Info); + ItemClasses.Delete(I); + end; + end; + New(Info); + Info.ItemClass := AClass; + Info.Caption := ACaption; + Info.ImageIndex := LoadItemImage(ResInstance, Uppercase(AClass.ClassName)); + ItemClasses.Add(Info); +end; + +function GetItemClassImage(AClass: TTBCustomItemClass): Integer; +var + I: Integer; + Info: PItemClassInfo; +begin + for I := ItemClasses.Count-1 downto 0 do begin + Info := ItemClasses[I]; + if AClass.InheritsFrom(Info.ItemClass) then begin + Result := Info.ImageIndex; + if Result >= 0 then + Exit; + end; + end; + if AClass.InheritsFrom(TTBSubmenuItem) then + Result := 1 + else if AClass.InheritsFrom(TTBSeparatorItem) then + Result := 2 + else + Result := 0; +end; + +procedure ShowEditForm(AParentComponent: TComponent; ARootItem: TTBCustomItem; + const ADesigner: {$IFDEF JR_D6} IDesigner {$ELSE} IFormDesigner {$ENDIF}); +var + I: Integer; + Form: TCustomForm; + EditForm: TTBItemEditForm; +begin + if Assigned(ARootItem.LinkSubitems) then begin + case MessageDlg(Format('The LinkSubitems property is set to ''%s''. ' + + 'Would you like to edit that item instead?', + [ARootItem.LinkSubitems.Name]), mtConfirmation, [mbYes, mbNo, mbCancel], 0) of + mrYes: begin + AParentComponent := ARootItem.LinkSubitems; + ARootItem := ARootItem.LinkSubitems; + end; + mrCancel: Exit; + end; + end; + for I := 0 to Screen.FormCount-1 do begin + Form := Screen.Forms[I]; + if Form is TTBItemEditForm then + if TTBItemEditForm(Form).FRootItem = ARootItem then begin + Form.Show; + if Form.WindowState = wsMinimized then + Form.WindowState := wsNormal; + Exit; + end; + end; + EditForm := TTBItemEditForm.Create(Application); + try + EditForm.Designer := ADesigner; + EditForm.FParentComponent := AParentComponent; + AParentComponent.FreeNotification(EditForm); + EditForm.FRootItem := ARootItem; + ARootItem.FreeNotification(EditForm); + EditForm.FSelParentItem := ARootItem; + EditForm.Caption := 'Editing ' + AParentComponent.Name; + EditForm.RebuildTree; + EditForm.RebuildList; + {$IFDEF JR_D9} + EditForm.PopupMode := pmExplicit; + {$ENDIF} + EditForm.Show; + except + EditForm.Free; + raise; + end; +end; + +function IsSubmenuItem(Item: TTBCustomItem): Boolean; +begin + Result := tbisSubitemsEditable in TTBCustomItemAccess(Item).ItemStyle; +end; + +procedure ShowVersion; +const + AboutText = + '%s'#13#10 + + 'Copyright (C) 1998-2005 by Jordan Russell'#13#10 + + 'For conditions of distribution and use, see LICENSE.TXT.'#13#10 + + #13#10 + + 'Visit my web site for the latest versions of Toolbar2000:'#13#10 + + 'http://www.jrsoftware.org/'; +begin + MessageDlg(Format(AboutText, [Toolbar2000VersionPropText]), mtInformation, + [mbOK], 0); +end; + + +{ TTBItemEditForm } + +constructor TTBItemEditForm.Create(AOwner: TComponent); +var + I: Integer; + Info: PItemClassInfo; + Item: TTBItem; +begin + inherited; + FNotifyItemList := TList.Create; + ToolbarItems.SubMenuImages := ItemImageList; + ListView.SmallImages := ItemImageList; + { Populate the 'More' menu } + for I := 0 to ItemClasses.Count-1 do begin + Info := ItemClasses[I]; + Item := TTBItem.Create(Self); + Item.Caption := Info.Caption; + Item.ImageIndex := GetItemClassImage(Info.ItemClass); + Item.Tag := Integer(Info.ItemClass); + Item.OnClick := MoreItemClick; + MoreMenu.Add(Item); + end; + { Run the hooks } + + if EditFormHooks <> nil then + for I := 0 to EditFormHooks.Count - 1 do + TTBDsgnEditorHook(EditFormHooks[I]^)(Self); +end; + +destructor TTBItemEditForm.Destroy; +begin + inherited; + if Assigned(FNotifyItemList) then begin + UnregisterAllNotifications; + FNotifyItemList.Free; + FNotifyItemList := nil; + end; +end; + +procedure TTBItemEditForm.FormClose(Sender: TObject; + var Action: TCloseAction); +begin + Action := caFree; +end; + +procedure TTBItemEditForm.FormActivate(Sender: TObject); +begin + SetSelParentItem(FSelParentItem); +end; + +procedure TTBItemEditForm.Notification(AComponent: TComponent; + Operation: TOperation); +begin + inherited; + if (Operation = opRemove) and + ((AComponent = FParentComponent) or (AComponent = FRootItem)) then + { Must use Free instead of Close, since Close causes the freeing of the + form to be delayed until the next message. We have to destroy the form + immediately, otherwise Delphi will crash when Compile is clicked on the + TB2k package. } + Free; + {}{temp:} + (*if (Operation = opRemove) and (FNotifyItemList.IndexOf(AComponent) <> -1) then begin + outputdebugstring(pchar('Still in list: ' + AComponent.name)); + //beep; + end;*) +end; + +function TTBItemEditForm.UniqueName(Component: TComponent): String; +begin + Result := Designer.UniqueName(Component.ClassName); +end; + +function TTBItemEditForm.GetEditState: TEditState; +begin + Result := []; + if ActiveControl = ListView then begin + if Assigned(ListView.Selected) then + Result := [esCanDelete, esCanCut, esCanCopy]; + if ClipboardComponents then + Include(Result, esCanPaste); + end; +end; + +{$IFDEF JR_D6} +function TTBItemEditForm.EditAction(Action: TEditAction): Boolean; +{$ELSE} +procedure TTBItemEditForm.EditAction(Action: TEditAction); +{$ENDIF} +begin + {$IFDEF JR_D6} + Result := True; + {$ENDIF} + case Action of + eaCut: Cut; + eaCopy: Copy; + eaPaste: Paste; + eaDelete: Delete; + {$IFDEF JR_D6} + else + Result := False; + {$ENDIF} + end; +end; + +procedure TTBItemEditForm.UnregisterAllNotifications; +var + I: Integer; +begin + for I := FNotifyItemList.Count-1 downto 0 do begin + //outputdebugstring(pchar('Unregall: ' + TTBCustomItem(FNotifyItemList[I]).name)); + TTBCustomItem(FNotifyItemList[I]).UnregisterNotification(ItemNotification); + FNotifyItemList.Delete(I); + end; +end; + +procedure TTBItemEditForm.ItemNotification(Ancestor: TTBCustomItem; + Relayed: Boolean; Action: TTBItemChangedAction; Index: Integer; + Item: TTBCustomItem); +var + ListItem: TListItem; + TreeNode: TTreeNode; + I: Integer; + C: String; +begin + { Manipulate the list view when items are inserted, deleted, or their Caption + changes } + case Action of + tbicInserted: + begin + if (Ancestor = FSelParentItem) and not Relayed then + AddListViewItem(Index, Item); + if IsSubmenuItem(Item) then + RebuildTree; + end; + tbicDeleting: + if (Ancestor = FSelParentItem) and not Relayed then begin + ListItem := ListView.FindData(0, Item, True, False); + if Assigned(ListItem) then + ListItem.Delete; + end; + tbicInvalidateAndResize: + if (Ancestor = FSelParentItem) and not Relayed then begin + ListItem := ListView.FindData(0, Item, True, False); + if Assigned(ListItem) and (ListItem.Caption <> TTBCustomItem(Item).Caption) then + ListItem.Caption := TTBCustomItem(Item).Caption; + end; + end; + { Update tree view when an item is deleted, or a Caption changes } + if Action = tbicDeleting then begin + I := FNotifyItemList.IndexOf(Item); + if I <> -1 then begin + //outputdebugstring(pchar('Deleting, so unreging: ' + item.name)); + TTBCustomItem(Item).UnregisterNotification(ItemNotification); + FNotifyItemList.Delete(I); + end; + end; + if Action in [tbicDeleting, tbicInvalidateAndResize, tbicNameChanged] then begin + TreeNode := TreeView.Items.GetFirstNode; + while Assigned(TreeNode) do begin + if TreeNode.Data = Item then begin + if Action = tbicDeleting then begin + TreeNode.Delete; + if FSelParentItem = Item then + SetSelParentItem(TTBCustomItem(Item).Parent); + end + else begin + { tbicInvalidateAndResize, tbicNameChanged: } + C := GetItemTreeCaption(Item); + if TreeNode.Text <> C then + TreeNode.Text := C; + end; + Break; + end; + TreeNode := TreeNode.GetNext; + end; + end; +end; + +function TTBItemEditForm.GetItemTreeCaption(AItem: TTBCustomItem): String; +begin + if AItem <> FRootItem then begin + Result := AItem.Caption; + if Result = '' then + Result := '[' + AItem.Name + ']'; + end + else + Result := '(Root)'; +end; + +procedure TTBItemEditForm.RebuildTree; + + procedure Recurse(const AParentItem: TTBCustomItem; const ATreeNode: TTreeNode; + var FoundSelParentItem: TTreeNode); + var + I: Integer; + NewNode: TTreeNode; + ChildItem: TTBCustomItem; + begin + {}AParentItem.FreeNotification(Self); + AParentItem.RegisterNotification(ItemNotification); + FNotifyItemList.Add(AParentItem); + NewNode := TreeView.Items.AddChild(ATreeNode, GetItemTreeCaption(AParentItem)); + NewNode.Data := AParentItem; + if AParentItem = FSelParentItem then + FoundSelParentItem := NewNode; + for I := 0 to AParentItem.Count-1 do begin + ChildItem := AParentItem[I]; + if IsSubmenuItem(ChildItem) then + Recurse(ChildItem, NewNode, FoundSelParentItem); + end; + end; + +var + FoundSelParentItem: TTreeNode; +begin + Inc(FRebuildingTree); + try + TreeView.Items.BeginUpdate; + try + TreeView.Items.Clear; + UnregisterAllNotifications; + FoundSelParentItem := nil; + Recurse(FRootItem, nil, FoundSelParentItem); + if FoundSelParentItem = nil then + SetSelParentItem(FRootItem) + else + TreeView.Selected := FoundSelParentItem; + TreeView.Items[0].Expand(True); + finally + TreeView.Items.EndUpdate; + end; + finally + Dec(FRebuildingTree); + end; +end; + +function TTBItemEditForm.AddListViewItem(const Index: Integer; + const Item: TTBCustomItem): TListItem; +begin + Result := ListView.Items.Insert(Index); + Result.Data := Item; + if not(Item is TTBControlItem) then begin + Result.Caption := Item.Caption; + Result.Subitems.Add(Item.ClassName); + Result.ImageIndex := GetItemClassImage(TTBCustomItemClass(Item.ClassType)); + end + else begin + Result.Caption := '(Control)'; + Result.Subitems.Add(Item.ClassName); + Result.ImageIndex := -1; + end; +end; + +procedure TTBItemEditForm.RebuildList; +var + ChildItem: TTBCustomItem; + I: Integer; +begin + Inc(FRebuildingList); + try + ListView.Items.BeginUpdate; + try + ListView.Items.Clear; + if Assigned(FSelParentItem) then begin + for I := 0 to FSelParentItem.Count-1 do begin + ChildItem := FSelParentItem[I]; + { Check for csDestroying because deleting an item in the tree view + causes the parent item to be selected, and the parent item won't + get a notification that the item is deleting since notifications + were already sent } + if not(csDestroying in ChildItem.ComponentState) then + AddListViewItem(I, ChildItem); + end; + { Add an empty item to the end } + ListView.Items.Add.ImageIndex := -1; + end; + finally + ListView.Items.EndUpdate; + end; + { Work around a strange TListView bug(?). Without this, the column header + isn't painted properly. } + if HandleAllocated then + SetWindowPos(ListView.Handle, 0, 0, 0, 0, 0, SWP_FRAMECHANGED or + SWP_NOACTIVATE or SWP_NOMOVE or SWP_NOSIZE or SWP_NOZORDER); + finally + Dec(FRebuildingList); + end; +end; + +procedure TTBItemEditForm.SelectInObjectInspector(AList: TList); +var + CompList1, CompList2: TDesignerSelectionList; + I: Integer; + C: TComponent; +begin + { Designer.SetSelections will make components appear selected on the form. + It will also select the component in Object Inspector, but only if the + form has the focus. TDesignWindow.SetSelection will select the component + in Object Inspector regardless of whether the form has the focus. } + CompList1 := CreateSelectionList; + CompList2 := CreateSelectionList; + for I := 0 to AList.Count-1 do begin + C := AList[I]; + { Must check for csDestroying. If SetSelection is passed a component that's + destroying, Delphi will crash. } + if not(csDestroying in C.ComponentState) then begin + CompList1.Add(C); + CompList2.Add(C); + end; + end; + if CompList1.Count = 0 then begin + {$IFNDEF JR_D6} + CompList1.Free; + CompList2.Free; + {$ENDIF} + end + else begin + Designer.SetSelections(CompList1); + { Note: Never pass an empty list to SetSelection or Delphi will crash } + { History here: + - 1.34: SetSelection call remarked out because it fixed Delphi 6 issue + with random AV's after the editor was closed. + - 1.38: SetSelection call restored because without it, Ctrl+X/C/V didn't + work. + - 1.40: SetSelection call disabled on Delphi 6 only because AV problem + still seems to exist despite another change which I thought fixed it. + On D6 it isn't necessary to call SetSelection for Ctrl+X/C/V to work. + Note: Using "ComponentDesigner.SetSelection(Designer, nil, CompList2);" + instead seems to fix the AV problem, but for consistency with Delphi's + TMainMenu editor (which only selects items when its parent form is + focused), I decided not to call SetSelection at all on D6. + } + {$IFNDEF JR_D6} + SetSelection(CompList2); + {$ENDIF} + end; +end; + +procedure TTBItemEditForm.GetSelItemList(const AList: TList); +var + ListItem: TListItem; +begin + ListItem := nil; + while True do begin + ListItem := ListView.GetNextItem(ListItem, sdAll, [isSelected]); + if ListItem = nil then + Break; + if Assigned(ListItem.Data) then + AList.Add(ListItem.Data); + end; +end; + +procedure TTBItemEditForm.SetSelParentItem(ASelParentItem: TTBCustomItem); +{ - Rebuilds the list view to match a new selection (ASelParentItem) in the + tree view + - Updates toolbar + - Selects selected item(s) into Object Inspector } +var + I: Integer; + TreeNode: TTreeNode; + ItemIsSelected: Boolean; + List: TList; +begin + if FSettingSel > 0 then + Exit; + List := TList.Create; + Inc(FSettingSel); + try + if FSelParentItem <> ASelParentItem then begin + FSelParentItem := ASelParentItem; + NewSubmenuButton.Enabled := Assigned(ASelParentItem); + NewItemButton.Enabled := Assigned(ASelParentItem); + NewSepButton.Enabled := Assigned(ASelParentItem); + for I := 0 to MoreMenu.Count-1 do + MoreMenu[I].Enabled := Assigned(ASelParentItem); + if not Assigned(TreeView.Selected) or (TreeView.Selected.Data <> FSelParentItem) then begin + if FSelParentItem = nil then + TreeView.Selected := nil + else begin + TreeNode := TreeView.Items.GetFirstNode; + while Assigned(TreeNode) do begin + if TreeNode.Data = FSelParentItem then begin + TreeView.Selected := TreeNode; + Break; + end; + TreeNode := TreeNode.GetNext; + end; + end; + end; + RebuildList; + end; + + ItemIsSelected := (ActiveControl = ListView) and Assigned(ListView.Selected) and + Assigned(ListView.Selected.Data); + if ItemIsSelected then + GetSelItemList(List); + + CutButton.Enabled := ItemIsSelected; + CopyButton.Enabled := ItemIsSelected; + PasteButton.Enabled := (ActiveControl = ListView); + DeleteButton.Enabled := ItemIsSelected or + ((ActiveControl = TreeView) and (FSelParentItem <> FRootItem)); + MoveUpButton.Enabled := ItemIsSelected and + (FSelParentItem.IndexOf(List.First) > 0); + MoveDownButton.Enabled := ItemIsSelected and + (FSelParentItem.IndexOf(List.Last) < FSelParentItem.Count-1); + + if ActiveControl = ListView then begin + if List.Count = 0 then + { No item was selected, or the blank item was selected. + Select the root item so it looks like no item was selected in + Object Inspector } + List.Add(FRootItem); + end + else if not Assigned(ASelParentItem) or (ASelParentItem = FRootItem) then + List.Add(FParentComponent) + else + List.Add(ASelParentItem); + SelectInObjectInspector(List); + finally + Dec(FSettingSel); + List.Free; + end; +end; + +procedure TTBItemEditForm.Cut; +begin + Copy; + Delete; +end; + +procedure TTBItemEditForm.Copy; +var + SelList: TList; + CompList: TDesignerSelectionList; + I: Integer; + Item: TTBCustomItem; +begin + if ListView.Selected = nil then Exit; + CompList := nil; + SelList := TList.Create; + try + GetSelItemList(SelList); + CompList := CreateSelectionList; + for I := 0 to SelList.Count-1 do begin + Item := SelList[I]; + if Item is TTBControlItem then + raise EInvalidOperation.Create('Cannot cut or copy TTBControlItems'); + CompList.Add(Item); + end; + CopyComponents(FParentComponent.Owner, CompList); + finally + {$IFNDEF JR_D6} + CompList.Free; + {$ENDIF} + SelList.Free; + end; +end; + +procedure TTBItemEditForm.Paste; +var + CompList: TDesignerSelectionList; +begin + if FSelParentItem = nil then Exit; + CompList := CreateSelectionList; + try + PasteComponents(FParentComponent.Owner, FSelParentItem, CompList); + if CompList.Count <> 0 then + Designer.Modified; + finally + {$IFNDEF JR_D6} + CompList.Free; + {$ENDIF} + end; +end; + +procedure TTBItemEditForm.DeleteItem(const Item: TTBCustomItem); +begin + if csAncestor in Item.ComponentState then + raise EInvalidOperation.Create('Items introduced in an ancestor form cannot be deleted'); + //Designer.ValidateRename(Item, Item.Name, ''); + Item.Free; + Designer.Modified; +end; + +procedure TTBItemEditForm.Delete; +var + List: TList; + Item: TTBCustomItem; + ListItem: TListItem; +begin + List := TList.Create; + try + List.Add(FSelParentItem); + SelectInObjectInspector(List); + finally + List.Free; + end; + FSelParentItem.ViewBeginUpdate; + try + while Assigned(ListView.Selected) do begin + Item := ListView.Selected.Data; + if Item = nil then + Break; + DeleteItem(Item); + end; + finally + FSelParentItem.ViewEndUpdate; + end; + { After deleting the items, select the item with the focus } + ListItem := ListView.GetNextItem(nil, sdAll, [isFocused]); + if Assigned(ListItem) then + ListItem.Selected := True; +end; + +procedure TTBItemEditForm.MoveItem(CurIndex, NewIndex: Integer); +var + WasFocused: Boolean; +begin + WasFocused := ListView.Items[CurIndex].Focused; + + FSelParentItem.Move(CurIndex, NewIndex); + Designer.Modified; + + if WasFocused then + ListView.Items[NewIndex].Focused := True; + ListView.Items[NewIndex].Selected := True; +end; + +procedure TTBItemEditForm.TreeViewChange(Sender: TObject; Node: TTreeNode); +var + NewSelectedParentItem: TTBCustomItem; +begin + if (FRebuildingTree > 0) or (FSettingSel > 0) then Exit; + if Node = nil then + NewSelectedParentItem := nil + else + NewSelectedParentItem := Node.Data; + SetSelParentItem(NewSelectedParentItem); +end; + +procedure TTBItemEditForm.TreeViewEnter(Sender: TObject); +{ When the tree view gets the focus, act as if the currently selected item + was clicked. } +begin + ListView.Selected := nil; + SetSelParentItem(FSelParentItem); +end; + +procedure TTBItemEditForm.ListViewChange(Sender: TObject; Item: TListItem; + Change: TItemChange); +begin + if (FRebuildingList > 0) or (FSettingSel > 0) or (Change <> ctState) or + (csDestroying in ListView.ComponentState) then + Exit; + SetSelParentItem(FSelParentItem); +end; + +procedure TTBItemEditForm.ListViewEnter(Sender: TObject); +begin + { When list view gets the focus, update the toolbar } + SetSelParentItem(FSelParentItem); +end; + +procedure TTBItemEditForm.ListViewDblClick(Sender: TObject); +var + SelItem: TTBCustomItem; + PropCount, I: Integer; + Props: PPropList; + PropInfo: PPropInfo; + MethodName: String; + Method: TMethod; +begin + SelItem := nil; + if Assigned(ListView.Selected) then + SelItem := ListView.Selected.Data; + if SelItem = nil then Exit; + if IsSubmenuItem(SelItem) then begin + SetSelParentItem(SelItem); + Exit; + end; + PropCount := GetPropList(SelItem.ClassInfo, [tkMethod], nil); + GetMem(Props, PropCount * SizeOf(PPropInfo)); + try + GetPropList(SelItem.ClassInfo, [tkMethod], Props); + for I := PropCount-1 downto 0 do begin + PropInfo := Props[I]; + if CompareText(PropInfo.Name, 'OnClick') = 0 then begin + Method := GetMethodProp(SelItem, PropInfo); + MethodName := Designer.GetMethodName(Method); + if MethodName = '' then begin + MethodName := SelItem.Name + 'Click'; + Method := Designer.CreateMethod(MethodName, GetTypeData(PropInfo.PropType^)); + SetMethodProp(SelItem, + {$IFDEF JR_D5} PropInfo.Name {$ELSE} PropInfo {$ENDIF}, + Method); + Designer.Modified; + end; + if Designer.MethodExists(MethodName) then + Designer.ShowMethod(MethodName); + Break; + end; + end; + finally + FreeMem(Props); + end; +end; + +procedure TTBItemEditForm.ListViewKeyDown(Sender: TObject; var Key: Word; + Shift: TShiftState); +begin + case Key of + VK_RETURN: begin + Key := 0; + ActivateInspector(#0); + end; + VK_INSERT: begin + Key := 0; + if ssCtrl in Shift then + NewSubmenuButtonClick(Sender) + else + NewItemButtonClick(Sender); + end; + VK_DELETE: begin + Key := 0; + Delete; + end; + end; +end; + +procedure TTBItemEditForm.TreeViewKeyDown(Sender: TObject; var Key: Word; + Shift: TShiftState); +begin + case Key of + VK_RETURN: begin + Key := 0; + ActivateInspector(#0); + end; + VK_DELETE: begin + Key := 0; + DeleteButtonClick(Sender); + end; + end; +end; + +procedure TTBItemEditForm.TreeViewKeyPress(Sender: TObject; var Key: Char); +begin + if Key in [#33..#126] then begin + ActivateInspector(Key); + Key := #0; + end + else if Key = #13 then + Key := #0; { suppress beep } +end; + +procedure TTBItemEditForm.ListViewKeyPress(Sender: TObject; var Key: Char); +begin + if Key = '-' then begin + NewSepButtonClick(Sender); + Key := #0; + end + else if Key in [#33..#126] then begin + ActivateInspector(Key); + Key := #0; + end; +end; + +procedure TTBItemEditForm.ListViewDragOver(Sender, Source: TObject; X, + Y: Integer; State: TDragState; var Accept: Boolean); +{ List item dragged over the list view } +var + Item: TListItem; +begin + Accept := False; + if (Sender = ListView) and (Source = ListView) and (ListView.SelCount = 1) then begin + Item := ListView.GetItemAt(X, Y); + if Assigned(Item) and (Item <> ListView.Selected) then + Accept := True; + end; +end; + +procedure TTBItemEditForm.ListViewDragDrop(Sender, Source: TObject; X, + Y: Integer); +{ List item dropped onto another list item } +var + ListItem: TListItem; + Item: TTBCustomItem; + NewIndex: Integer; +begin + if (Sender = ListView) and (Source = ListView) and (ListView.SelCount = 1) then begin + ListItem := ListView.GetItemAt(X, Y); + if Assigned(ListItem) and (ListItem <> ListView.Selected) and Assigned(FSelParentItem) then begin + NewIndex := FSelParentItem.IndexOf(ListItem.Data); + if NewIndex <> -1 then begin + ListView.Items.BeginUpdate; + { For good performance and to prevent Object Inspector flicker, increment + FSettingSel to prevent calls to SetSelParentItem while moving items } + Inc(FSettingSel); + try + Item := ListView.Selected.Data; + MoveItem(FSelParentItem.IndexOf(Item), NewIndex); + finally + Dec(FSettingSel); + ListView.Items.EndUpdate; + end; + { After decrementing FSettingSel, now call SetSelParentItem, to update + the toolbar buttons } + SetSelParentItem(FSelParentItem); + end; + end; + end; +end; + +function TTBItemEditForm.TreeViewDragHandler(Sender, Source: TObject; + X, Y: Integer; Drop: Boolean): Boolean; +var + Node: TTreeNode; + ListItem: TListItem; + Item, NewParentItem: TTBCustomItem; + ItemList: TList; + I: Integer; + NeedRebuildTree: Boolean; +begin + Result := False; + if (Sender = TreeView) and (Source = ListView) then begin + Node := TreeView.GetNodeAt(X, Y); + if Assigned(Node) and (Node <> TreeView.Selected) then begin + NewParentItem := Node.Data; + ItemList := TList.Create; + try + ListItem := nil; + while True do begin + ListItem := ListView.GetNextItem(ListItem, sdAll, [isSelected]); + if ListItem = nil then + Break; + Item := ListItem.Data; + if Assigned(Item) and (Item <> NewParentItem) and + not Item.ContainsItem(NewParentItem) and + not(Item is TTBControlItem) then begin + Result := True; + ItemList.Add(Item); + end; + end; + if Drop then begin + NeedRebuildTree := False; + for I := 0 to ItemList.Count-1 do begin + Item := ItemList[I]; + Item.Parent.Remove(Item); + NewParentItem.Add(Item); + Designer.Modified; + if IsSubmenuItem(Item) then + NeedRebuildTree := True; + end; + if NeedRebuildTree then + RebuildTree; + end; + finally + ItemList.Free; + end; + end; + end; +end; + +procedure TTBItemEditForm.TreeViewDragOver(Sender, Source: TObject; X, + Y: Integer; State: TDragState; var Accept: Boolean); +{ List item dragged over the tree view } +begin + Accept := TreeViewDragHandler(Sender, Source, X, Y, False); +end; + +procedure TTBItemEditForm.TreeViewDragDrop(Sender, Source: TObject; X, + Y: Integer); +{ List item dropped onto the tree view } +begin + TreeViewDragHandler(Sender, Source, X, Y, True); +end; + +procedure TTBItemEditForm.CreateNewItem(const AClass: TTBCustomItemClass); +var + NewIndex: Integer; + NewItem: TTBCustomItem; + ListItem: TListItem; +begin + if FSelParentItem = nil then Exit; + NewIndex := -1; + if (GetKeyState(VK_SHIFT) >= 0) and Assigned(ListView.Selected) then + NewIndex := FSelParentItem.IndexOf(ListView.Selected.Data); + if NewIndex = -1 then + NewIndex := FSelParentItem.Count; + NewItem := AClass.Create(FParentComponent.Owner{Designer.Form}); + try + NewItem.Name := Designer.UniqueName(NewItem.ClassName); + FSelParentItem.Insert(NewIndex, NewItem); + except + NewItem.Free; + raise; + end; + Designer.Modified; + ListView.Selected := nil; + ListItem := ListView.FindData(0, NewItem, True, False); + if Assigned(ListItem) then begin + ListItem.Selected := True; + ListItem.Focused := True; + ListItem.MakeVisible(False); + ListView.SetFocus; + end; +end; + +procedure TTBItemEditForm.NewSubmenuButtonClick(Sender: TObject); +begin + CreateNewItem(TTBSubmenuItem); +end; + +procedure TTBItemEditForm.NewItemButtonClick(Sender: TObject); +begin + CreateNewItem(TTBItem); +end; + +procedure TTBItemEditForm.NewSepButtonClick(Sender: TObject); +begin + CreateNewItem(TTBSeparatorItem); +end; + +procedure TTBItemEditForm.MoreItemClick(Sender: TObject); +begin + CreateNewItem(TTBCustomItemClass((Sender as TTBItem).Tag)); +end; + +procedure TTBItemEditForm.CutButtonClick(Sender: TObject); +begin + Cut; +end; + +procedure TTBItemEditForm.CopyButtonClick(Sender: TObject); +begin + Copy; +end; + +procedure TTBItemEditForm.PasteButtonClick(Sender: TObject); +begin + Paste; +end; + +procedure TTBItemEditForm.DeleteButtonClick(Sender: TObject); +begin + if ActiveControl = ListView then + Delete + else if (ActiveControl = TreeView) and (FSelParentItem <> FRootItem) then + DeleteItem(FSelParentItem); +end; + +procedure TTBItemEditForm.MoveUpButtonClick(Sender: TObject); +var + SelList: TList; + I, J: Integer; + Item: TTBCustomItem; + ListItem: TListItem; +begin + if FSelParentItem = nil then Exit; + SelList := TList.Create; + try + GetSelItemList(SelList); + if SelList.Count = 0 then Exit; + + ListView.Items.BeginUpdate; + FSelParentItem.ViewBeginUpdate; + { For good performance and to prevent Object Inspector flicker, increment + FSettingSel to prevent calls to SetSelParentItem while moving items } + Inc(FSettingSel); + try + for I := 0 to SelList.Count-1 do begin + Item := SelList[I]; + J := FSelParentItem.IndexOf(Item); + if J <> -1 then + MoveItem(J, J-1); + end; + ListItem := ListView.FindData(0, SelList[0], True, False); + if Assigned(ListItem) then + ListItem.MakeVisible(False); + finally + Dec(FSettingSel); + FSelParentItem.ViewEndUpdate; + ListView.Items.EndUpdate; + end; + { After decrementing FSettingSel, now call SetSelParentItem, to update + the toolbar buttons } + SetSelParentItem(FSelParentItem); + finally + SelList.Free; + end; +end; + +procedure TTBItemEditForm.MoveDownButtonClick(Sender: TObject); +var + SelList: TList; + I, J: Integer; + Item: TTBCustomItem; + ListItem: TListItem; +begin + if FSelParentItem = nil then Exit; + SelList := TList.Create; + try + GetSelItemList(SelList); + if SelList.Count = 0 then Exit; + + ListView.Items.BeginUpdate; + FSelParentItem.ViewBeginUpdate; + { For good performance and to prevent Object Inspector flicker, increment + FSettingSel to prevent calls to SetSelParentItem while moving items } + Inc(FSettingSel); + try + for I := SelList.Count-1 downto 0 do begin + Item := SelList[I]; + J := FSelParentItem.IndexOf(Item); + if J <> -1 then + MoveItem(J, J+1); + end; + ListItem := ListView.FindData(0, SelList[SelList.Count-1], True, False); + if Assigned(ListItem) then + ListItem.MakeVisible(False); + finally + Dec(FSettingSel); + FSelParentItem.ViewEndUpdate; + ListView.Items.EndUpdate; + end; + { After decrementing FSettingSel, now call SetSelParentItem, to update + the toolbar buttons } + SetSelParentItem(FSelParentItem); + finally + SelList.Free; + end; +end; + +procedure TTBItemEditForm.TConvertMenuClick(Sender: TObject); +begin + if FSelParentItem = nil then Exit; + DoConvert(FSelParentItem, FParentComponent.Owner); +end; + + +{ TTBItemsEditor } + +procedure TTBItemsEditor.Edit; +var + Intf: ITBItems; +begin + if Assigned(Component) and Component.GetInterface(ITBItems, Intf) then + ShowEditForm(Component, Intf.GetItems, Designer); +end; + +procedure TTBItemsEditor.ExecuteVerb(Index: Integer); +begin + case Index of + 0: Edit; + 1: ShowVersion; + end; +end; + +function TTBItemsEditor.GetVerbCount: Integer; +begin + Result := 2; +end; + +function TTBItemsEditor.GetVerb(Index: Integer): String; +begin + case Index of + 0: Result := 'Edit...'; + 1: Result := 'Version...'; + else + Result := ''; + end; +end; + + +{ TTBItemsPropertyEditor } + +procedure TTBItemsPropertyEditor.Edit; +var + Editor: {$IFDEF JR_D6} IComponentEditor {$ELSE} TComponentEditor {$ENDIF}; +begin + if PropCount <> 1 then Exit; + Editor := GetComponentEditor(GetComponent(0) as TComponent, Designer); + try + Editor.Edit; + finally + {$IFNDEF JR_D6} + Editor.Free; + {$ENDIF} + end; +end; + +function TTBItemsPropertyEditor.GetAttributes: TPropertyAttributes; +begin + Result := inherited GetAttributes + [paDialog, paReadOnly]; +end; + +function TTBItemsPropertyEditor.GetValue: String; +begin + Result := '(TB2000 Items)'; +end; + + +procedure TBRegisterDsgnEditorHook(Hook: TTBDsgnEditorHook); +var + H: ^TTBDsgnEditorHook; +begin + New(H); + H^ := Hook; + EditFormHooks.Add(H); +end; + +procedure TBUnregisterDsgnEditorHook(Hook: TTBDsgnEditorHook); +var + H: ^TTBDsgnEditorHook; + I: Integer; +begin + for I := EditFormHooks.Count - 1 downto 0 do + begin + H := EditFormHooks[I]; + if (TMethod(H^).Code = TMethod(Hook).Code) and + (TMethod(H^).Data = TMethod(Hook).Data) then + begin + Dispose(H); + EditFormHooks.Delete(I); +// Break; + end; + end; +end; + +initialization + ItemImageList := TImageList.Create(nil); + ItemImageList.Handle := ImageList_LoadImage(HInstance, 'TB2_DSGNEDITORIMAGES', + 16, 0, clFuchsia, IMAGE_BITMAP, 0); + ItemClasses := TList.Create; + EditFormHooks := TList.Create; + AddModuleUnloadProc(UnregisterModuleItemClasses); +finalization + RemoveModuleUnloadProc(UnregisterModuleItemClasses); + FreeItemClasses; + FreeAndNil(ItemImageList); + FreeAndNil(EditFormHooks); +end. diff --git a/official/2.1.6+2.1.beta1/Source/TB2DsgnItemEditor.pas.orig b/official/2.1.6+2.1.beta1/Source/TB2DsgnItemEditor.pas.orig new file mode 100644 index 0000000..fc85c75 --- /dev/null +++ b/official/2.1.6+2.1.beta1/Source/TB2DsgnItemEditor.pas.orig @@ -0,0 +1,1348 @@ +unit TB2DsgnItemEditor; + +{ + Toolbar2000 + Copyright (C) 1998-2005 by Jordan Russell + All rights reserved. + + The contents of this file are subject to the "Toolbar2000 License"; you may + not use or distribute this file except in compliance with the + "Toolbar2000 License". A copy of the "Toolbar2000 License" may be found in + TB2k-LICENSE.txt or at: + http://www.jrsoftware.org/files/tb2k/TB2k-LICENSE.txt + + Alternatively, the contents of this file may be used under the terms of the + GNU General Public License (the "GPL"), in which case the provisions of the + GPL are applicable instead of those in the "Toolbar2000 License". A copy of + the GPL may be found in GPL-LICENSE.txt or at: + http://www.jrsoftware.org/files/tb2k/GPL-LICENSE.txt + If you wish to allow use of your version of this file only under the terms of + the GPL and not to allow others to use your version of this file under the + "Toolbar2000 License", indicate your decision by deleting the provisions + above and replace them with the notice and other provisions required by the + GPL. If you do not delete the provisions above, a recipient may use your + version of this file under either the "Toolbar2000 License" or the GPL. + + $jrsoftware: tb2k/Source/TB2DsgnItemEditor.pas,v 1.55 2005/01/27 06:48:53 jr Exp $ +} + +interface + +{$I TB2Ver.inc} + +uses + Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, + StdCtrls, ExtCtrls, Buttons, ComCtrls, ImgList, Menus, + TB2Item, TB2Toolbar, TB2Dock, + {$IFDEF JR_D6} + DesignIntf, DesignWindows, DesignEditors; + {$ELSE} + DsgnIntf, DsgnWnds, LibIntf; + {$ENDIF} + +type + TTBItemEditForm = class(TDesignWindow) + TreeView: TTreeView; + ListView: TListView; + Splitter1: TSplitter; + Toolbar: TTBToolbar; + NewSubmenuButton: TTBItem; + NewItemButton: TTBItem; + NewSepButton: TTBItem; + DeleteButton: TTBItem; + TBSeparatorItem1: TTBSeparatorItem; + TBPopupMenu1: TTBPopupMenu; + TBItemContainer1: TTBItemContainer; + ToolbarItems: TTBSubmenuItem; + CopyButton: TTBItem; + CutButton: TTBItem; + PasteButton: TTBItem; + MoreMenu: TTBSubmenuItem; + TBSeparatorItem2: TTBSeparatorItem; + TBSubmenuItem1: TTBSubmenuItem; + TConvertMenu: TTBItem; + TBSeparatorItem3: TTBSeparatorItem; + MoveUpButton: TTBItem; + MoveDownButton: TTBItem; + procedure FormClose(Sender: TObject; var Action: TCloseAction); + procedure TreeViewChange(Sender: TObject; Node: TTreeNode); + procedure NewSubmenuButtonClick(Sender: TObject); + procedure NewItemButtonClick(Sender: TObject); + procedure ListViewChange(Sender: TObject; Item: TListItem; + Change: TItemChange); + procedure DeleteButtonClick(Sender: TObject); + procedure NewSepButtonClick(Sender: TObject); + procedure ListViewDragOver(Sender, Source: TObject; X, Y: Integer; + State: TDragState; var Accept: Boolean); + procedure ListViewDragDrop(Sender, Source: TObject; X, Y: Integer); + procedure TreeViewEnter(Sender: TObject); + procedure TreeViewDragDrop(Sender, Source: TObject; X, Y: Integer); + procedure TreeViewDragOver(Sender, Source: TObject; X, Y: Integer; + State: TDragState; var Accept: Boolean); + procedure CopyButtonClick(Sender: TObject); + procedure ListViewKeyDown(Sender: TObject; var Key: Word; + Shift: TShiftState); + procedure CutButtonClick(Sender: TObject); + procedure PasteButtonClick(Sender: TObject); + procedure FormActivate(Sender: TObject); + procedure ListViewKeyPress(Sender: TObject; var Key: Char); + procedure ListViewDblClick(Sender: TObject); + procedure ListViewEnter(Sender: TObject); + procedure TreeViewKeyDown(Sender: TObject; var Key: Word; + Shift: TShiftState); + procedure TConvertMenuClick(Sender: TObject); + procedure TreeViewKeyPress(Sender: TObject; var Key: Char); + procedure MoveUpButtonClick(Sender: TObject); + procedure MoveDownButtonClick(Sender: TObject); + private + FParentComponent: TComponent; + FRootItem, FSelParentItem: TTBCustomItem; + FNotifyItemList: TList; + FSettingSel, FRebuildingTree, FRebuildingList: Integer; + function AddListViewItem(const Index: Integer; + const Item: TTBCustomItem): TListItem; + procedure Copy; + procedure CreateNewItem(const AClass: TTBCustomItemClass); + procedure Cut; + procedure Delete; + procedure DeleteItem(const Item: TTBCustomItem); + function GetItemTreeCaption(AItem: TTBCustomItem): String; + procedure GetSelItemList(const AList: TList); + procedure ItemNotification(Ancestor: TTBCustomItem; Relayed: Boolean; + Action: TTBItemChangedAction; Index: Integer; Item: TTBCustomItem); + procedure MoreItemClick(Sender: TObject); + procedure MoveItem(CurIndex, NewIndex: Integer); + procedure Paste; + procedure RebuildList; + procedure RebuildTree; + procedure SelectInObjectInspector(AList: TList); + procedure SetSelParentItem(ASelParentItem: TTBCustomItem); + function TreeViewDragHandler(Sender, Source: TObject; X, Y: Integer; + Drop: Boolean): Boolean; + procedure UnregisterAllNotifications; + protected + procedure Notification(AComponent: TComponent; Operation: TOperation); override; + function UniqueName(Component: TComponent): String; override; + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + {$IFDEF JR_D6} + function EditAction(Action: TEditAction): Boolean; override; + {$ELSE} + procedure EditAction(Action: TEditAction); override; + {$ENDIF} + function GetEditState: TEditState; override; + end; + + TTBItemsEditor = class(TDefaultEditor) + public + procedure Edit; override; + procedure ExecuteVerb(Index: Integer); override; + function GetVerb(Index: Integer): String; override; + function GetVerbCount: Integer; override; + end; + + TTBItemsPropertyEditor = class(TStringProperty) + public + procedure Edit; override; + function GetAttributes: TPropertyAttributes; override; + function GetValue: String; override; + end; + +procedure TBRegisterItemClass(AClass: TTBCustomItemClass; + const ACaption: String; ResInstance: HINST); + +implementation + +{$R *.DFM} + +uses + TypInfo, CommCtrl, TB2Version, TB2Common, TB2DsgnConverter; + +type + {}TTBCustomItemAccess = class(TTBCustomItem); + {}TControlAccess = class(TControl); +{$IFNDEF JR_D5} + TDesignerSelectionList = TComponentList; +{$ENDIF} +{$IFDEF JR_D6} + TDesignerSelectionList = IDesignerSelections; +{$ENDIF} + + PItemClassInfo = ^TItemClassInfo; + TItemClassInfo = record + ItemClass: TTBCustomItemClass; + Caption: String; + ImageIndex: Integer; + end; + +var + ItemClasses: TList; + ItemImageList: TImageList; + +{$IFNDEF JR_D6} +function CreateSelectionList: TDesignerSelectionList; +begin + Result := TDesignerSelectionList.Create; +end; +{$ENDIF} + +procedure FreeItemClasses; +var + I: Integer; + IC: TList; +begin + if ItemClasses = nil then Exit; + IC := ItemClasses; + ItemClasses := nil; + for I := IC.Count-1 downto 0 do + Dispose(PItemClassInfo(IC[I])); + IC.Free; +end; + +procedure UnregisterModuleItemClasses(AModule: {$IFDEF JR_D5} LongWord {$ELSE} Integer {$ENDIF}); +var + I: Integer; + Info: PItemClassInfo; +begin + I := 0; + while I < ItemClasses.Count do begin + Info := ItemClasses[I]; + if FindClassHInstance(Info.ItemClass) = AModule then begin + ItemClasses.Delete(I); + Dispose(Info); + end + else + Inc(I); + end; + { Note: TTBItemEditForm also holds references to item classes, but since + Delphi automatically closes all editor forms before compiling/removing + a package, we don't need to remove them. } +end; + +function LoadItemImage(Instance: HINST; const ResName: String): Integer; +var + Bmp: TBitmap; +begin + Bmp := TBitmap.Create; + try + Bmp.Handle := LoadBitmap(Instance, PChar(ResName)); + if Bmp.Handle = 0 then + Result := -1 + else + Result := ItemImageList.AddMasked(Bmp, Bmp.Canvas.Pixels[0, Bmp.Height-1]); + finally + Bmp.Free; + end; +end; + +procedure TBRegisterItemClass(AClass: TTBCustomItemClass; + const ACaption: String; ResInstance: HINST); +var + Info: PItemClassInfo; +begin + New(Info); + Info.ItemClass := AClass; + Info.Caption := ACaption; + Info.ImageIndex := LoadItemImage(ResInstance, Uppercase(AClass.ClassName)); + ItemClasses.Add(Info); +end; + +function GetItemClassImage(AClass: TTBCustomItemClass): Integer; +var + I: Integer; + Info: PItemClassInfo; +begin + for I := ItemClasses.Count-1 downto 0 do begin + Info := ItemClasses[I]; + if AClass.InheritsFrom(Info.ItemClass) then begin + Result := Info.ImageIndex; + if Result >= 0 then + Exit; + end; + end; + if AClass.InheritsFrom(TTBSubmenuItem) then + Result := 1 + else if AClass.InheritsFrom(TTBSeparatorItem) then + Result := 2 + else + Result := 0; +end; + +procedure ShowEditForm(AParentComponent: TComponent; ARootItem: TTBCustomItem; + const ADesigner: {$IFDEF JR_D6} IDesigner {$ELSE} IFormDesigner {$ENDIF}); +var + I: Integer; + Form: TCustomForm; + EditForm: TTBItemEditForm; +begin + if Assigned(ARootItem.LinkSubitems) then begin + case MessageDlg(Format('The LinkSubitems property is set to ''%s''. ' + + 'Would you like to edit that item instead?', + [ARootItem.LinkSubitems.Name]), mtConfirmation, [mbYes, mbNo, mbCancel], 0) of + mrYes: begin + AParentComponent := ARootItem.LinkSubitems; + ARootItem := ARootItem.LinkSubitems; + end; + mrCancel: Exit; + end; + end; + for I := 0 to Screen.FormCount-1 do begin + Form := Screen.Forms[I]; + if Form is TTBItemEditForm then + if TTBItemEditForm(Form).FRootItem = ARootItem then begin + Form.Show; + if Form.WindowState = wsMinimized then + Form.WindowState := wsNormal; + Exit; + end; + end; + EditForm := TTBItemEditForm.Create(Application); + try + EditForm.Designer := ADesigner; + EditForm.FParentComponent := AParentComponent; + AParentComponent.FreeNotification(EditForm); + EditForm.FRootItem := ARootItem; + ARootItem.FreeNotification(EditForm); + EditForm.FSelParentItem := ARootItem; + EditForm.Caption := 'Editing ' + AParentComponent.Name; + EditForm.RebuildTree; + EditForm.RebuildList; + {$IFDEF JR_D9} + EditForm.PopupMode := pmExplicit; + {$ENDIF} + EditForm.Show; + except + EditForm.Free; + raise; + end; +end; + +function IsSubmenuItem(Item: TTBCustomItem): Boolean; +begin + Result := tbisSubitemsEditable in TTBCustomItemAccess(Item).ItemStyle; +end; + +procedure ShowVersion; +const + AboutText = + '%s'#13#10 + + 'Copyright (C) 1998-2005 by Jordan Russell'#13#10 + + 'For conditions of distribution and use, see LICENSE.TXT.'#13#10 + + #13#10 + + 'Visit my web site for the latest versions of Toolbar2000:'#13#10 + + 'http://www.jrsoftware.org/'; +begin + MessageDlg(Format(AboutText, [Toolbar2000VersionPropText]), mtInformation, + [mbOK], 0); +end; + + +{ TTBItemEditForm } + +constructor TTBItemEditForm.Create(AOwner: TComponent); +var + I: Integer; + Info: PItemClassInfo; + Item: TTBItem; +begin + inherited; + FNotifyItemList := TList.Create; + ToolbarItems.SubMenuImages := ItemImageList; + ListView.SmallImages := ItemImageList; + { Populate the 'More' menu } + for I := 0 to ItemClasses.Count-1 do begin + Info := ItemClasses[I]; + Item := TTBItem.Create(Self); + Item.Caption := Info.Caption; + Item.ImageIndex := GetItemClassImage(Info.ItemClass); + Item.Tag := Integer(Info.ItemClass); + Item.OnClick := MoreItemClick; + MoreMenu.Add(Item); + end; +end; + +destructor TTBItemEditForm.Destroy; +begin + inherited; + if Assigned(FNotifyItemList) then begin + UnregisterAllNotifications; + FNotifyItemList.Free; + FNotifyItemList := nil; + end; +end; + +procedure TTBItemEditForm.FormClose(Sender: TObject; + var Action: TCloseAction); +begin + Action := caFree; +end; + +procedure TTBItemEditForm.FormActivate(Sender: TObject); +begin + SetSelParentItem(FSelParentItem); +end; + +procedure TTBItemEditForm.Notification(AComponent: TComponent; + Operation: TOperation); +begin + inherited; + if (Operation = opRemove) and + ((AComponent = FParentComponent) or (AComponent = FRootItem)) then + { Must use Free instead of Close, since Close causes the freeing of the + form to be delayed until the next message. We have to destroy the form + immediately, otherwise Delphi will crash when Compile is clicked on the + TB2k package. } + Free; + {}{temp:} + (*if (Operation = opRemove) and (FNotifyItemList.IndexOf(AComponent) <> -1) then begin + outputdebugstring(pchar('Still in list: ' + AComponent.name)); + //beep; + end;*) +end; + +function TTBItemEditForm.UniqueName(Component: TComponent): String; +begin + Result := Designer.UniqueName(Component.ClassName); +end; + +function TTBItemEditForm.GetEditState: TEditState; +begin + Result := []; + if ActiveControl = ListView then begin + if Assigned(ListView.Selected) then + Result := [esCanDelete, esCanCut, esCanCopy]; + if ClipboardComponents then + Include(Result, esCanPaste); + end; +end; + +{$IFDEF JR_D6} +function TTBItemEditForm.EditAction(Action: TEditAction): Boolean; +{$ELSE} +procedure TTBItemEditForm.EditAction(Action: TEditAction); +{$ENDIF} +begin + {$IFDEF JR_D6} + Result := True; + {$ENDIF} + case Action of + eaCut: Cut; + eaCopy: Copy; + eaPaste: Paste; + eaDelete: Delete; + {$IFDEF JR_D6} + else + Result := False; + {$ENDIF} + end; +end; + +procedure TTBItemEditForm.UnregisterAllNotifications; +var + I: Integer; +begin + for I := FNotifyItemList.Count-1 downto 0 do begin + //outputdebugstring(pchar('Unregall: ' + TTBCustomItem(FNotifyItemList[I]).name)); + TTBCustomItem(FNotifyItemList[I]).UnregisterNotification(ItemNotification); + FNotifyItemList.Delete(I); + end; +end; + +procedure TTBItemEditForm.ItemNotification(Ancestor: TTBCustomItem; + Relayed: Boolean; Action: TTBItemChangedAction; Index: Integer; + Item: TTBCustomItem); +var + ListItem: TListItem; + TreeNode: TTreeNode; + I: Integer; + C: String; +begin + { Manipulate the list view when items are inserted, deleted, or their Caption + changes } + case Action of + tbicInserted: + begin + if (Ancestor = FSelParentItem) and not Relayed then + AddListViewItem(Index, Item); + if IsSubmenuItem(Item) then + RebuildTree; + end; + tbicDeleting: + if (Ancestor = FSelParentItem) and not Relayed then begin + ListItem := ListView.FindData(0, Item, True, False); + if Assigned(ListItem) then + ListItem.Delete; + end; + tbicInvalidateAndResize: + if (Ancestor = FSelParentItem) and not Relayed then begin + ListItem := ListView.FindData(0, Item, True, False); + if Assigned(ListItem) and (ListItem.Caption <> TTBCustomItem(Item).Caption) then + ListItem.Caption := TTBCustomItem(Item).Caption; + end; + end; + { Update tree view when an item is deleted, or a Caption changes } + if Action = tbicDeleting then begin + I := FNotifyItemList.IndexOf(Item); + if I <> -1 then begin + //outputdebugstring(pchar('Deleting, so unreging: ' + item.name)); + TTBCustomItem(Item).UnregisterNotification(ItemNotification); + FNotifyItemList.Delete(I); + end; + end; + if Action in [tbicDeleting, tbicInvalidateAndResize, tbicNameChanged] then begin + TreeNode := TreeView.Items.GetFirstNode; + while Assigned(TreeNode) do begin + if TreeNode.Data = Item then begin + if Action = tbicDeleting then begin + TreeNode.Delete; + if FSelParentItem = Item then + SetSelParentItem(TTBCustomItem(Item).Parent); + end + else begin + { tbicInvalidateAndResize, tbicNameChanged: } + C := GetItemTreeCaption(Item); + if TreeNode.Text <> C then + TreeNode.Text := C; + end; + Break; + end; + TreeNode := TreeNode.GetNext; + end; + end; +end; + +function TTBItemEditForm.GetItemTreeCaption(AItem: TTBCustomItem): String; +begin + if AItem <> FRootItem then begin + Result := AItem.Caption; + if Result = '' then + Result := '[' + AItem.Name + ']'; + end + else + Result := '(Root)'; +end; + +procedure TTBItemEditForm.RebuildTree; + + procedure Recurse(const AParentItem: TTBCustomItem; const ATreeNode: TTreeNode; + var FoundSelParentItem: TTreeNode); + var + I: Integer; + NewNode: TTreeNode; + ChildItem: TTBCustomItem; + begin + {}AParentItem.FreeNotification(Self); + AParentItem.RegisterNotification(ItemNotification); + FNotifyItemList.Add(AParentItem); + NewNode := TreeView.Items.AddChild(ATreeNode, GetItemTreeCaption(AParentItem)); + NewNode.Data := AParentItem; + if AParentItem = FSelParentItem then + FoundSelParentItem := NewNode; + for I := 0 to AParentItem.Count-1 do begin + ChildItem := AParentItem[I]; + if IsSubmenuItem(ChildItem) then + Recurse(ChildItem, NewNode, FoundSelParentItem); + end; + end; + +var + FoundSelParentItem: TTreeNode; +begin + Inc(FRebuildingTree); + try + TreeView.Items.BeginUpdate; + try + TreeView.Items.Clear; + UnregisterAllNotifications; + FoundSelParentItem := nil; + Recurse(FRootItem, nil, FoundSelParentItem); + if FoundSelParentItem = nil then + SetSelParentItem(FRootItem) + else + TreeView.Selected := FoundSelParentItem; + TreeView.Items[0].Expand(True); + finally + TreeView.Items.EndUpdate; + end; + finally + Dec(FRebuildingTree); + end; +end; + +function TTBItemEditForm.AddListViewItem(const Index: Integer; + const Item: TTBCustomItem): TListItem; +begin + Result := ListView.Items.Insert(Index); + Result.Data := Item; + if not(Item is TTBControlItem) then begin + Result.Caption := Item.Caption; + Result.Subitems.Add(Item.ClassName); + Result.ImageIndex := GetItemClassImage(TTBCustomItemClass(Item.ClassType)); + end + else begin + Result.Caption := '(Control)'; + Result.Subitems.Add(Item.ClassName); + Result.ImageIndex := -1; + end; +end; + +procedure TTBItemEditForm.RebuildList; +var + ChildItem: TTBCustomItem; + I: Integer; +begin + Inc(FRebuildingList); + try + ListView.Items.BeginUpdate; + try + ListView.Items.Clear; + if Assigned(FSelParentItem) then begin + for I := 0 to FSelParentItem.Count-1 do begin + ChildItem := FSelParentItem[I]; + { Check for csDestroying because deleting an item in the tree view + causes the parent item to be selected, and the parent item won't + get a notification that the item is deleting since notifications + were already sent } + if not(csDestroying in ChildItem.ComponentState) then + AddListViewItem(I, ChildItem); + end; + { Add an empty item to the end } + ListView.Items.Add.ImageIndex := -1; + end; + finally + ListView.Items.EndUpdate; + end; + { Work around a strange TListView bug(?). Without this, the column header + isn't painted properly. } + if HandleAllocated then + SetWindowPos(ListView.Handle, 0, 0, 0, 0, 0, SWP_FRAMECHANGED or + SWP_NOACTIVATE or SWP_NOMOVE or SWP_NOSIZE or SWP_NOZORDER); + finally + Dec(FRebuildingList); + end; +end; + +procedure TTBItemEditForm.SelectInObjectInspector(AList: TList); +var + CompList1, CompList2: TDesignerSelectionList; + I: Integer; + C: TComponent; +begin + { Designer.SetSelections will make components appear selected on the form. + It will also select the component in Object Inspector, but only if the + form has the focus. TDesignWindow.SetSelection will select the component + in Object Inspector regardless of whether the form has the focus. } + CompList1 := CreateSelectionList; + CompList2 := CreateSelectionList; + for I := 0 to AList.Count-1 do begin + C := AList[I]; + { Must check for csDestroying. If SetSelection is passed a component that's + destroying, Delphi will crash. } + if not(csDestroying in C.ComponentState) then begin + CompList1.Add(C); + CompList2.Add(C); + end; + end; + if CompList1.Count = 0 then begin + {$IFNDEF JR_D6} + CompList1.Free; + CompList2.Free; + {$ENDIF} + end + else begin + Designer.SetSelections(CompList1); + { Note: Never pass an empty list to SetSelection or Delphi will crash } + { History here: + - 1.34: SetSelection call remarked out because it fixed Delphi 6 issue + with random AV's after the editor was closed. + - 1.38: SetSelection call restored because without it, Ctrl+X/C/V didn't + work. + - 1.40: SetSelection call disabled on Delphi 6 only because AV problem + still seems to exist despite another change which I thought fixed it. + On D6 it isn't necessary to call SetSelection for Ctrl+X/C/V to work. + Note: Using "ComponentDesigner.SetSelection(Designer, nil, CompList2);" + instead seems to fix the AV problem, but for consistency with Delphi's + TMainMenu editor (which only selects items when its parent form is + focused), I decided not to call SetSelection at all on D6. + } + {$IFNDEF JR_D6} + SetSelection(CompList2); + {$ENDIF} + end; +end; + +procedure TTBItemEditForm.GetSelItemList(const AList: TList); +var + ListItem: TListItem; +begin + ListItem := nil; + while True do begin + ListItem := ListView.GetNextItem(ListItem, sdAll, [isSelected]); + if ListItem = nil then + Break; + if Assigned(ListItem.Data) then + AList.Add(ListItem.Data); + end; +end; + +procedure TTBItemEditForm.SetSelParentItem(ASelParentItem: TTBCustomItem); +{ - Rebuilds the list view to match a new selection (ASelParentItem) in the + tree view + - Updates toolbar + - Selects selected item(s) into Object Inspector } +var + I: Integer; + TreeNode: TTreeNode; + ItemIsSelected: Boolean; + List: TList; +begin + if FSettingSel > 0 then + Exit; + List := TList.Create; + Inc(FSettingSel); + try + if FSelParentItem <> ASelParentItem then begin + FSelParentItem := ASelParentItem; + NewSubmenuButton.Enabled := Assigned(ASelParentItem); + NewItemButton.Enabled := Assigned(ASelParentItem); + NewSepButton.Enabled := Assigned(ASelParentItem); + for I := 0 to MoreMenu.Count-1 do + MoreMenu[I].Enabled := Assigned(ASelParentItem); + if not Assigned(TreeView.Selected) or (TreeView.Selected.Data <> FSelParentItem) then begin + if FSelParentItem = nil then + TreeView.Selected := nil + else begin + TreeNode := TreeView.Items.GetFirstNode; + while Assigned(TreeNode) do begin + if TreeNode.Data = FSelParentItem then begin + TreeView.Selected := TreeNode; + Break; + end; + TreeNode := TreeNode.GetNext; + end; + end; + end; + RebuildList; + end; + + ItemIsSelected := (ActiveControl = ListView) and Assigned(ListView.Selected) and + Assigned(ListView.Selected.Data); + if ItemIsSelected then + GetSelItemList(List); + + CutButton.Enabled := ItemIsSelected; + CopyButton.Enabled := ItemIsSelected; + PasteButton.Enabled := (ActiveControl = ListView); + DeleteButton.Enabled := ItemIsSelected or + ((ActiveControl = TreeView) and (FSelParentItem <> FRootItem)); + MoveUpButton.Enabled := ItemIsSelected and + (FSelParentItem.IndexOf(List.First) > 0); + MoveDownButton.Enabled := ItemIsSelected and + (FSelParentItem.IndexOf(List.Last) < FSelParentItem.Count-1); + + if ActiveControl = ListView then begin + if List.Count = 0 then + { No item was selected, or the blank item was selected. + Select the root item so it looks like no item was selected in + Object Inspector } + List.Add(FRootItem); + end + else if not Assigned(ASelParentItem) or (ASelParentItem = FRootItem) then + List.Add(FParentComponent) + else + List.Add(ASelParentItem); + SelectInObjectInspector(List); + finally + Dec(FSettingSel); + List.Free; + end; +end; + +procedure TTBItemEditForm.Cut; +begin + Copy; + Delete; +end; + +procedure TTBItemEditForm.Copy; +var + SelList: TList; + CompList: TDesignerSelectionList; + I: Integer; + Item: TTBCustomItem; +begin + if ListView.Selected = nil then Exit; + CompList := nil; + SelList := TList.Create; + try + GetSelItemList(SelList); + CompList := CreateSelectionList; + for I := 0 to SelList.Count-1 do begin + Item := SelList[I]; + if Item is TTBControlItem then + raise EInvalidOperation.Create('Cannot cut or copy TTBControlItems'); + CompList.Add(Item); + end; + CopyComponents(FParentComponent.Owner, CompList); + finally + {$IFNDEF JR_D6} + CompList.Free; + {$ENDIF} + SelList.Free; + end; +end; + +procedure TTBItemEditForm.Paste; +var + CompList: TDesignerSelectionList; +begin + if FSelParentItem = nil then Exit; + CompList := CreateSelectionList; + try + PasteComponents(FParentComponent.Owner, FSelParentItem, CompList); + if CompList.Count <> 0 then + Designer.Modified; + finally + {$IFNDEF JR_D6} + CompList.Free; + {$ENDIF} + end; +end; + +procedure TTBItemEditForm.DeleteItem(const Item: TTBCustomItem); +begin + if csAncestor in Item.ComponentState then + raise EInvalidOperation.Create('Items introduced in an ancestor form cannot be deleted'); + //Designer.ValidateRename(Item, Item.Name, ''); + Item.Free; + Designer.Modified; +end; + +procedure TTBItemEditForm.Delete; +var + List: TList; + Item: TTBCustomItem; + ListItem: TListItem; +begin + List := TList.Create; + try + List.Add(FSelParentItem); + SelectInObjectInspector(List); + finally + List.Free; + end; + FSelParentItem.ViewBeginUpdate; + try + while Assigned(ListView.Selected) do begin + Item := ListView.Selected.Data; + if Item = nil then + Break; + DeleteItem(Item); + end; + finally + FSelParentItem.ViewEndUpdate; + end; + { After deleting the items, select the item with the focus } + ListItem := ListView.GetNextItem(nil, sdAll, [isFocused]); + if Assigned(ListItem) then + ListItem.Selected := True; +end; + +procedure TTBItemEditForm.MoveItem(CurIndex, NewIndex: Integer); +var + WasFocused: Boolean; +begin + WasFocused := ListView.Items[CurIndex].Focused; + + FSelParentItem.Move(CurIndex, NewIndex); + Designer.Modified; + + if WasFocused then + ListView.Items[NewIndex].Focused := True; + ListView.Items[NewIndex].Selected := True; +end; + +procedure TTBItemEditForm.TreeViewChange(Sender: TObject; Node: TTreeNode); +var + NewSelectedParentItem: TTBCustomItem; +begin + if (FRebuildingTree > 0) or (FSettingSel > 0) then Exit; + if Node = nil then + NewSelectedParentItem := nil + else + NewSelectedParentItem := Node.Data; + SetSelParentItem(NewSelectedParentItem); +end; + +procedure TTBItemEditForm.TreeViewEnter(Sender: TObject); +{ When the tree view gets the focus, act as if the currently selected item + was clicked. } +begin + ListView.Selected := nil; + SetSelParentItem(FSelParentItem); +end; + +procedure TTBItemEditForm.ListViewChange(Sender: TObject; Item: TListItem; + Change: TItemChange); +begin + if (FRebuildingList > 0) or (FSettingSel > 0) or (Change <> ctState) or + (csDestroying in ListView.ComponentState) then + Exit; + SetSelParentItem(FSelParentItem); +end; + +procedure TTBItemEditForm.ListViewEnter(Sender: TObject); +begin + { When list view gets the focus, update the toolbar } + SetSelParentItem(FSelParentItem); +end; + +procedure TTBItemEditForm.ListViewDblClick(Sender: TObject); +var + SelItem: TTBCustomItem; + PropCount, I: Integer; + Props: PPropList; + PropInfo: PPropInfo; + MethodName: String; + Method: TMethod; +begin + SelItem := nil; + if Assigned(ListView.Selected) then + SelItem := ListView.Selected.Data; + if SelItem = nil then Exit; + if IsSubmenuItem(SelItem) then begin + SetSelParentItem(SelItem); + Exit; + end; + PropCount := GetPropList(SelItem.ClassInfo, [tkMethod], nil); + GetMem(Props, PropCount * SizeOf(PPropInfo)); + try + GetPropList(SelItem.ClassInfo, [tkMethod], Props); + for I := PropCount-1 downto 0 do begin + PropInfo := Props[I]; + if CompareText(PropInfo.Name, 'OnClick') = 0 then begin + Method := GetMethodProp(SelItem, PropInfo); + MethodName := Designer.GetMethodName(Method); + if MethodName = '' then begin + MethodName := SelItem.Name + 'Click'; + Method := Designer.CreateMethod(MethodName, GetTypeData(PropInfo.PropType^)); + SetMethodProp(SelItem, + {$IFDEF JR_D5} PropInfo.Name {$ELSE} PropInfo {$ENDIF}, + Method); + Designer.Modified; + end; + if Designer.MethodExists(MethodName) then + Designer.ShowMethod(MethodName); + Break; + end; + end; + finally + FreeMem(Props); + end; +end; + +procedure TTBItemEditForm.ListViewKeyDown(Sender: TObject; var Key: Word; + Shift: TShiftState); +begin + case Key of + VK_RETURN: begin + Key := 0; + ActivateInspector(#0); + end; + VK_INSERT: begin + Key := 0; + if ssCtrl in Shift then + NewSubmenuButtonClick(Sender) + else + NewItemButtonClick(Sender); + end; + VK_DELETE: begin + Key := 0; + Delete; + end; + end; +end; + +procedure TTBItemEditForm.TreeViewKeyDown(Sender: TObject; var Key: Word; + Shift: TShiftState); +begin + case Key of + VK_RETURN: begin + Key := 0; + ActivateInspector(#0); + end; + VK_DELETE: begin + Key := 0; + DeleteButtonClick(Sender); + end; + end; +end; + +procedure TTBItemEditForm.TreeViewKeyPress(Sender: TObject; var Key: Char); +begin + if Key in [#33..#126] then begin + ActivateInspector(Key); + Key := #0; + end + else if Key = #13 then + Key := #0; { suppress beep } +end; + +procedure TTBItemEditForm.ListViewKeyPress(Sender: TObject; var Key: Char); +begin + if Key = '-' then begin + NewSepButtonClick(Sender); + Key := #0; + end + else if Key in [#33..#126] then begin + ActivateInspector(Key); + Key := #0; + end; +end; + +procedure TTBItemEditForm.ListViewDragOver(Sender, Source: TObject; X, + Y: Integer; State: TDragState; var Accept: Boolean); +{ List item dragged over the list view } +var + Item: TListItem; +begin + Accept := False; + if (Sender = ListView) and (Source = ListView) and (ListView.SelCount = 1) then begin + Item := ListView.GetItemAt(X, Y); + if Assigned(Item) and (Item <> ListView.Selected) then + Accept := True; + end; +end; + +procedure TTBItemEditForm.ListViewDragDrop(Sender, Source: TObject; X, + Y: Integer); +{ List item dropped onto another list item } +var + ListItem: TListItem; + Item: TTBCustomItem; + NewIndex: Integer; +begin + if (Sender = ListView) and (Source = ListView) and (ListView.SelCount = 1) then begin + ListItem := ListView.GetItemAt(X, Y); + if Assigned(ListItem) and (ListItem <> ListView.Selected) and Assigned(FSelParentItem) then begin + NewIndex := FSelParentItem.IndexOf(ListItem.Data); + if NewIndex <> -1 then begin + ListView.Items.BeginUpdate; + { For good performance and to prevent Object Inspector flicker, increment + FSettingSel to prevent calls to SetSelParentItem while moving items } + Inc(FSettingSel); + try + Item := ListView.Selected.Data; + MoveItem(FSelParentItem.IndexOf(Item), NewIndex); + finally + Dec(FSettingSel); + ListView.Items.EndUpdate; + end; + { After decrementing FSettingSel, now call SetSelParentItem, to update + the toolbar buttons } + SetSelParentItem(FSelParentItem); + end; + end; + end; +end; + +function TTBItemEditForm.TreeViewDragHandler(Sender, Source: TObject; + X, Y: Integer; Drop: Boolean): Boolean; +var + Node: TTreeNode; + ListItem: TListItem; + Item, NewParentItem: TTBCustomItem; + ItemList: TList; + I: Integer; + NeedRebuildTree: Boolean; +begin + Result := False; + if (Sender = TreeView) and (Source = ListView) then begin + Node := TreeView.GetNodeAt(X, Y); + if Assigned(Node) and (Node <> TreeView.Selected) then begin + NewParentItem := Node.Data; + ItemList := TList.Create; + try + ListItem := nil; + while True do begin + ListItem := ListView.GetNextItem(ListItem, sdAll, [isSelected]); + if ListItem = nil then + Break; + Item := ListItem.Data; + if Assigned(Item) and (Item <> NewParentItem) and + not Item.ContainsItem(NewParentItem) and + not(Item is TTBControlItem) then begin + Result := True; + ItemList.Add(Item); + end; + end; + if Drop then begin + NeedRebuildTree := False; + for I := 0 to ItemList.Count-1 do begin + Item := ItemList[I]; + Item.Parent.Remove(Item); + NewParentItem.Add(Item); + Designer.Modified; + if IsSubmenuItem(Item) then + NeedRebuildTree := True; + end; + if NeedRebuildTree then + RebuildTree; + end; + finally + ItemList.Free; + end; + end; + end; +end; + +procedure TTBItemEditForm.TreeViewDragOver(Sender, Source: TObject; X, + Y: Integer; State: TDragState; var Accept: Boolean); +{ List item dragged over the tree view } +begin + Accept := TreeViewDragHandler(Sender, Source, X, Y, False); +end; + +procedure TTBItemEditForm.TreeViewDragDrop(Sender, Source: TObject; X, + Y: Integer); +{ List item dropped onto the tree view } +begin + TreeViewDragHandler(Sender, Source, X, Y, True); +end; + +procedure TTBItemEditForm.CreateNewItem(const AClass: TTBCustomItemClass); +var + NewIndex: Integer; + NewItem: TTBCustomItem; + ListItem: TListItem; +begin + if FSelParentItem = nil then Exit; + NewIndex := -1; + if (GetKeyState(VK_SHIFT) >= 0) and Assigned(ListView.Selected) then + NewIndex := FSelParentItem.IndexOf(ListView.Selected.Data); + if NewIndex = -1 then + NewIndex := FSelParentItem.Count; + NewItem := AClass.Create(FParentComponent.Owner{Designer.Form}); + try + NewItem.Name := Designer.UniqueName(NewItem.ClassName); + FSelParentItem.Insert(NewIndex, NewItem); + except + NewItem.Free; + raise; + end; + Designer.Modified; + ListView.Selected := nil; + ListItem := ListView.FindData(0, NewItem, True, False); + if Assigned(ListItem) then begin + ListItem.Selected := True; + ListItem.Focused := True; + ListItem.MakeVisible(False); + ListView.SetFocus; + end; +end; + +procedure TTBItemEditForm.NewSubmenuButtonClick(Sender: TObject); +begin + CreateNewItem(TTBSubmenuItem); +end; + +procedure TTBItemEditForm.NewItemButtonClick(Sender: TObject); +begin + CreateNewItem(TTBItem); +end; + +procedure TTBItemEditForm.NewSepButtonClick(Sender: TObject); +begin + CreateNewItem(TTBSeparatorItem); +end; + +procedure TTBItemEditForm.MoreItemClick(Sender: TObject); +begin + CreateNewItem(TTBCustomItemClass((Sender as TTBItem).Tag)); +end; + +procedure TTBItemEditForm.CutButtonClick(Sender: TObject); +begin + Cut; +end; + +procedure TTBItemEditForm.CopyButtonClick(Sender: TObject); +begin + Copy; +end; + +procedure TTBItemEditForm.PasteButtonClick(Sender: TObject); +begin + Paste; +end; + +procedure TTBItemEditForm.DeleteButtonClick(Sender: TObject); +begin + if ActiveControl = ListView then + Delete + else if (ActiveControl = TreeView) and (FSelParentItem <> FRootItem) then + DeleteItem(FSelParentItem); +end; + +procedure TTBItemEditForm.MoveUpButtonClick(Sender: TObject); +var + SelList: TList; + I, J: Integer; + Item: TTBCustomItem; + ListItem: TListItem; +begin + if FSelParentItem = nil then Exit; + SelList := TList.Create; + try + GetSelItemList(SelList); + if SelList.Count = 0 then Exit; + + ListView.Items.BeginUpdate; + FSelParentItem.ViewBeginUpdate; + { For good performance and to prevent Object Inspector flicker, increment + FSettingSel to prevent calls to SetSelParentItem while moving items } + Inc(FSettingSel); + try + for I := 0 to SelList.Count-1 do begin + Item := SelList[I]; + J := FSelParentItem.IndexOf(Item); + if J <> -1 then + MoveItem(J, J-1); + end; + ListItem := ListView.FindData(0, SelList[0], True, False); + if Assigned(ListItem) then + ListItem.MakeVisible(False); + finally + Dec(FSettingSel); + FSelParentItem.ViewEndUpdate; + ListView.Items.EndUpdate; + end; + { After decrementing FSettingSel, now call SetSelParentItem, to update + the toolbar buttons } + SetSelParentItem(FSelParentItem); + finally + SelList.Free; + end; +end; + +procedure TTBItemEditForm.MoveDownButtonClick(Sender: TObject); +var + SelList: TList; + I, J: Integer; + Item: TTBCustomItem; + ListItem: TListItem; +begin + if FSelParentItem = nil then Exit; + SelList := TList.Create; + try + GetSelItemList(SelList); + if SelList.Count = 0 then Exit; + + ListView.Items.BeginUpdate; + FSelParentItem.ViewBeginUpdate; + { For good performance and to prevent Object Inspector flicker, increment + FSettingSel to prevent calls to SetSelParentItem while moving items } + Inc(FSettingSel); + try + for I := SelList.Count-1 downto 0 do begin + Item := SelList[I]; + J := FSelParentItem.IndexOf(Item); + if J <> -1 then + MoveItem(J, J+1); + end; + ListItem := ListView.FindData(0, SelList[SelList.Count-1], True, False); + if Assigned(ListItem) then + ListItem.MakeVisible(False); + finally + Dec(FSettingSel); + FSelParentItem.ViewEndUpdate; + ListView.Items.EndUpdate; + end; + { After decrementing FSettingSel, now call SetSelParentItem, to update + the toolbar buttons } + SetSelParentItem(FSelParentItem); + finally + SelList.Free; + end; +end; + +procedure TTBItemEditForm.TConvertMenuClick(Sender: TObject); +begin + if FSelParentItem = nil then Exit; + DoConvert(FSelParentItem, FParentComponent.Owner); +end; + + +{ TTBItemsEditor } + +procedure TTBItemsEditor.Edit; +var + Intf: ITBItems; +begin + if Assigned(Component) and Component.GetInterface(ITBItems, Intf) then + ShowEditForm(Component, Intf.GetItems, Designer); +end; + +procedure TTBItemsEditor.ExecuteVerb(Index: Integer); +begin + case Index of + 0: Edit; + 1: ShowVersion; + end; +end; + +function TTBItemsEditor.GetVerbCount: Integer; +begin + Result := 2; +end; + +function TTBItemsEditor.GetVerb(Index: Integer): String; +begin + case Index of + 0: Result := 'Edit...'; + 1: Result := 'Version...'; + else + Result := ''; + end; +end; + + +{ TTBItemsPropertyEditor } + +procedure TTBItemsPropertyEditor.Edit; +var + Editor: {$IFDEF JR_D6} IComponentEditor {$ELSE} TComponentEditor {$ENDIF}; +begin + if PropCount <> 1 then Exit; + Editor := GetComponentEditor(GetComponent(0) as TComponent, Designer); + try + Editor.Edit; + finally + {$IFNDEF JR_D6} + Editor.Free; + {$ENDIF} + end; +end; + +function TTBItemsPropertyEditor.GetAttributes: TPropertyAttributes; +begin + Result := inherited GetAttributes + [paDialog, paReadOnly]; +end; + +function TTBItemsPropertyEditor.GetValue: String; +begin + Result := '(TB2000 Items)'; +end; + +initialization + ItemImageList := TImageList.Create(nil); + ItemImageList.Handle := ImageList_LoadImage(HInstance, 'TB2_DSGNEDITORIMAGES', + 16, 0, clFuchsia, IMAGE_BITMAP, 0); + ItemClasses := TList.Create; + AddModuleUnloadProc(UnregisterModuleItemClasses); +finalization + RemoveModuleUnloadProc(UnregisterModuleItemClasses); + FreeItemClasses; + FreeAndNil(ItemImageList); +end. diff --git a/official/2.1.6+2.1.beta1/Source/TB2DsgnItemEditor.res b/official/2.1.6+2.1.beta1/Source/TB2DsgnItemEditor.res new file mode 100644 index 0000000..938763e Binary files /dev/null and b/official/2.1.6+2.1.beta1/Source/TB2DsgnItemEditor.res differ diff --git a/official/2.1.6+2.1.beta1/Source/TB2ExtItems.pas b/official/2.1.6+2.1.beta1/Source/TB2ExtItems.pas new file mode 100644 index 0000000..606d6e4 --- /dev/null +++ b/official/2.1.6+2.1.beta1/Source/TB2ExtItems.pas @@ -0,0 +1,1008 @@ +unit TB2ExtItems; + +{ + Toolbar2000 + Copyright (C) 1998-2005 by Jordan Russell + All rights reserved. + + The contents of this file are subject to the "Toolbar2000 License"; you may + not use or distribute this file except in compliance with the + "Toolbar2000 License". A copy of the "Toolbar2000 License" may be found in + TB2k-LICENSE.txt or at: + http://www.jrsoftware.org/files/tb2k/TB2k-LICENSE.txt + + Alternatively, the contents of this file may be used under the terms of the + GNU General Public License (the "GPL"), in which case the provisions of the + GPL are applicable instead of those in the "Toolbar2000 License". A copy of + the GPL may be found in GPL-LICENSE.txt or at: + http://www.jrsoftware.org/files/tb2k/GPL-LICENSE.txt + If you wish to allow use of your version of this file only under the terms of + the GPL and not to allow others to use your version of this file under the + "Toolbar2000 License", indicate your decision by deleting the provisions + above and replace them with the notice and other provisions required by the + GPL. If you do not delete the provisions above, a recipient may use your + version of this file under either the "Toolbar2000 License" or the GPL. + + $jrsoftware: tb2k/Source/TB2ExtItems.pas,v 1.63 2005/07/04 02:49:52 jr Exp $ +} + +interface + +{$I TB2Ver.inc} + +uses + Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, + StdCtrls, CommCtrl, Menus, ActnList, + TB2Item; + +type + TTBEditItemOption = (tboUseEditWhenVertical); + TTBEditItemOptions = set of TTBEditItemOption; + +const + EditItemDefaultEditOptions = []; + EditItemDefaultEditWidth = 64; + +{ Change reasons for TTBEditItem.Text property } + tcrSetProperty = 0; // direct assignment to TTBEditItem.Text property + tcrActionLink = 1; // change comes from an action link + tcrEditControl = 2; // change is caused by typing in edit area + +type + TTBEditItem = class; + TTBEditItemViewer = class; + + TTBAcceptTextEvent = procedure(Sender: TObject; var NewText: String; + var Accept: Boolean) of object; + TTBBeginEditEvent = procedure(Sender: TTBEditItem; Viewer: TTBEditItemViewer; + EditControl: TEdit) of object; + + TTBEditAction = class(TAction) + private + FEditOptions: TTBEditItemOptions; + FEditCaption: String; + FEditWidth: Integer; + FOnAcceptText: TTBAcceptTextEvent; + FText: String; + procedure SetEditCaption(Value: String); + procedure SetEditOptions(Value: TTBEditItemOptions); + procedure SetEditWidth(Value: Integer); + procedure SetOnAcceptText(Value: TTBAcceptTextEvent); + procedure SetText(Value: String); + public + constructor Create(AOwner: TComponent); override; + published + property EditCaption: String read FEditCaption write SetEditCaption; + property EditOptions: TTBEditItemOptions read FEditOptions write SetEditOptions default EditItemDefaultEditOptions; + property EditWidth: Integer read FEditWidth write SetEditWidth default EditItemDefaultEditWidth; + property Text: String read FText write SetText; + + property OnAcceptText: TTBAcceptTextEvent read FOnAcceptText write SetOnAcceptText; + end; + + TTBEditItemActionLink = class(TTBCustomItemActionLink) + protected + procedure AssignClient(AClient: TObject); override; + function IsEditCaptionLinked: Boolean; virtual; + function IsEditOptionsLinked: Boolean; virtual; + function IsEditWidthLinked: Boolean; virtual; + function IsOnAcceptTextLinked: Boolean; virtual; + function IsTextLinked: Boolean; virtual; + procedure SetEditCaption(const Value: String); virtual; + procedure SetEditOptions(Value: TTBEditItemOptions); virtual; + procedure SetEditWidth(const Value: Integer); virtual; + procedure SetOnAcceptText(Value: TTBAcceptTextEvent); virtual; + procedure SetText(const Value: String); virtual; + end; + + TTBEditItem = class(TTBCustomItem) + private + FCharCase: TEditCharCase; + FEditCaption: String; + FEditOptions: TTBEditItemOptions; + FEditWidth: Integer; + FExtendedAccept: Boolean; + FMaxLength: Integer; + FOnAcceptText: TTBAcceptTextEvent; + FOnBeginEdit: TTBBeginEditEvent; + FText: String; + function IsEditCaptionStored: Boolean; + function IsEditOptionsStored: Boolean; + function IsEditWidthStored: Boolean; + function IsTextStored: Boolean; + procedure SetCharCase(Value: TEditCharCase); + procedure SetEditCaption(Value: String); + procedure SetEditOptions(Value: TTBEditItemOptions); + procedure SetEditWidth(Value: Integer); + procedure SetMaxLength(Value: Integer); + procedure SetText(Value: String); + protected + procedure ActionChange(Sender: TObject; CheckDefaults: Boolean); override; + function DoAcceptText(var NewText: string): Boolean; virtual; + procedure DoBeginEdit(Viewer: TTBEditItemViewer); virtual; + procedure DoTextChanging(const OldText: String; var NewText: String; Reason: Integer); virtual; + procedure DoTextChanged(Reason: Integer); virtual; + function GetActionLinkClass: TTBCustomItemActionLinkClass; override; + function GetItemViewerClass(AView: TTBView): TTBItemViewerClass; override; + function NeedToRecreateViewer(AViewer: TTBItemViewer): Boolean; override; + property ExtendedAccept: Boolean read FExtendedAccept write FExtendedAccept default False; + procedure SetTextEx(Value: String; Reason: Integer); + public + constructor Create(AOwner: TComponent); override; + procedure Clear; + procedure Click; override; + published + property Action; + property AutoCheck; + property Caption; + property CharCase: TEditCharCase read FCharCase write SetCharCase default ecNormal; + property Checked; + property DisplayMode; + property EditCaption: String read FEditCaption write SetEditCaption stored IsEditCaptionStored; + property EditOptions: TTBEditItemOptions read FEditOptions write SetEditOptions stored IsEditOptionsStored; + property EditWidth: Integer read FEditWidth write SetEditWidth stored IsEditWidthStored; + property MaxLength: Integer read FMaxLength write SetMaxLength default 0; + property Enabled; + property GroupIndex; + property HelpContext; + property Hint; + property ImageIndex; + property RadioItem; + property ShortCut; + property Text: String read FText write SetText stored IsTextStored; + property Visible; + + property OnAcceptText: TTBAcceptTextEvent read FOnAcceptText write FOnAcceptText; + property OnBeginEdit: TTBBeginEditEvent read FOnBeginEdit write FOnBeginEdit; + property OnClick; + property OnSelect; + end; + + TEditClass = class of TEdit; + + TTBEditItemViewer = class(TTBItemViewer) + private + FEditControl: TEdit; + FEditControlStatus: set of (ecsContinueLoop, ecsAccept, ecsClose); + function EditLoop(const CapHandle: HWND): Boolean; + procedure EditWndProc(var Message: TMessage); + procedure MouseBeginEdit; + protected + procedure CalcSize(const Canvas: TCanvas; var AWidth, AHeight: Integer); + override; + function CaptionShown: Boolean; override; + function DoExecute: Boolean; override; + function GetAccRole: Integer; override; + function GetAccValue(var Value: WideString): Boolean; override; + function GetCaptionText: String; override; + procedure GetCursor(const Pt: TPoint; var ACursor: HCURSOR); override; + function GetEditControlClass: TEditClass; virtual; + procedure GetEditRect(var R: TRect); virtual; + procedure MouseDown(Shift: TShiftState; X, Y: Integer; + var MouseDownOnMenu: Boolean); override; + procedure MouseUp(X, Y: Integer; MouseWasDownOnMenu: Boolean); override; + procedure Paint(const Canvas: TCanvas; const ClientAreaRect: TRect; + IsSelected, IsPushed, UseDisabledShadow: Boolean); override; + function UsesSameWidth: Boolean; override; + public + property EditControl: TEdit read FEditControl; + end; + + { TTBVisibilityToggleItem } + + TTBVisibilityToggleItem = class(TTBCustomItem) + private + FControl: TControl; + procedure SetControl(Value: TControl); + procedure UpdateProps; + protected + procedure Notification(AComponent: TComponent; Operation: TOperation); override; + public + procedure Click; override; + procedure InitiateAction; override; + published + property Caption; + property Control: TControl read FControl write SetControl; + property DisplayMode; + property Enabled; + property HelpContext; + property Hint; + property ImageIndex; + property Images; + property InheritOptions; + property MaskOptions; + property Options; + property ShortCut; + property Visible; + + property OnClick; + property OnSelect; + end; + + +implementation + +uses + TB2Common, TB2Consts; + +const + EditMenuTextMargin = 3; + EditMenuMidWidth = 4; + +type + TControlAccess = class(TControl); + TEditAccess = class(TEdit); + + +{ TTBEditAction } + +constructor TTBEditAction.Create(AOwner: TComponent); +begin + inherited; + FEditOptions := EditItemDefaultEditOptions; + FEditWidth := EditItemDefaultEditWidth; + DisableIfNoHandler := False; +end; + +procedure TTBEditAction.SetEditCaption(Value: String); +var + I: Integer; +begin + if FEditCaption <> Value then begin + for I := 0 to FClients.Count - 1 do + if TBasicActionLink(FClients[I]) is TTBEditItemActionLink then + TTBEditItemActionLink(FClients[I]).SetEditCaption(Value); + FEditCaption := Value; + Change; + end; +end; + +procedure TTBEditAction.SetEditOptions(Value: TTBEditItemOptions); +var + I: Integer; +begin + if FEditOptions <> Value then begin + for I := 0 to FClients.Count - 1 do + if TBasicActionLink(FClients[I]) is TTBEditItemActionLink then + TTBEditItemActionLink(FClients[I]).SetEditOptions(Value); + FEditOptions := Value; + Change; + end; +end; + +procedure TTBEditAction.SetEditWidth(Value: Integer); +var + I: Integer; +begin + if FEditWidth <> Value then begin + for I := 0 to FClients.Count - 1 do + if TBasicActionLink(FClients[I]) is TTBEditItemActionLink then + TTBEditItemActionLink(FClients[I]).SetEditWidth(Value); + FEditWidth := Value; + Change; + end; +end; + +procedure TTBEditAction.SetOnAcceptText(Value: TTBAcceptTextEvent); +var + I: Integer; +begin + if not MethodsEqual(TMethod(FOnAcceptText), TMethod(Value)) then begin + for I := 0 to FClients.Count - 1 do + if TBasicActionLink(FClients[I]) is TTBEditItemActionLink then + TTBEditItemActionLink(FClients[I]).SetOnAcceptText(Value); + FOnAcceptText := Value; + Change; + end; +end; + +procedure TTBEditAction.SetText(Value: String); +var + I: Integer; +begin + if FText <> Value then begin + for I := 0 to FClients.Count - 1 do + if TBasicActionLink(FClients[I]) is TTBEditItemActionLink then + TTBEditItemActionLink(FClients[I]).SetText(Value); + FText := Value; + Change; + end; +end; + + +{ TTBEditItemActionLink } + +procedure TTBEditItemActionLink.AssignClient(AClient: TObject); +begin + FClient := AClient as TTBEditItem; +end; + +function TTBEditItemActionLink.IsEditCaptionLinked: Boolean; +begin + if Action is TTBEditAction then + Result := TTBEditItem(FClient).EditCaption = TTBEditAction(Action).EditCaption + else + Result := False; +end; + +function TTBEditItemActionLink.IsEditOptionsLinked: Boolean; +begin + if Action is TTBEditAction then + Result := TTBEditItem(FClient).EditOptions = TTBEditAction(Action).EditOptions + else + Result := False; +end; + +function TTBEditItemActionLink.IsEditWidthLinked: Boolean; +begin + if Action is TTBEditAction then + Result := TTBEditItem(FClient).EditWidth = TTBEditAction(Action).EditWidth + else + Result := False; +end; + +function TTBEditItemActionLink.IsOnAcceptTextLinked: Boolean; +begin + if Action is TTBEditAction then + Result := MethodsEqual(TMethod(TTBEditItem(FClient).OnAcceptText), + TMethod(TTBEditAction(Action).OnAcceptText)) + else + Result := False; +end; + +function TTBEditItemActionLink.IsTextLinked: Boolean; +begin + if Action is TTBEditAction then + Result := TTBEditItem(FClient).Text = TTBEditAction(Action).Text + else + Result := False; +end; + +procedure TTBEditItemActionLink.SetEditCaption(const Value: String); +begin + if IsEditCaptionLinked then TTBEditItem(FClient).EditCaption := Value; +end; + +procedure TTBEditItemActionLink.SetEditOptions(Value: TTBEditItemOptions); +begin + if IsEditOptionsLinked then TTBEditItem(FClient).EditOptions := Value; +end; + +procedure TTBEditItemActionLink.SetEditWidth(const Value: Integer); +begin + if IsEditWidthLinked then TTBEditItem(FClient).EditWidth := Value; +end; + +procedure TTBEditItemActionLink.SetOnAcceptText(Value: TTBAcceptTextEvent); +begin + if IsOnAcceptTextLinked then TTBEditItem(FClient).OnAcceptText := Value; +end; + +procedure TTBEditItemActionLink.SetText(const Value: String); +begin + if IsTextLinked then TTBEditItem(FClient).SetTextEx(Value , tcrActionLink); +end; + + +{ TTBEditItem } + +constructor TTBEditItem.Create(AOwner: TComponent); +begin + inherited; + FEditOptions := EditItemDefaultEditOptions; + FEditWidth := EditItemDefaultEditWidth; +end; + +procedure TTBEditItem.ActionChange(Sender: TObject; CheckDefaults: Boolean); +begin + inherited; + if Action is TTBEditAction then + with TTBEditAction(Sender) do + begin + if not CheckDefaults or (Self.EditCaption = '') then + Self.EditCaption := EditCaption; + if not CheckDefaults or (Self.EditOptions = []) then + Self.EditOptions := EditOptions; + if not CheckDefaults or (Self.Text = '') then + Self.SetTextEx(Text, tcrActionLink); + if not CheckDefaults or not Assigned(Self.OnAcceptText) then + Self.OnAcceptText := OnAcceptText; + end; +end; + +function TTBEditItem.GetActionLinkClass: TTBCustomItemActionLinkClass; +begin + Result := TTBEditItemActionLink; +end; + +function TTBEditItem.GetItemViewerClass(AView: TTBView): TTBItemViewerClass; +begin + if not(tboUseEditWhenVertical in EditOptions) and + (AView.Orientation = tbvoVertical) then + Result := inherited GetItemViewerClass(AView) + else + Result := TTBEditItemViewer; +end; + +function TTBEditItem.NeedToRecreateViewer(AViewer: TTBItemViewer): Boolean; +begin + Result := GetItemViewerClass(AViewer.View) <> AViewer.ClassType; +end; + +procedure TTBEditItem.Clear; +begin + Text := ''; +end; + +procedure TTBEditItem.Click; +begin + inherited; +end; + +procedure TTBEditItem.DoBeginEdit(Viewer: TTBEditItemViewer); +begin + if Assigned(FOnBeginEdit) then + FOnBeginEdit(Self, Viewer, Viewer.EditControl); +end; + +function TTBEditItem.IsEditOptionsStored: Boolean; +begin + Result := (EditOptions <> EditItemDefaultEditOptions) and + ((ActionLink = nil) or not(ActionLink is TTBEditItemActionLink) or + not TTBEditItemActionLink(ActionLink).IsEditOptionsLinked); +end; + +function TTBEditItem.IsEditCaptionStored: Boolean; +begin + Result := (ActionLink = nil) or not(ActionLink is TTBEditItemActionLink) or + not TTBEditItemActionLink(ActionLink).IsEditCaptionLinked; +end; + +function TTBEditItem.IsEditWidthStored: Boolean; +begin + Result := (EditWidth <> EditItemDefaultEditWidth) and + ((ActionLink = nil) or not(ActionLink is TTBEditItemActionLink) or + not TTBEditItemActionLink(ActionLink).IsEditWidthLinked); +end; + +function TTBEditItem.IsTextStored: Boolean; +begin + Result := (ActionLink = nil) or not(ActionLink is TTBEditItemActionLink) or + not TTBEditItemActionLink(ActionLink).IsTextLinked; +end; + +procedure TTBEditItem.SetCharCase(Value: TEditCharCase); +begin + if FCharCase <> Value then begin + FCharCase := Value; + Text := Text; { update case } + end; +end; + +procedure TTBEditItem.SetEditOptions(Value: TTBEditItemOptions); +begin + if FEditOptions <> Value then begin + FEditOptions := Value; + Change(True); + end; +end; + +procedure TTBEditItem.SetEditCaption(Value: String); +begin + if FEditCaption <> Value then begin + FEditCaption := Value; + Change(True); + end; +end; + +procedure TTBEditItem.SetEditWidth(Value: Integer); +begin + if FEditWidth <> Value then begin + FEditWidth := Value; + Change(True); + end; +end; + +procedure TTBEditItem.SetMaxLength(Value: Integer); +begin + if FMaxLength <> Value then begin + FMaxLength := Value; + Change(False); + end; +end; + +function TTBEditItem.DoAcceptText(var NewText: string): Boolean; +begin + Result := True; + if Assigned(FOnAcceptText) then FOnAcceptText(Self, NewText, Result); +end; + +procedure TTBEditItem.DoTextChanging(const OldText: String; var NewText: String; Reason: Integer); +begin + case FCharCase of + ecUpperCase: NewText := AnsiUpperCase(NewText); + ecLowerCase: NewText := AnsiLowerCase(NewText); + end; +end; + +procedure TTBEditItem.DoTextChanged(Reason: Integer); +begin +end; + +procedure TTBEditItem.SetText(Value: String); +begin + DoTextChanging(FText, Value, tcrSetProperty); + if FText <> Value then begin + FText := Value; + Change(False); + DoTextChanged(tcrSetProperty); + end; +end; + +procedure TTBEditItem.SetTextEx(Value: String; Reason: Integer); +begin + DoTextChanging(FText, Value, Reason); + if FText <> Value then begin + FText := Value; + Change(False); + DoTextChanged(Reason); + end; +end; + + +{ TTBEditItemViewer } + +procedure TTBEditItemViewer.EditWndProc(var Message: TMessage); +var + Item: TTBEditItem; + + procedure AcceptText; + var + S: String; + begin + S := FEditControl.Text; + if Item.DoAcceptText(S) then Item.SetTextEx(S, tcrEditControl); + end; + +begin + Item := TTBEditItem(Self.Item); + if FEditControl = nil then + Exit; + if Message.Msg = WM_CHAR then + case TWMChar(Message).CharCode of + VK_TAB: begin + FEditControlStatus := [ecsAccept]; + AcceptText; + Exit; + end; + VK_RETURN: begin + FEditControlStatus := [ecsAccept, ecsClose]; + AcceptText; + Exit; + end; + VK_ESCAPE: begin + FEditControlStatus := []; + Exit; + end; + end; + TEditAccess(FEditControl).WndProc(Message); + if Message.Msg = WM_KILLFOCUS then begin + { Someone has stolen the focus from us, so 'cancel mode'. (We have to + handle WM_KILLFOCUS in addition to the upstream WM_CANCELMODE handling + since we don't always hold the mouse capture.) } + View.CancelMode; + FEditControlStatus := [ecsClose]; + end; +end; + +function TTBEditItemViewer.GetEditControlClass: TEditClass; +begin + Result := TEdit; +end; + +procedure TTBEditItemViewer.GetEditRect(var R: TRect); +var + Item: TTBEditItem; + DC: HDC; +begin + Item := TTBEditItem(Self.Item); + DC := GetDC(0); + try + SelectObject(DC, View.GetFont.Handle); + R := BoundsRect; + if not View.IsToolbar and (Item.EditCaption <> '') then begin + Inc(R.Left, GetTextWidth(DC, Item.EditCaption, True) + + EditMenuMidWidth + EditMenuTextMargin * 2); + end; + finally + ReleaseDC(0, DC); + end; +end; + +procedure TTBEditItemViewer.CalcSize(const Canvas: TCanvas; + var AWidth, AHeight: Integer); +var + Item: TTBEditItem; + DC: HDC; + TextHeight, MinHeight: Integer; +begin + Item := TTBEditItem(Self.Item); + DC := Canvas.Handle; + TextHeight := GetTextHeight(DC); + AWidth := Item.FEditWidth; + AHeight := TextHeight; + if not IsToolbarStyle and (Item.EditCaption <> '') then begin + Inc(AWidth, GetTextWidth(DC, Item.EditCaption, True) + EditMenuMidWidth + + EditMenuTextMargin * 2); + end; + MinHeight := AHeight + (EditMenuTextMargin * 2) + 1; + if not IsToolbarStyle then + Inc(AHeight, DivRoundUp(AHeight, 4)); + if AHeight < MinHeight then + AHeight := MinHeight; +end; + +function TTBEditItemViewer.CaptionShown: Boolean; +begin + Result := not IsToolbarStyle and inherited CaptionShown; +end; + +function TTBEditItemViewer.GetCaptionText: String; +begin + Result := TTBEditItem(Item).EditCaption; +end; + +procedure TTBEditItemViewer.Paint(const Canvas: TCanvas; + const ClientAreaRect: TRect; IsSelected, IsPushed, UseDisabledShadow: Boolean); +const + FillColors: array[Boolean] of TColor = (clBtnFace, clWindow); + TextColors: array[Boolean] of TColor = (clGrayText, clWindowText); +var + Item: TTBEditItem; + S: String; + R: TRect; + W: Integer; +begin + Item := TTBEditItem(Self.Item); + R := ClientAreaRect; + + { Caption } + if not IsToolbarStyle and (Item.EditCaption <> '') then begin + S := Item.EditCaption; + W := GetTextWidth(Canvas.Handle, S, True) + EditMenuTextMargin * 2; + R.Right := R.Left + W; + if IsSelected then + Canvas.FillRect(R); + Inc(R.Left, EditMenuTextMargin); + DrawItemCaption(Canvas, R, S, UseDisabledShadow, DT_SINGLELINE or + DT_LEFT or DT_VCENTER); + R := ClientAreaRect; + Inc(R.Left, W + EditMenuMidWidth); + end; + + { Border } + if IsSelected and Item.Enabled then + DrawEdge(Canvas.Handle, R, BDR_SUNKENOUTER, BF_RECT); + InflateRect(R, -1, -1); + Canvas.Brush.Color := FillColors[not Item.Enabled]; + Canvas.FrameRect(R); + InflateRect(R, -1, -1); + + { Fill } + Canvas.Brush.Color := FillColors[Item.Enabled]; + Canvas.FillRect(R); + InflateRect(R, -1, -1); + + { Text } + if Item.Text <> '' then begin + S := Item.Text; + Canvas.Brush.Style := bsClear; { speed optimization } + Canvas.Font.Color := TextColors[Item.Enabled]; + DrawText(Canvas.Handle, PChar(S), Length(S), R, DT_SINGLELINE or DT_NOPREFIX); + end; +end; + +procedure TTBEditItemViewer.GetCursor(const Pt: TPoint; var ACursor: HCURSOR); +var + R: TRect; +begin + if not Item.Enabled then + Exit; + GetEditRect(R); + OffsetRect(R, -BoundsRect.Left, -BoundsRect.Top); + InflateRect(R, -2, -2); + if PtInRect(R, Pt) then + ACursor := LoadCursor(0, IDC_IBEAM); +end; + +function TTBEditItemViewer.EditLoop(const CapHandle: HWND): Boolean; + + procedure ControlMessageLoop; + + function PointInWindow(const Wnd: HWND; const P: TPoint): Boolean; + var + W: HWND; + begin + Result := False; + W := WindowFromPoint(P); + if W = 0 then Exit; + if W = Wnd then + Result := True + else + if IsChild(Wnd, W) then + Result := True; + end; + + function ContinueLoop: Boolean; + begin + Result := (ecsContinueLoop in FEditControlStatus) and + not View.IsModalEnding and FEditControl.Focused and Item.Enabled; + { Note: View.IsModalEnding is checked since TTBView.CancelMode doesn't + destroy popup windows; it merely hides them and calls EndModal. So if + IsModalEnding returns True we can infer that CancelMode was likely + called. } + end; + + var + Msg: TMsg; + IsKeypadDigit: Boolean; + V: Integer; + begin + try + while ContinueLoop do begin + { Examine the next message before popping it out of the queue } + if not PeekMessage(Msg, 0, 0, 0, PM_NOREMOVE) then begin + WaitMessage; + Continue; + end; + case Msg.message of + WM_SYSKEYDOWN: begin + { Exit immediately if Alt+[key] or F10 are pressed, but not + Alt+Shift, Alt+`, or Alt+[keypad digit] } + if (Msg.wParam <> VK_MENU) and (Msg.wParam <> VK_SHIFT) and + (Msg.wParam <> VK_HANJA) then begin + IsKeypadDigit := False; + { This detect digits regardless of whether Num Lock is on: } + if Lo(LongRec(Msg.lParam).Hi) <> 0 then + for V := VK_NUMPAD0 to VK_NUMPAD9 do + if MapVirtualKey(V, 0) = Lo(LongRec(Msg.lParam).Hi) then begin + IsKeypadDigit := True; + Break; + end; + if not IsKeypadDigit then begin + FEditControlStatus := [ecsClose]; + Exit; + end; + end; + end; + WM_SYSKEYUP: begin + { Exit when Alt is released by itself } + if Msg.wParam = VK_MENU then begin + FEditControlStatus := [ecsClose]; + Exit; + end; + end; + WM_LBUTTONDOWN, WM_LBUTTONDBLCLK, + WM_RBUTTONDOWN, WM_RBUTTONDBLCLK, + WM_MBUTTONDOWN, WM_MBUTTONDBLCLK, + WM_NCLBUTTONDOWN, WM_NCLBUTTONDBLCLK, + WM_NCRBUTTONDOWN, WM_NCRBUTTONDBLCLK, + WM_NCMBUTTONDOWN, WM_NCMBUTTONDBLCLK: begin + { If a mouse click outside the edit control is in the queue, + exit and let the upstream message loop deal with it } + if Msg.hwnd <> FEditControl.Handle then + Exit; + end; + WM_MOUSEMOVE, WM_NCMOUSEMOVE: begin + if GetCapture = CapHandle then begin + if PointInWindow(FEditControl.Handle, Msg.pt) then + ReleaseCapture; + end + else if GetCapture = 0 then begin + if not PointInWindow(FEditControl.Handle, Msg.pt) then + SetCapture(CapHandle); + end; + if GetCapture = CapHandle then + SetCursor(LoadCursor(0, IDC_ARROW)); + end; + end; + { Now pop the message out of the queue } + if not PeekMessage(Msg, 0, Msg.message, Msg.message, PM_REMOVE or PM_NOYIELD) then + Continue; + if ((Msg.message >= WM_MOUSEFIRST) and (Msg.message <= WM_MOUSELAST)) and + (Msg.hwnd = CapHandle) then + { discard, so that the selection doesn't get changed } + else begin + TranslateMessage(Msg); + DispatchMessage(Msg); + end; + end; + finally + { Make sure there are no outstanding WM_*CHAR messages } + RemoveMessages(WM_CHAR, WM_DEADCHAR); + RemoveMessages(WM_SYSCHAR, WM_SYSDEADCHAR); + end; + end; + +var + Item: TTBEditItem; + R: TRect; + ActiveWnd, FocusWnd: HWND; + S: string; +begin + Item := TTBEditItem(Self.Item); + GetEditRect(R); + if IsRectEmpty(R) then begin + Result := False; + Exit; + end; + + ActiveWnd := GetActiveWindow; + FocusWnd := GetFocus; + + { Create the edit control } + InflateRect(R, -3, -3); + //View.FreeNotification (Self); + FEditControl := GetEditControlClass.Create(nil); + try + FEditControl.Name := Format('%s_edit_control_%p', [ClassName, + Pointer(FEditControl)]); + FEditControl.Visible := False; + FEditControl.BorderStyle := bsNone; + FEditControl.AutoSize := False; + FEditControl.Font.Assign(View.GetFont); + FEditControl.Text := Item.Text; + FEditControl.CharCase := Item.FCharCase; + FEditControl.MaxLength := Item.FMaxLength; + FEditControl.BoundsRect := R; + FEditControl.WindowProc := EditWndProc; + FEditControl.ParentWindow := View.Window.Handle; + FEditControl.SelectAll; + Item.DoBeginEdit(Self); + FEditControl.Visible := True; + FEditControl.SetFocus; + if GetActiveWindow <> ActiveWnd then + { don't gray out title bar of old active window } + SendMessage(ActiveWnd, WM_NCACTIVATE, 1, 0) + else + ActiveWnd := 0; + + FEditControlStatus := [ecsContinueLoop]; + ControlMessageLoop; + finally + S := FEditControl.Text; + FreeAndNil(FEditControl); + end; + + with TTBEditItem(Item) do + if (FEditControlStatus = [ecsContinueLoop]) and ExtendedAccept then + if DoAcceptText(S) then SetTextEx(S, tcrEditControl); + + { ensure the area underneath the edit control is repainted immediately } + View.Window.Update; + { If app is still active, set focus to previous control and restore capture + to CapHandle if another control hasn't taken it } + if GetActiveWindow <> 0 then begin + SetFocus(FocusWnd); + if GetCapture = 0 then + SetCapture(CapHandle); + end; + if ActiveWnd <> 0 then + SendMessage(ActiveWnd, WM_NCACTIVATE, Ord(GetActiveWindow = ActiveWnd), 0); + { The SetFocus call above can change the Z order of windows. If the parent + window is a popup window, reassert its topmostness. } + if View.Window is TTBPopupWindow then + SetWindowPos(View.Window.Handle, HWND_TOPMOST, 0, 0, 0, 0, + SWP_NOACTIVATE or SWP_NOMOVE or SWP_NOSIZE); + { Send an MSAA "focus" event now that we're returning to the regular modal loop } + View.NotifyFocusEvent; + + Result := ecsClose in FEditControlStatus; + if not Result and (GetCapture = CapHandle) then begin + if ecsAccept in FEditControlStatus then + { if we are accepting but not closing, Tab must have been pressed } + View.Selected := View.NextSelectable(View.Selected, + GetKeyState(VK_SHIFT) >= 0); + end; +end; + +function TTBEditItemViewer.DoExecute: Boolean; +begin + { Close any delay-close popup menus before entering the edit loop } + View.CancelChildPopups; + Result := False; + if EditLoop(View.GetCaptureWnd) then begin + View.EndModal; + if ecsAccept in FEditControlStatus then + Result := True; + end; +end; + +procedure TTBEditItemViewer.MouseBeginEdit; +begin + if Item.Enabled then + Execute(True) + else begin + if (View.ParentView = nil) and not View.IsPopup then + View.EndModal; + end; +end; + +procedure TTBEditItemViewer.MouseDown(Shift: TShiftState; X, Y: Integer; + var MouseDownOnMenu: Boolean); +begin + if IsPtInButtonPart(X, Y) then { for TBX... } + MouseBeginEdit + else + inherited; +end; + +procedure TTBEditItemViewer.MouseUp(X, Y: Integer; MouseWasDownOnMenu: Boolean); +begin + if IsPtInButtonPart(X, Y) then { for TBX... } + MouseBeginEdit + else + inherited; +end; + +function TTBEditItemViewer.UsesSameWidth: Boolean; +begin + Result := False; +end; + +function TTBEditItemViewer.GetAccRole: Integer; +const + ROLE_SYSTEM_TEXT = $2a; { from OleAcc.h } +begin + Result := ROLE_SYSTEM_TEXT; +end; + +function TTBEditItemViewer.GetAccValue(var Value: WideString): Boolean; +begin + Value := TTBEditItem(Item).Text; + Result := True; +end; + + +{ TTBToolbarVisibilityItem } + +procedure TTBVisibilityToggleItem.Click; +begin + if Assigned(FControl) then + FControl.Visible := not FControl.Visible; + inherited; +end; + +procedure TTBVisibilityToggleItem.InitiateAction; +begin + UpdateProps; +end; + +procedure TTBVisibilityToggleItem.Notification(AComponent: TComponent; + Operation: TOperation); +begin + inherited; + if (Operation = opRemove) and (AComponent = FControl) then + Control := nil; +end; + +procedure TTBVisibilityToggleItem.SetControl(Value: TControl); +begin + if FControl <> Value then begin + FControl := Value; + if Assigned(Value) then begin + Value.FreeNotification(Self); + if (Caption = '') and not(csLoading in ComponentState) then + Caption := TControlAccess(Value).Caption; + end; + UpdateProps; + end; +end; + +procedure TTBVisibilityToggleItem.UpdateProps; +begin + if (ComponentState * [csDesigning, csLoading, csDestroying] = []) then + Checked := Assigned(FControl) and FControl.Visible; +end; + +end. diff --git a/official/2.1.6+2.1.beta1/Source/TB2ExtItems.pas.orig b/official/2.1.6+2.1.beta1/Source/TB2ExtItems.pas.orig new file mode 100644 index 0000000..ae99b6a --- /dev/null +++ b/official/2.1.6+2.1.beta1/Source/TB2ExtItems.pas.orig @@ -0,0 +1,962 @@ +unit TB2ExtItems; + +{ + Toolbar2000 + Copyright (C) 1998-2005 by Jordan Russell + All rights reserved. + + The contents of this file are subject to the "Toolbar2000 License"; you may + not use or distribute this file except in compliance with the + "Toolbar2000 License". A copy of the "Toolbar2000 License" may be found in + TB2k-LICENSE.txt or at: + http://www.jrsoftware.org/files/tb2k/TB2k-LICENSE.txt + + Alternatively, the contents of this file may be used under the terms of the + GNU General Public License (the "GPL"), in which case the provisions of the + GPL are applicable instead of those in the "Toolbar2000 License". A copy of + the GPL may be found in GPL-LICENSE.txt or at: + http://www.jrsoftware.org/files/tb2k/GPL-LICENSE.txt + If you wish to allow use of your version of this file only under the terms of + the GPL and not to allow others to use your version of this file under the + "Toolbar2000 License", indicate your decision by deleting the provisions + above and replace them with the notice and other provisions required by the + GPL. If you do not delete the provisions above, a recipient may use your + version of this file under either the "Toolbar2000 License" or the GPL. + + $jrsoftware: tb2k/Source/TB2ExtItems.pas,v 1.63 2005/07/04 02:49:52 jr Exp $ +} + +interface + +{$I TB2Ver.inc} + +uses + Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, + StdCtrls, CommCtrl, Menus, ActnList, + TB2Item; + +type + TTBEditItemOption = (tboUseEditWhenVertical); + TTBEditItemOptions = set of TTBEditItemOption; + +const + EditItemDefaultEditOptions = []; + EditItemDefaultEditWidth = 64; + +type + TTBEditItem = class; + TTBEditItemViewer = class; + + TTBAcceptTextEvent = procedure(Sender: TObject; var NewText: String; + var Accept: Boolean) of object; + TTBBeginEditEvent = procedure(Sender: TTBEditItem; Viewer: TTBEditItemViewer; + EditControl: TEdit) of object; + + TTBEditAction = class(TAction) + private + FEditOptions: TTBEditItemOptions; + FEditCaption: String; + FEditWidth: Integer; + FOnAcceptText: TTBAcceptTextEvent; + FText: String; + procedure SetEditCaption(Value: String); + procedure SetEditOptions(Value: TTBEditItemOptions); + procedure SetEditWidth(Value: Integer); + procedure SetOnAcceptText(Value: TTBAcceptTextEvent); + procedure SetText(Value: String); + public + constructor Create(AOwner: TComponent); override; + published + property EditCaption: String read FEditCaption write SetEditCaption; + property EditOptions: TTBEditItemOptions read FEditOptions write SetEditOptions default EditItemDefaultEditOptions; + property EditWidth: Integer read FEditWidth write SetEditWidth default EditItemDefaultEditWidth; + property Text: String read FText write SetText; + + property OnAcceptText: TTBAcceptTextEvent read FOnAcceptText write SetOnAcceptText; + end; + + TTBEditItemActionLink = class(TTBCustomItemActionLink) + protected + procedure AssignClient(AClient: TObject); override; + function IsEditCaptionLinked: Boolean; virtual; + function IsEditOptionsLinked: Boolean; virtual; + function IsEditWidthLinked: Boolean; virtual; + function IsOnAcceptTextLinked: Boolean; virtual; + function IsTextLinked: Boolean; virtual; + procedure SetEditCaption(const Value: String); virtual; + procedure SetEditOptions(Value: TTBEditItemOptions); virtual; + procedure SetEditWidth(const Value: Integer); virtual; + procedure SetOnAcceptText(Value: TTBAcceptTextEvent); virtual; + procedure SetText(const Value: String); virtual; + end; + + TTBEditItem = class(TTBCustomItem) + private + FCharCase: TEditCharCase; + FEditCaption: String; + FEditOptions: TTBEditItemOptions; + FEditWidth: Integer; + FMaxLength: Integer; + FOnAcceptText: TTBAcceptTextEvent; + FOnBeginEdit: TTBBeginEditEvent; + FText: String; + function IsEditCaptionStored: Boolean; + function IsEditOptionsStored: Boolean; + function IsEditWidthStored: Boolean; + function IsTextStored: Boolean; + procedure SetCharCase(Value: TEditCharCase); + procedure SetEditCaption(Value: String); + procedure SetEditOptions(Value: TTBEditItemOptions); + procedure SetEditWidth(Value: Integer); + procedure SetMaxLength(Value: Integer); + procedure SetText(Value: String); + protected + procedure ActionChange(Sender: TObject; CheckDefaults: Boolean); override; + procedure DoBeginEdit(Viewer: TTBEditItemViewer); virtual; + function GetActionLinkClass: TTBCustomItemActionLinkClass; override; + function GetItemViewerClass(AView: TTBView): TTBItemViewerClass; override; + function NeedToRecreateViewer(AViewer: TTBItemViewer): Boolean; override; + public + constructor Create(AOwner: TComponent); override; + procedure Clear; + procedure Click; override; + published + property Action; + property AutoCheck; + property Caption; + property CharCase: TEditCharCase read FCharCase write SetCharCase default ecNormal; + property Checked; + property DisplayMode; + property EditCaption: String read FEditCaption write SetEditCaption stored IsEditCaptionStored; + property EditOptions: TTBEditItemOptions read FEditOptions write SetEditOptions stored IsEditOptionsStored; + property EditWidth: Integer read FEditWidth write SetEditWidth stored IsEditWidthStored; + property MaxLength: Integer read FMaxLength write SetMaxLength default 0; + property Enabled; + property GroupIndex; + property HelpContext; + property Hint; + property ImageIndex; + property RadioItem; + property ShortCut; + property Text: String read FText write SetText stored IsTextStored; + property Visible; + + property OnAcceptText: TTBAcceptTextEvent read FOnAcceptText write FOnAcceptText; + property OnBeginEdit: TTBBeginEditEvent read FOnBeginEdit write FOnBeginEdit; + property OnClick; + property OnSelect; + end; + + TTBEditItemViewer = class(TTBItemViewer) + private + FEditControl: TEdit; + FEditControlStatus: set of (ecsContinueLoop, ecsAccept, ecsClose); + function EditLoop(const CapHandle: HWND): Boolean; + procedure EditWndProc(var Message: TMessage); + procedure MouseBeginEdit; + protected + procedure CalcSize(const Canvas: TCanvas; var AWidth, AHeight: Integer); + override; + function CaptionShown: Boolean; override; + function DoExecute: Boolean; override; + function GetAccRole: Integer; override; + function GetAccValue(var Value: WideString): Boolean; override; + function GetCaptionText: String; override; + procedure GetCursor(const Pt: TPoint; var ACursor: HCURSOR); override; + procedure GetEditRect(var R: TRect); virtual; + procedure MouseDown(Shift: TShiftState; X, Y: Integer; + var MouseDownOnMenu: Boolean); override; + procedure MouseUp(X, Y: Integer; MouseWasDownOnMenu: Boolean); override; + procedure Paint(const Canvas: TCanvas; const ClientAreaRect: TRect; + IsSelected, IsPushed, UseDisabledShadow: Boolean); override; + function UsesSameWidth: Boolean; override; + public + property EditControl: TEdit read FEditControl; + end; + + { TTBVisibilityToggleItem } + + TTBVisibilityToggleItem = class(TTBCustomItem) + private + FControl: TControl; + procedure SetControl(Value: TControl); + procedure UpdateProps; + protected + procedure Notification(AComponent: TComponent; Operation: TOperation); override; + public + procedure Click; override; + procedure InitiateAction; override; + published + property Caption; + property Control: TControl read FControl write SetControl; + property DisplayMode; + property Enabled; + property HelpContext; + property Hint; + property ImageIndex; + property Images; + property InheritOptions; + property MaskOptions; + property Options; + property ShortCut; + property Visible; + + property OnClick; + property OnSelect; + end; + + +implementation + +uses + TB2Common, TB2Consts; + +const + EditMenuTextMargin = 3; + EditMenuMidWidth = 4; + +type + TControlAccess = class(TControl); + TEditAccess = class(TEdit); + + +{ TTBEditAction } + +constructor TTBEditAction.Create(AOwner: TComponent); +begin + inherited; + FEditOptions := EditItemDefaultEditOptions; + FEditWidth := EditItemDefaultEditWidth; + DisableIfNoHandler := False; +end; + +procedure TTBEditAction.SetEditCaption(Value: String); +var + I: Integer; +begin + if FEditCaption <> Value then begin + for I := 0 to FClients.Count - 1 do + if TBasicActionLink(FClients[I]) is TTBEditItemActionLink then + TTBEditItemActionLink(FClients[I]).SetEditCaption(Value); + FEditCaption := Value; + Change; + end; +end; + +procedure TTBEditAction.SetEditOptions(Value: TTBEditItemOptions); +var + I: Integer; +begin + if FEditOptions <> Value then begin + for I := 0 to FClients.Count - 1 do + if TBasicActionLink(FClients[I]) is TTBEditItemActionLink then + TTBEditItemActionLink(FClients[I]).SetEditOptions(Value); + FEditOptions := Value; + Change; + end; +end; + +procedure TTBEditAction.SetEditWidth(Value: Integer); +var + I: Integer; +begin + if FEditWidth <> Value then begin + for I := 0 to FClients.Count - 1 do + if TBasicActionLink(FClients[I]) is TTBEditItemActionLink then + TTBEditItemActionLink(FClients[I]).SetEditWidth(Value); + FEditWidth := Value; + Change; + end; +end; + +procedure TTBEditAction.SetOnAcceptText(Value: TTBAcceptTextEvent); +var + I: Integer; +begin + if not MethodsEqual(TMethod(FOnAcceptText), TMethod(Value)) then begin + for I := 0 to FClients.Count - 1 do + if TBasicActionLink(FClients[I]) is TTBEditItemActionLink then + TTBEditItemActionLink(FClients[I]).SetOnAcceptText(Value); + FOnAcceptText := Value; + Change; + end; +end; + +procedure TTBEditAction.SetText(Value: String); +var + I: Integer; +begin + if FText <> Value then begin + for I := 0 to FClients.Count - 1 do + if TBasicActionLink(FClients[I]) is TTBEditItemActionLink then + TTBEditItemActionLink(FClients[I]).SetText(Value); + FText := Value; + Change; + end; +end; + + +{ TTBEditItemActionLink } + +procedure TTBEditItemActionLink.AssignClient(AClient: TObject); +begin + FClient := AClient as TTBEditItem; +end; + +function TTBEditItemActionLink.IsEditCaptionLinked: Boolean; +begin + if Action is TTBEditAction then + Result := TTBEditItem(FClient).EditCaption = TTBEditAction(Action).EditCaption + else + Result := False; +end; + +function TTBEditItemActionLink.IsEditOptionsLinked: Boolean; +begin + if Action is TTBEditAction then + Result := TTBEditItem(FClient).EditOptions = TTBEditAction(Action).EditOptions + else + Result := False; +end; + +function TTBEditItemActionLink.IsEditWidthLinked: Boolean; +begin + if Action is TTBEditAction then + Result := TTBEditItem(FClient).EditWidth = TTBEditAction(Action).EditWidth + else + Result := False; +end; + +function TTBEditItemActionLink.IsOnAcceptTextLinked: Boolean; +begin + if Action is TTBEditAction then + Result := MethodsEqual(TMethod(TTBEditItem(FClient).OnAcceptText), + TMethod(TTBEditAction(Action).OnAcceptText)) + else + Result := False; +end; + +function TTBEditItemActionLink.IsTextLinked: Boolean; +begin + if Action is TTBEditAction then + Result := TTBEditItem(FClient).Text = TTBEditAction(Action).Text + else + Result := False; +end; + +procedure TTBEditItemActionLink.SetEditCaption(const Value: String); +begin + if IsEditCaptionLinked then TTBEditItem(FClient).EditCaption := Value; +end; + +procedure TTBEditItemActionLink.SetEditOptions(Value: TTBEditItemOptions); +begin + if IsEditOptionsLinked then TTBEditItem(FClient).EditOptions := Value; +end; + +procedure TTBEditItemActionLink.SetEditWidth(const Value: Integer); +begin + if IsEditWidthLinked then TTBEditItem(FClient).EditWidth := Value; +end; + +procedure TTBEditItemActionLink.SetOnAcceptText(Value: TTBAcceptTextEvent); +begin + if IsOnAcceptTextLinked then TTBEditItem(FClient).OnAcceptText := Value; +end; + +procedure TTBEditItemActionLink.SetText(const Value: String); +begin + if IsTextLinked then TTBEditItem(FClient).Text := Value; +end; + + +{ TTBEditItem } + +constructor TTBEditItem.Create(AOwner: TComponent); +begin + inherited; + FEditOptions := EditItemDefaultEditOptions; + FEditWidth := EditItemDefaultEditWidth; +end; + +procedure TTBEditItem.ActionChange(Sender: TObject; CheckDefaults: Boolean); +begin + inherited; + if Action is TTBEditAction then + with TTBEditAction(Sender) do + begin + if not CheckDefaults or (Self.EditCaption = '') then + Self.EditCaption := EditCaption; + if not CheckDefaults or (Self.EditOptions = []) then + Self.EditOptions := EditOptions; + if not CheckDefaults or (Self.Text = '') then + Self.Text := Text; + if not CheckDefaults or not Assigned(Self.OnAcceptText) then + Self.OnAcceptText := OnAcceptText; + end; +end; + +function TTBEditItem.GetActionLinkClass: TTBCustomItemActionLinkClass; +begin + Result := TTBEditItemActionLink; +end; + +function TTBEditItem.GetItemViewerClass(AView: TTBView): TTBItemViewerClass; +begin + if not(tboUseEditWhenVertical in EditOptions) and + (AView.Orientation = tbvoVertical) then + Result := inherited GetItemViewerClass(AView) + else + Result := TTBEditItemViewer; +end; + +function TTBEditItem.NeedToRecreateViewer(AViewer: TTBItemViewer): Boolean; +begin + Result := GetItemViewerClass(AViewer.View) <> AViewer.ClassType; +end; + +procedure TTBEditItem.Clear; +begin + Text := ''; +end; + +procedure TTBEditItem.Click; +begin + inherited; +end; + +procedure TTBEditItem.DoBeginEdit(Viewer: TTBEditItemViewer); +begin + if Assigned(FOnBeginEdit) then + FOnBeginEdit(Self, Viewer, Viewer.EditControl); +end; + +function TTBEditItem.IsEditOptionsStored: Boolean; +begin + Result := (EditOptions <> EditItemDefaultEditOptions) and + ((ActionLink = nil) or not(ActionLink is TTBEditItemActionLink) or + not TTBEditItemActionLink(ActionLink).IsEditOptionsLinked); +end; + +function TTBEditItem.IsEditCaptionStored: Boolean; +begin + Result := (ActionLink = nil) or not(ActionLink is TTBEditItemActionLink) or + not TTBEditItemActionLink(ActionLink).IsEditCaptionLinked; +end; + +function TTBEditItem.IsEditWidthStored: Boolean; +begin + Result := (EditWidth <> EditItemDefaultEditWidth) and + ((ActionLink = nil) or not(ActionLink is TTBEditItemActionLink) or + not TTBEditItemActionLink(ActionLink).IsEditWidthLinked); +end; + +function TTBEditItem.IsTextStored: Boolean; +begin + Result := (ActionLink = nil) or not(ActionLink is TTBEditItemActionLink) or + not TTBEditItemActionLink(ActionLink).IsTextLinked; +end; + +procedure TTBEditItem.SetCharCase(Value: TEditCharCase); +begin + if FCharCase <> Value then begin + FCharCase := Value; + Text := Text; { update case } + end; +end; + +procedure TTBEditItem.SetEditOptions(Value: TTBEditItemOptions); +begin + if FEditOptions <> Value then begin + FEditOptions := Value; + Change(True); + end; +end; + +procedure TTBEditItem.SetEditCaption(Value: String); +begin + if FEditCaption <> Value then begin + FEditCaption := Value; + Change(True); + end; +end; + +procedure TTBEditItem.SetEditWidth(Value: Integer); +begin + if FEditWidth <> Value then begin + FEditWidth := Value; + Change(True); + end; +end; + +procedure TTBEditItem.SetMaxLength(Value: Integer); +begin + if FMaxLength <> Value then begin + FMaxLength := Value; + Change(False); + end; +end; + +procedure TTBEditItem.SetText(Value: String); +begin + case FCharCase of + ecUpperCase: Value := AnsiUpperCase(Value); + ecLowerCase: Value := AnsiLowerCase(Value); + end; + if FText <> Value then begin + FText := Value; + Change(False); + end; +end; + + +{ TTBEditItemViewer } + +procedure TTBEditItemViewer.EditWndProc(var Message: TMessage); +var + Item: TTBEditItem; + + procedure AcceptText; + var + S: String; + Accept: Boolean; + begin + S := FEditControl.Text; + Accept := True; + if Assigned(Item.FOnAcceptText) then + Item.FOnAcceptText(Self, S, Accept); + if Accept then + Item.Text := S; + end; + +begin + Item := TTBEditItem(Self.Item); + if FEditControl = nil then + Exit; + if Message.Msg = WM_CHAR then + case TWMChar(Message).CharCode of + VK_TAB: begin + FEditControlStatus := [ecsAccept]; + AcceptText; + Exit; + end; + VK_RETURN: begin + FEditControlStatus := [ecsAccept, ecsClose]; + AcceptText; + Exit; + end; + VK_ESCAPE: begin + FEditControlStatus := []; + Exit; + end; + end; + TEditAccess(FEditControl).WndProc(Message); + if Message.Msg = WM_KILLFOCUS then begin + { Someone has stolen the focus from us, so 'cancel mode'. (We have to + handle WM_KILLFOCUS in addition to the upstream WM_CANCELMODE handling + since we don't always hold the mouse capture.) } + View.CancelMode; + FEditControlStatus := [ecsClose]; + end; +end; + +procedure TTBEditItemViewer.GetEditRect(var R: TRect); +var + Item: TTBEditItem; + DC: HDC; +begin + Item := TTBEditItem(Self.Item); + DC := GetDC(0); + try + SelectObject(DC, View.GetFont.Handle); + R := BoundsRect; + if not View.IsToolbar and (Item.EditCaption <> '') then begin + Inc(R.Left, GetTextWidth(DC, Item.EditCaption, True) + + EditMenuMidWidth + EditMenuTextMargin * 2); + end; + finally + ReleaseDC(0, DC); + end; +end; + +procedure TTBEditItemViewer.CalcSize(const Canvas: TCanvas; + var AWidth, AHeight: Integer); +var + Item: TTBEditItem; + DC: HDC; + TextHeight, MinHeight: Integer; +begin + Item := TTBEditItem(Self.Item); + DC := Canvas.Handle; + TextHeight := GetTextHeight(DC); + AWidth := Item.FEditWidth; + AHeight := TextHeight; + if not IsToolbarStyle and (Item.EditCaption <> '') then begin + Inc(AWidth, GetTextWidth(DC, Item.EditCaption, True) + EditMenuMidWidth + + EditMenuTextMargin * 2); + end; + MinHeight := AHeight + (EditMenuTextMargin * 2) + 1; + if not IsToolbarStyle then + Inc(AHeight, DivRoundUp(AHeight, 4)); + if AHeight < MinHeight then + AHeight := MinHeight; +end; + +function TTBEditItemViewer.CaptionShown: Boolean; +begin + Result := not IsToolbarStyle and inherited CaptionShown; +end; + +function TTBEditItemViewer.GetCaptionText: String; +begin + Result := TTBEditItem(Item).EditCaption; +end; + +procedure TTBEditItemViewer.Paint(const Canvas: TCanvas; + const ClientAreaRect: TRect; IsSelected, IsPushed, UseDisabledShadow: Boolean); +const + FillColors: array[Boolean] of TColor = (clBtnFace, clWindow); + TextColors: array[Boolean] of TColor = (clGrayText, clWindowText); +var + Item: TTBEditItem; + S: String; + R: TRect; + W: Integer; +begin + Item := TTBEditItem(Self.Item); + R := ClientAreaRect; + + { Caption } + if not IsToolbarStyle and (Item.EditCaption <> '') then begin + S := Item.EditCaption; + W := GetTextWidth(Canvas.Handle, S, True) + EditMenuTextMargin * 2; + R.Right := R.Left + W; + if IsSelected then + Canvas.FillRect(R); + Inc(R.Left, EditMenuTextMargin); + DrawItemCaption(Canvas, R, S, UseDisabledShadow, DT_SINGLELINE or + DT_LEFT or DT_VCENTER); + R := ClientAreaRect; + Inc(R.Left, W + EditMenuMidWidth); + end; + + { Border } + if IsSelected and Item.Enabled then + DrawEdge(Canvas.Handle, R, BDR_SUNKENOUTER, BF_RECT); + InflateRect(R, -1, -1); + Canvas.Brush.Color := FillColors[not Item.Enabled]; + Canvas.FrameRect(R); + InflateRect(R, -1, -1); + + { Fill } + Canvas.Brush.Color := FillColors[Item.Enabled]; + Canvas.FillRect(R); + InflateRect(R, -1, -1); + + { Text } + if Item.Text <> '' then begin + S := Item.Text; + Canvas.Brush.Style := bsClear; { speed optimization } + Canvas.Font.Color := TextColors[Item.Enabled]; + DrawText(Canvas.Handle, PChar(S), Length(S), R, DT_SINGLELINE or DT_NOPREFIX); + end; +end; + +procedure TTBEditItemViewer.GetCursor(const Pt: TPoint; var ACursor: HCURSOR); +var + R: TRect; +begin + if not Item.Enabled then + Exit; + GetEditRect(R); + OffsetRect(R, -BoundsRect.Left, -BoundsRect.Top); + InflateRect(R, -2, -2); + if PtInRect(R, Pt) then + ACursor := LoadCursor(0, IDC_IBEAM); +end; + +function TTBEditItemViewer.EditLoop(const CapHandle: HWND): Boolean; + + procedure ControlMessageLoop; + + function PointInWindow(const Wnd: HWND; const P: TPoint): Boolean; + var + W: HWND; + begin + Result := False; + W := WindowFromPoint(P); + if W = 0 then Exit; + if W = Wnd then + Result := True + else + if IsChild(Wnd, W) then + Result := True; + end; + + function ContinueLoop: Boolean; + begin + Result := (ecsContinueLoop in FEditControlStatus) and + not View.IsModalEnding and FEditControl.Focused and Item.Enabled; + { Note: View.IsModalEnding is checked since TTBView.CancelMode doesn't + destroy popup windows; it merely hides them and calls EndModal. So if + IsModalEnding returns True we can infer that CancelMode was likely + called. } + end; + + var + Msg: TMsg; + IsKeypadDigit: Boolean; + V: Integer; + begin + try + while ContinueLoop do begin + { Examine the next message before popping it out of the queue } + if not PeekMessage(Msg, 0, 0, 0, PM_NOREMOVE) then begin + WaitMessage; + Continue; + end; + case Msg.message of + WM_SYSKEYDOWN: begin + { Exit immediately if Alt+[key] or F10 are pressed, but not + Alt+Shift, Alt+`, or Alt+[keypad digit] } + if (Msg.wParam <> VK_MENU) and (Msg.wParam <> VK_SHIFT) and + (Msg.wParam <> VK_HANJA) then begin + IsKeypadDigit := False; + { This detect digits regardless of whether Num Lock is on: } + if Lo(LongRec(Msg.lParam).Hi) <> 0 then + for V := VK_NUMPAD0 to VK_NUMPAD9 do + if MapVirtualKey(V, 0) = Lo(LongRec(Msg.lParam).Hi) then begin + IsKeypadDigit := True; + Break; + end; + if not IsKeypadDigit then begin + FEditControlStatus := [ecsClose]; + Exit; + end; + end; + end; + WM_SYSKEYUP: begin + { Exit when Alt is released by itself } + if Msg.wParam = VK_MENU then begin + FEditControlStatus := [ecsClose]; + Exit; + end; + end; + WM_LBUTTONDOWN, WM_LBUTTONDBLCLK, + WM_RBUTTONDOWN, WM_RBUTTONDBLCLK, + WM_MBUTTONDOWN, WM_MBUTTONDBLCLK, + WM_NCLBUTTONDOWN, WM_NCLBUTTONDBLCLK, + WM_NCRBUTTONDOWN, WM_NCRBUTTONDBLCLK, + WM_NCMBUTTONDOWN, WM_NCMBUTTONDBLCLK: begin + { If a mouse click outside the edit control is in the queue, + exit and let the upstream message loop deal with it } + if Msg.hwnd <> FEditControl.Handle then + Exit; + end; + WM_MOUSEMOVE, WM_NCMOUSEMOVE: begin + if GetCapture = CapHandle then begin + if PointInWindow(FEditControl.Handle, Msg.pt) then + ReleaseCapture; + end + else if GetCapture = 0 then begin + if not PointInWindow(FEditControl.Handle, Msg.pt) then + SetCapture(CapHandle); + end; + if GetCapture = CapHandle then + SetCursor(LoadCursor(0, IDC_ARROW)); + end; + end; + { Now pop the message out of the queue } + if not PeekMessage(Msg, 0, Msg.message, Msg.message, PM_REMOVE or PM_NOYIELD) then + Continue; + if ((Msg.message >= WM_MOUSEFIRST) and (Msg.message <= WM_MOUSELAST)) and + (Msg.hwnd = CapHandle) then + { discard, so that the selection doesn't get changed } + else begin + TranslateMessage(Msg); + DispatchMessage(Msg); + end; + end; + finally + { Make sure there are no outstanding WM_*CHAR messages } + RemoveMessages(WM_CHAR, WM_DEADCHAR); + RemoveMessages(WM_SYSCHAR, WM_SYSDEADCHAR); + end; + end; + +var + Item: TTBEditItem; + R: TRect; + ActiveWnd, FocusWnd: HWND; +begin + Item := TTBEditItem(Self.Item); + GetEditRect(R); + if IsRectEmpty(R) then begin + Result := False; + Exit; + end; + + ActiveWnd := GetActiveWindow; + FocusWnd := GetFocus; + + { Create the edit control } + InflateRect(R, -3, -3); + //View.FreeNotification(Self); + FEditControl := TEdit.Create(nil); + try + FEditControl.Name := Format('%s_edit_control_%p', [ClassName, + Pointer(FEditControl)]); + FEditControl.Visible := False; + FEditControl.BorderStyle := bsNone; + FEditControl.AutoSize := False; + FEditControl.Font.Assign(View.GetFont); + FEditControl.Text := Item.Text; + FEditControl.CharCase := Item.FCharCase; + FEditControl.MaxLength := Item.FMaxLength; + FEditControl.BoundsRect := R; + FEditControl.WindowProc := EditWndProc; + FEditControl.ParentWindow := View.Window.Handle; + FEditControl.SelectAll; + Item.DoBeginEdit(Self); + FEditControl.Visible := True; + FEditControl.SetFocus; + if GetActiveWindow <> ActiveWnd then + { don't gray out title bar of old active window } + SendMessage(ActiveWnd, WM_NCACTIVATE, 1, 0) + else + ActiveWnd := 0; + + FEditControlStatus := [ecsContinueLoop]; + ControlMessageLoop; + finally + FreeAndNil(FEditControl); + end; + + { ensure the area underneath the edit control is repainted immediately } + View.Window.Update; + { If app is still active, set focus to previous control and restore capture + to CapHandle if another control hasn't taken it } + if GetActiveWindow <> 0 then begin + SetFocus(FocusWnd); + if GetCapture = 0 then + SetCapture(CapHandle); + end; + if ActiveWnd <> 0 then + SendMessage(ActiveWnd, WM_NCACTIVATE, Ord(GetActiveWindow = ActiveWnd), 0); + { The SetFocus call above can change the Z order of windows. If the parent + window is a popup window, reassert its topmostness. } + if View.Window is TTBPopupWindow then + SetWindowPos(View.Window.Handle, HWND_TOPMOST, 0, 0, 0, 0, + SWP_NOACTIVATE or SWP_NOMOVE or SWP_NOSIZE); + { Send an MSAA "focus" event now that we're returning to the regular modal loop } + View.NotifyFocusEvent; + + Result := ecsClose in FEditControlStatus; + if not Result and (GetCapture = CapHandle) then begin + if ecsAccept in FEditControlStatus then + { if we are accepting but not closing, Tab must have been pressed } + View.Selected := View.NextSelectable(View.Selected, + GetKeyState(VK_SHIFT) >= 0); + end; +end; + +function TTBEditItemViewer.DoExecute: Boolean; +begin + { Close any delay-close popup menus before entering the edit loop } + View.CancelChildPopups; + Result := False; + if EditLoop(View.GetCaptureWnd) then begin + View.EndModal; + if ecsAccept in FEditControlStatus then + Result := True; + end; +end; + +procedure TTBEditItemViewer.MouseBeginEdit; +begin + if Item.Enabled then + Execute(True) + else begin + if (View.ParentView = nil) and not View.IsPopup then + View.EndModal; + end; +end; + +procedure TTBEditItemViewer.MouseDown(Shift: TShiftState; X, Y: Integer; + var MouseDownOnMenu: Boolean); +begin + if IsPtInButtonPart(X, Y) then { for TBX... } + MouseBeginEdit + else + inherited; +end; + +procedure TTBEditItemViewer.MouseUp(X, Y: Integer; MouseWasDownOnMenu: Boolean); +begin + if IsPtInButtonPart(X, Y) then { for TBX... } + MouseBeginEdit + else + inherited; +end; + +function TTBEditItemViewer.UsesSameWidth: Boolean; +begin + Result := False; +end; + +function TTBEditItemViewer.GetAccRole: Integer; +const + ROLE_SYSTEM_TEXT = $2a; { from OleAcc.h } +begin + Result := ROLE_SYSTEM_TEXT; +end; + +function TTBEditItemViewer.GetAccValue(var Value: WideString): Boolean; +begin + Value := TTBEditItem(Item).Text; + Result := True; +end; + + +{ TTBToolbarVisibilityItem } + +procedure TTBVisibilityToggleItem.Click; +begin + if Assigned(FControl) then + FControl.Visible := not FControl.Visible; + inherited; +end; + +procedure TTBVisibilityToggleItem.InitiateAction; +begin + UpdateProps; +end; + +procedure TTBVisibilityToggleItem.Notification(AComponent: TComponent; + Operation: TOperation); +begin + inherited; + if (Operation = opRemove) and (AComponent = FControl) then + Control := nil; +end; + +procedure TTBVisibilityToggleItem.SetControl(Value: TControl); +begin + if FControl <> Value then begin + FControl := Value; + if Assigned(Value) then begin + Value.FreeNotification(Self); + if (Caption = '') and not(csLoading in ComponentState) then + Caption := TControlAccess(Value).Caption; + end; + UpdateProps; + end; +end; + +procedure TTBVisibilityToggleItem.UpdateProps; +begin + if (ComponentState * [csDesigning, csLoading, csDestroying] = []) then + Checked := Assigned(FControl) and FControl.Visible; +end; + +end. diff --git a/official/2.1.6+2.1.beta1/Source/TB2Hook.pas b/official/2.1.6+2.1.beta1/Source/TB2Hook.pas new file mode 100644 index 0000000..87d66cc --- /dev/null +++ b/official/2.1.6+2.1.beta1/Source/TB2Hook.pas @@ -0,0 +1,311 @@ +unit TB2Hook; + +{ + Toolbar2000 + Copyright (C) 1998-2005 by Jordan Russell + All rights reserved. + + The contents of this file are subject to the "Toolbar2000 License"; you may + not use or distribute this file except in compliance with the + "Toolbar2000 License". A copy of the "Toolbar2000 License" may be found in + TB2k-LICENSE.txt or at: + http://www.jrsoftware.org/files/tb2k/TB2k-LICENSE.txt + + Alternatively, the contents of this file may be used under the terms of the + GNU General Public License (the "GPL"), in which case the provisions of the + GPL are applicable instead of those in the "Toolbar2000 License". A copy of + the GPL may be found in GPL-LICENSE.txt or at: + http://www.jrsoftware.org/files/tb2k/GPL-LICENSE.txt + If you wish to allow use of your version of this file only under the terms of + the GPL and not to allow others to use your version of this file under the + "Toolbar2000 License", indicate your decision by deleting the provisions + above and replace them with the notice and other provisions required by the + GPL. If you do not delete the provisions above, a recipient may use your + version of this file under either the "Toolbar2000 License" or the GPL. + + $jrsoftware: tb2k/Source/TB2Hook.pas,v 1.15 2005/06/26 18:21:33 jr Exp $ +} + +interface + +uses + Windows; + +type + THookProcCode = (hpSendActivate, hpSendActivateApp, hpSendWindowPosChanged, + hpPreDestroy, hpGetMessage); + THookProcCodes = set of THookProcCode; + + THookProc = procedure(Code: THookProcCode; Wnd: HWND; WParam: WPARAM; LParam: LPARAM); + +procedure InstallHookProc(AUser: TObject; AProc: THookProc; ACodes: THookProcCodes); +procedure UninstallHookProc(AUser: TObject; AProc: THookProc); + +implementation + +uses + SysUtils, Classes, Messages; + +type + THookType = (htCallWndProc, htCBT, htGetMessage); + THookTypes = set of THookType; + + PHookUserData = ^THookUserData; + THookUserData = record + Prev: PHookUserData; + User: TObject; + InstalledHookTypes: THookTypes; + end; + + PHookProcData = ^THookProcData; + THookProcData = record + Proc: THookProc; + Codes: THookProcCodes; + LastUserData: PHookUserData; + end; + +threadvar + HookHandles: array[THookType] of HHOOK; + HookProcList: TList; + HookCounts: array[THookType] of Longint; + + +function CallWndProcHook(Code: Integer; WParam: WPARAM; LParam: LPARAM): LRESULT; +stdcall; +type + THookProcCodeMsgs = hpSendActivate..hpSendWindowPosChanged; +const + MsgMap: array[THookProcCodeMsgs] of UINT = + (WM_ACTIVATE, WM_ACTIVATEAPP, WM_WINDOWPOSCHANGED); +var + J: THookProcCodeMsgs; + I: Integer; +begin + if Assigned(HookProcList) and (Code = HC_ACTION) then + with PCWPStruct(LParam)^ do begin + for J := Low(J) to High(J) do + if Message = MsgMap[J] then begin + for I := 0 to HookProcList.Count-1 do + try + with PHookProcData(HookProcList.List[I])^ do + if J in Codes then + Proc(J, hwnd, WParam, LParam); + except + end; + Break; + end; + end; + Result := CallNextHookEx(HookHandles[htCallWndProc], Code, WParam, LParam); +end; + +function CBTHook(Code: Integer; WParam: WPARAM; LParam: LPARAM): LRESULT; +stdcall; +var + I: Integer; +begin + if Assigned(HookProcList) and (Code = HCBT_DESTROYWND) then + for I := 0 to HookProcList.Count-1 do + try + with PHookProcData(HookProcList.List[I])^ do + if hpPreDestroy in Codes then + Proc(hpPreDestroy, HWND(WParam), 0, 0); + except + end; + Result := CallNextHookEx(HookHandles[htCBT], Code, WParam, LParam); +end; + +function GetMessageHook(Code: Integer; WParam: WPARAM; LParam: LPARAM): LRESULT; +stdcall; +var + I: Integer; +begin + if Assigned(HookProcList) and (Code = HC_ACTION) then + for I := 0 to HookProcList.Count-1 do + try + with PHookProcData(HookProcList.List[I])^ do + if hpGetMessage in Codes then + Proc(hpGetMessage, 0, WParam, LParam); + except + end; + Result := CallNextHookEx(HookHandles[htGetMessage], Code, WParam, LParam); +end; + +function HookCodesToTypes(Codes: THookProcCodes): THookTypes; +const + HookCodeToType: array[THookProcCode] of THookType = + (htCallWndProc, htCallWndProc, htCallWndProc, htCBT, htGetMessage); +var + J: THookProcCode; +begin + Result := []; + for J := Low(J) to High(J) do + if J in Codes then + Include(Result, HookCodeToType[J]); +end; + +const + HookProcs: array[THookType] of TFNHookProc = + (CallWndProcHook, CBTHook, GetMessageHook); + HookIDs: array[THookType] of Integer = + (WH_CALLWNDPROC, WH_CBT, WH_GETMESSAGE); + +procedure InstallHooks(ATypes: THookTypes; var InstalledTypes: THookTypes); +var + T: THookType; +begin + { Don't increment reference counts for hook types that were already + installed previously } + ATypes := ATypes - InstalledTypes; + + { Increment reference counts first. This should never raise an exception. } + for T := Low(T) to High(T) do + if T in ATypes then begin + Inc(HookCounts[T]); + Include(InstalledTypes, T); + end; + + { Then install the hooks } + for T := Low(T) to High(T) do + if T in InstalledTypes then begin + if HookHandles[T] = 0 then begin + { On Windows NT platforms, SetWindowsHookExW is used to work around an + apparent bug in Windows NT/2000/XP: if an 'ANSI' WH_GETMESSAGE hook + is called *before* a 'wide' WH_GETMESSAGE hook, then WM_*CHAR + messages passed to the 'wide' hook use ANSI character codes. + This is needed for compatibility with the combination of Tnt Unicode + Controls and Keyman. See "Widechar's and tb2k" thread on the + newsgroup from 2003-09-23 for more information. } + if Win32Platform = VER_PLATFORM_WIN32_NT then + HookHandles[T] := SetWindowsHookExW(HookIDs[T], HookProcs[T], + 0, GetCurrentThreadId) + else + HookHandles[T] := SetWindowsHookEx(HookIDs[T], HookProcs[T], + 0, GetCurrentThreadId); + end; + end; +end; + +procedure UninstallHooks(const ATypes: THookTypes; const Force: Boolean); +var + T: THookType; +begin + { Decrement reference counts first. This should never raise an exception. } + if not Force then + for T := Low(T) to High(T) do + if T in ATypes then + Dec(HookCounts[T]); + + { Then uninstall the hooks } + for T := Low(T) to High(T) do + if T in ATypes then begin + if (Force or (HookCounts[T] = 0)) and (HookHandles[T] <> 0) then begin + UnhookWindowsHookEx(HookHandles[T]); + HookHandles[T] := 0; + end; + end; +end; + +procedure InstallHookProc(AUser: TObject; AProc: THookProc; ACodes: THookProcCodes); +var + Found: Boolean; + I: Integer; + UserData: PHookUserData; + ProcData: PHookProcData; +label 1; +begin + if HookProcList = nil then + HookProcList := TList.Create; + Found := False; + UserData := nil; { avoid warning } + for I := 0 to HookProcList.Count-1 do begin + ProcData := PHookProcData(HookProcList[I]); + if @ProcData.Proc = @AProc then begin + UserData := ProcData.LastUserData; + while Assigned(UserData) do begin + if UserData.User = AUser then begin + { InstallHookProc was already called for AUser/AProc. Go ahead and + call InstallHooks again just in case the hooks weren't successfully + installed last time. } + goto 1; + end; + UserData := UserData.Prev; + end; + New(UserData); + UserData.Prev := ProcData.LastUserData; + UserData.User := AUser; + UserData.InstalledHookTypes := []; + ProcData.LastUserData := UserData; + Found := True; + Break; + end; + end; + if not Found then begin + New(UserData); + try + UserData.Prev := nil; + UserData.User := AUser; + UserData.InstalledHookTypes := []; + HookProcList.Expand; + New(ProcData); + except + Dispose(UserData); + raise; + end; + ProcData.Proc := AProc; + ProcData.Codes := ACodes; + ProcData.LastUserData := UserData; + HookProcList.Add(ProcData); + end; +1:InstallHooks(HookCodesToTypes(ACodes), UserData.InstalledHookTypes); +end; + +procedure UninstallHookProc(AUser: TObject; AProc: THookProc); +var + I: Integer; + ProcData: PHookProcData; + NextUserData, UserData: PHookUserData; + T: THookTypes; +begin + if HookProcList = nil then Exit; + for I := 0 to HookProcList.Count-1 do begin + ProcData := PHookProcData(HookProcList[I]); + if @ProcData.Proc = @AProc then begin + { Locate the UserData record } + NextUserData := nil; + UserData := ProcData.LastUserData; + while Assigned(UserData) and (UserData.User <> AUser) do begin + NextUserData := UserData; + UserData := UserData.Prev; + end; + if UserData = nil then + Exit; + + { Remove record from linked list } + if NextUserData = nil then begin + { It's the last item in the list } + if UserData.Prev = nil then begin + { It's the only item in the list, so destroy the ProcData record } + HookProcList.Delete(I); + Dispose(ProcData); + end + else + ProcData.LastUserData := UserData.Prev; + end + else + NextUserData.Prev := UserData.Prev; + + T := UserData.InstalledHookTypes; + Dispose(UserData); + UninstallHooks(T, False); + Break; + end; + end; + if HookProcList.Count = 0 then + FreeAndNil(HookProcList); +end; + + +initialization +finalization + UninstallHooks([Low(THookType)..High(THookType)], True); +end. diff --git a/official/2.1.6+2.1.beta1/Source/TB2Item.pas b/official/2.1.6+2.1.beta1/Source/TB2Item.pas new file mode 100644 index 0000000..3a87052 --- /dev/null +++ b/official/2.1.6+2.1.beta1/Source/TB2Item.pas @@ -0,0 +1,6905 @@ +unit TB2Item; + +{ + Toolbar2000 + Copyright (C) 1998-2005 by Jordan Russell + All rights reserved. + + The contents of this file are subject to the "Toolbar2000 License"; you may + not use or distribute this file except in compliance with the + "Toolbar2000 License". A copy of the "Toolbar2000 License" may be found in + TB2k-LICENSE.txt or at: + http://www.jrsoftware.org/files/tb2k/TB2k-LICENSE.txt + + Alternatively, the contents of this file may be used under the terms of the + GNU General Public License (the "GPL"), in which case the provisions of the + GPL are applicable instead of those in the "Toolbar2000 License". A copy of + the GPL may be found in GPL-LICENSE.txt or at: + http://www.jrsoftware.org/files/tb2k/GPL-LICENSE.txt + If you wish to allow use of your version of this file only under the terms of + the GPL and not to allow others to use your version of this file under the + "Toolbar2000 License", indicate your decision by deleting the provisions + above and replace them with the notice and other provisions required by the + GPL. If you do not delete the provisions above, a recipient may use your + version of this file under either the "Toolbar2000 License" or the GPL. + + $jrsoftware: tb2k/Source/TB2Item.pas,v 1.277 2005/06/23 21:55:44 jr Exp $ +} + +interface + +{$I TB2Ver.inc} +{x$DEFINE TB2K_NO_ANIMATION} + { Enabling the above define disables all menu animation. For debugging + purpose only. } +{x$DEFINE TB2K_USE_STRICT_O2K_MENU_STYLE} + { Enabling the above define forces it to use clBtnFace for the menu color + instead of clMenu, and disables the use of flat menu borders on Windows + XP with themes enabled. } + +uses + Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, + StdCtrls, CommCtrl, Menus, ActnList, ImgList, TB2Anim; + +const + WM_TB2K_POPUPSHOWING = WM_USER + 554; + + { Parameter in LParam of WM_TB2K_POPUPSHOWING } + TPS_ANIMSTART = 1; // animation query: if Result <> 0, do not animate! + TPS_ANIMFINISHED = 2; // only fired when animation thread is done + TPS_NOANIM = 3; // fired when animation is done, or if showing with no animation + +type + TTBCustomItem = class; + TTBCustomItemClass = class of TTBCustomItem; + TTBCustomItemActionLink = class; + TTBCustomItemActionLinkClass = class of TTBCustomItemActionLink; + TTBItemViewer = class; + TTBItemViewerClass = class of TTBItemViewer; + TTBPopupWindow = class; + TTBPopupWindowClass = class of TTBPopupWindow; + TTBView = class; + + TTBDoneAction = (tbdaNone, tbdaCancel, tbdaClickItem, tbdaOpenSystemMenu, + tbdaHelpContext); + PTBDoneActionData = ^TTBDoneActionData; + TTBDoneActionData = record + DoneAction: TTBDoneAction; + case TTBDoneAction of + tbdaClickItem: (ClickItem: TTBCustomItem; Sound: Boolean); + tbdaOpenSystemMenu: (Wnd: HWND; Key: Cardinal); + tbdaHelpContext: (ContextID: Integer); + end; + TTBInsertItemProc = procedure(AParent: TComponent; AItem: TTBCustomItem) of object; + TTBItemChangedAction = (tbicInserted, tbicDeleting, tbicSubitemsChanged, + tbicSubitemsBeginUpdate, tbicSubitemsEndUpdate, tbicInvalidate, + tbicInvalidateAndResize, tbicRecreateItemViewers, tbicNameChanged, + tbicSubMenuImagesChanged); + TTBItemChangedProc = procedure(Sender: TTBCustomItem; Relayed: Boolean; + Action: TTBItemChangedAction; Index: Integer; Item: TTBCustomItem) of object; + TTBItemData = record + Item: TTBCustomItem; + end; + PTBItemDataArray = ^TTBItemDataArray; + TTBItemDataArray = array[0..$7FFFFFFF div SizeOf(TTBItemData)-1] of TTBItemData; + TTBItemDisplayMode = (nbdmDefault, nbdmTextOnly, nbdmTextOnlyInMenus, nbdmImageAndText); + TTBItemOption = (tboDefault, tboDropdownArrow, tboImageAboveCaption, + tboLongHintInMenuOnly, tboNoAutoHint, tboNoRotation, tboSameWidth, + tboShowHint, tboToolbarStyle, tboToolbarSize); + TTBItemOptions = set of TTBItemOption; + TTBItemStyle = set of (tbisSubmenu, tbisSelectable, tbisSeparator, + tbisEmbeddedGroup, tbisClicksTransparent, tbisCombo, tbisNoAutoOpen, + tbisSubitemsEditable, tbisNoLineBreak, tbisRightAlign, tbisDontSelectFirst, + tbisRedrawOnSelChange, tbisRedrawOnMouseOverChange, tbisStretch); + TTBPopupAlignment = (tbpaLeft, tbpaRight, tbpaCenter); + TTBPopupEvent = procedure(Sender: TTBCustomItem; FromLink: Boolean) of object; + TTBSelectEvent = procedure(Sender: TTBCustomItem; Viewer: TTBItemViewer; + Selecting: Boolean) of object; + + ETBItemError = class(Exception); + + TTBImageChangeLink = class(TChangeLink) + private + FLastWidth, FLastHeight: Integer; + end; + {$IFNDEF JR_D5} + TImageIndex = type Integer; + {$ENDIF} + TTBPopupPositionRec = record + PositionAsSubmenu: Boolean; + Alignment: TTBPopupAlignment; + Opposite: Boolean; + MonitorRect: TRect; + ParentItemRect: TRect; + NCSizeX: Integer; + NCSizeY: Integer; + X, Y, W, H: Integer; + AnimDir: TTBAnimationDirection; + PlaySound: Boolean; + end; + + TTBCustomItem = class(TComponent) + private + FActionLink: TTBCustomItemActionLink; + FAutoCheck: Boolean; + FCaption: String; + FChecked: Boolean; + FDisplayMode: TTBItemDisplayMode; + FEnabled: Boolean; + FEffectiveOptions: TTBItemOptions; + FGroupIndex: Integer; + FHelpContext: THelpContext; + FHint: String; + FImageIndex: TImageIndex; + FImages: TCustomImageList; + FImagesChangeLink: TTBImageChangeLink; + FItems: PTBItemDataArray; + FItemCount: Integer; + FItemStyle: TTBItemStyle; + FLinkParents: TList; + FMaskOptions: TTBItemOptions; + FOptions: TTBItemOptions; + FInheritOptions: Boolean; + FNotifyList: TList; + FOnClick: TNotifyEvent; + FOnPopup: TTBPopupEvent; + FOnSelect: TTBSelectEvent; + FParent: TTBCustomItem; + FParentComponent: TComponent; + FRadioItem: Boolean; + FShortCut: TShortCut; + FSubMenuImages: TCustomImageList; + FSubMenuImagesChangeLink: TTBImageChangeLink; + FLinkSubitems: TTBCustomItem; + FVisible: Boolean; + + procedure DoActionChange(Sender: TObject); + function ChangeImages(var AImages: TCustomImageList; + const Value: TCustomImageList; var AChangeLink: TTBImageChangeLink): Boolean; + class procedure ClickWndProc(var Message: TMessage); + function FindItemWithShortCut(AShortCut: TShortCut; + var ATopmostParent: TTBCustomItem): TTBCustomItem; + function FixOptions(const AOptions: TTBItemOptions): TTBItemOptions; + function GetAction: TBasicAction; + function GetItem(Index: Integer): TTBCustomItem; + procedure ImageListChangeHandler(Sender: TObject); + procedure InternalNotify(Ancestor: TTBCustomItem; NestingLevel: Integer; + Action: TTBItemChangedAction; Index: Integer; Item: TTBCustomItem); + {$IFDEF JR_D6} + function IsAutoCheckStored: Boolean; + {$ENDIF} + function IsCaptionStored: Boolean; + function IsCheckedStored: Boolean; + function IsEnabledStored: Boolean; + function IsHelpContextStored: Boolean; + function IsHintStored: Boolean; + function IsImageIndexStored: Boolean; + function IsOnClickStored: Boolean; + function IsShortCutStored: Boolean; + function IsVisibleStored: Boolean; + procedure Notify(Action: TTBItemChangedAction; Index: Integer; Item: TTBCustomItem); + procedure RefreshOptions; + procedure SetAction(Value: TBasicAction); + procedure SetCaption(Value: String); + procedure SetChecked(Value: Boolean); + procedure SetDisplayMode(Value: TTBItemDisplayMode); + procedure SetEnabled(Value: Boolean); + procedure SetGroupIndex(Value: Integer); + procedure SetImageIndex(Value: TImageIndex); + procedure SetImages(Value: TCustomImageList); + procedure SetInheritOptions(Value: Boolean); + procedure SetLinkSubitems(Value: TTBCustomItem); + procedure SetMaskOptions(Value: TTBItemOptions); + procedure SetOptions(Value: TTBItemOptions); + procedure SetRadioItem(Value: Boolean); + procedure SetSubMenuImages(Value: TCustomImageList); + procedure SetVisible(Value: Boolean); + procedure SubMenuImagesChanged; + procedure TurnSiblingsOff; + protected + procedure ActionChange(Sender: TObject; CheckDefaults: Boolean); dynamic; + procedure Change(NeedResize: Boolean); virtual; + function CreatePopup(const ParentView: TTBView; const ParentViewer: TTBItemViewer; + const PositionAsSubmenu, SelectFirstItem, Customizing: Boolean; + const APopupPoint: TPoint; const Alignment: TTBPopupAlignment): TTBPopupWindow; virtual; + procedure DoPopup(Sender: TTBCustomItem; FromLink: Boolean); virtual; + procedure EnabledChanged; virtual; + function GetActionLinkClass: TTBCustomItemActionLinkClass; dynamic; + function GetChevronParentView: TTBView; virtual; + procedure GetChildren(Proc: TGetChildProc; Root: TComponent); override; + function GetItemViewerClass(AView: TTBView): TTBItemViewerClass; virtual; + procedure GetPopupPosition(ParentView: TTBView; + PopupWindow: TTBPopupWindow; var PopupPositionRec: TTBPopupPositionRec); virtual; + function GetPopupWindowClass: TTBPopupWindowClass; virtual; + procedure IndexError; + procedure Loaded; override; + function NeedToRecreateViewer(AViewer: TTBItemViewer): Boolean; virtual; + procedure Notification(AComponent: TComponent; Operation: TOperation); override; + function OpenPopup(const SelectFirstItem, TrackRightButton: Boolean; + const PopupPoint: TPoint; const Alignment: TTBPopupAlignment; + const ReturnClickedItemOnly: Boolean): TTBCustomItem; + procedure RecreateItemViewers; + procedure SetChildOrder(Child: TComponent; Order: Integer); override; + procedure SetName(const NewName: TComponentName); override; + procedure SetParentComponent(Value: TComponent); override; + + property ActionLink: TTBCustomItemActionLink read FActionLink write FActionLink; + property ItemStyle: TTBItemStyle read FItemStyle write FItemStyle; + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + function HasParent: Boolean; override; + function GetParentComponent: TComponent; override; + + procedure Add(AItem: TTBCustomItem); + procedure Clear; + procedure Click; virtual; + function ContainsItem(AItem: TTBCustomItem): Boolean; + procedure Delete(Index: Integer); + function GetShortCutText: String; + function IndexOf(AItem: TTBCustomItem): Integer; + procedure InitiateAction; virtual; + procedure Insert(NewIndex: Integer; AItem: TTBCustomItem); + function IsShortCut(var Message: TWMKey): Boolean; + procedure Move(CurIndex, NewIndex: Integer); + function Popup(X, Y: Integer; TrackRightButton: Boolean; + Alignment: TTBPopupAlignment = tbpaLeft; + ReturnClickedItemOnly: Boolean = False): TTBCustomItem; + procedure PostClick; + procedure RegisterNotification(ANotify: TTBItemChangedProc); + procedure Remove(Item: TTBCustomItem); + procedure UnregisterNotification(ANotify: TTBItemChangedProc); + procedure ViewBeginUpdate; + procedure ViewEndUpdate; + + property Action: TBasicAction read GetAction write SetAction; + property AutoCheck: Boolean read FAutoCheck write FAutoCheck {$IFDEF JR_D6} stored IsAutoCheckStored {$ENDIF} default False; + property Caption: String read FCaption write SetCaption stored IsCaptionStored; + property Count: Integer read FItemCount; + property Checked: Boolean read FChecked write SetChecked stored IsCheckedStored default False; + property DisplayMode: TTBItemDisplayMode read FDisplayMode write SetDisplayMode default nbdmDefault; + property EffectiveOptions: TTBItemOptions read FEffectiveOptions; + property Enabled: Boolean read FEnabled write SetEnabled stored IsEnabledStored default True; + property GroupIndex: Integer read FGroupIndex write SetGroupIndex default 0; + property HelpContext: THelpContext read FHelpContext write FHelpContext stored IsHelpContextStored default 0; + property Hint: String read FHint write FHint stored IsHintStored; + property ImageIndex: TImageIndex read FImageIndex write SetImageIndex stored IsImageIndexStored default -1; + property Images: TCustomImageList read FImages write SetImages; + property InheritOptions: Boolean read FInheritOptions write SetInheritOptions default True; + property Items[Index: Integer]: TTBCustomItem read GetItem; default; + property LinkSubitems: TTBCustomItem read FLinkSubitems write SetLinkSubitems; + property MaskOptions: TTBItemOptions read FMaskOptions write SetMaskOptions default []; + property Options: TTBItemOptions read FOptions write SetOptions default []; + property Parent: TTBCustomItem read FParent; + property ParentComponent: TComponent read FParentComponent write FParentComponent; + property RadioItem: Boolean read FRadioItem write SetRadioItem default False; + property ShortCut: TShortCut read FShortCut write FShortCut stored IsShortCutStored default 0; + property SubMenuImages: TCustomImageList read FSubMenuImages write SetSubMenuImages; + property Visible: Boolean read FVisible write SetVisible stored IsVisibleStored default True; + property OnClick: TNotifyEvent read FOnClick write FOnClick stored IsOnClickStored; + property OnPopup: TTBPopupEvent read FOnPopup write FOnPopup; + property OnSelect: TTBSelectEvent read FOnSelect write FOnSelect; + end; + + TTBCustomItemActionLink = class(TActionLink) + protected + FClient: TTBCustomItem; + procedure AssignClient(AClient: TObject); override; + {$IFDEF JR_D6} + function IsAutoCheckLinked: Boolean; virtual; + {$ENDIF} + function IsCaptionLinked: Boolean; override; + function IsCheckedLinked: Boolean; override; + function IsEnabledLinked: Boolean; override; + function IsHelpContextLinked: Boolean; override; + function IsHintLinked: Boolean; override; + function IsImageIndexLinked: Boolean; override; + function IsShortCutLinked: Boolean; override; + function IsVisibleLinked: Boolean; override; + function IsOnExecuteLinked: Boolean; override; + {$IFDEF JR_D6} + procedure SetAutoCheck(Value: Boolean); override; + {$ENDIF} + procedure SetCaption(const Value: String); override; + procedure SetChecked(Value: Boolean); override; + procedure SetEnabled(Value: Boolean); override; + procedure SetHelpContext(Value: THelpContext); override; + procedure SetHint(const Value: String); override; + procedure SetImageIndex(Value: Integer); override; + procedure SetShortCut(Value: TShortCut); override; + procedure SetVisible(Value: Boolean); override; + procedure SetOnExecute(Value: TNotifyEvent); override; + end; + + TTBBaseAccObject = class(TInterfacedObject, IDispatch) + public + procedure ClientIsDestroying; virtual; abstract; + { IDispatch } + function GetTypeInfoCount(out Count: Integer): HResult; stdcall; + function GetTypeInfo(Index, LocaleID: Integer; out TypeInfo): HResult; stdcall; + function GetIDsOfNames(const IID: TGUID; Names: Pointer; + NameCount, LocaleID: Integer; DispIDs: Pointer): HResult; stdcall; + function Invoke(DispID: Integer; const IID: TGUID; LocaleID: Integer; + Flags: Word; var Params; VarResult, ExcepInfo, ArgErr: Pointer): HResult; stdcall; + end; + + TTBItemViewer = class + private + FBoundsRect: TRect; + FClipped: Boolean; + FGroupLevel: Integer; + FItem: TTBCustomItem; + FOffEdge: Boolean; + FShow: Boolean; + FView: TTBView; + procedure AccSelect(const AExecute: Boolean); + function GetIndex: Integer; + protected + FAccObjectInstance: TTBBaseAccObject; + procedure CalcSize(const Canvas: TCanvas; var AWidth, AHeight: Integer); + virtual; + function CaptionShown: Boolean; dynamic; + function DoExecute: Boolean; virtual; + procedure DrawItemCaption(const Canvas: TCanvas; ARect: TRect; + const ACaption: String; ADrawDisabledShadow: Boolean; AFormat: UINT); virtual; + procedure Entering(OldSelected: TTBItemViewer); virtual; + function GetAccRole: Integer; virtual; + function GetAccValue(var Value: WideString): Boolean; virtual; + function GetCaptionText: String; virtual; + procedure GetCursor(const Pt: TPoint; var ACursor: HCURSOR); virtual; + function GetImageList: TCustomImageList; + function ImageShown: Boolean; + function IsRotated: Boolean; + function IsToolbarSize: Boolean; virtual; + function IsPtInButtonPart(X, Y: Integer): Boolean; virtual; + procedure KeyDown(var Key: Word; Shift: TShiftState); virtual; + procedure Leaving; virtual; + procedure LosingCapture; virtual; + procedure MouseDown(Shift: TShiftState; X, Y: Integer; + var MouseDownOnMenu: Boolean); virtual; + procedure MouseMove(X, Y: Integer); virtual; + procedure MouseUp(X, Y: Integer; MouseWasDownOnMenu: Boolean); virtual; + procedure MouseWheel(WheelDelta: Integer; X, Y: Integer); virtual; + procedure Paint(const Canvas: TCanvas; const ClientAreaRect: TRect; + IsSelected, IsPushed, UseDisabledShadow: Boolean); virtual; + procedure PostAccSelect(const AExecute: Boolean); + function UsesSameWidth: Boolean; virtual; + public + State: set of (tbisInvalidated, tbisLineSep); + property BoundsRect: TRect read FBoundsRect; + property Clipped: Boolean read FClipped; + property Index: Integer read GetIndex; + property Item: TTBCustomItem read FItem; + property OffEdge: Boolean read FOffEdge; + property Show: Boolean read FShow; + property View: TTBView read FView; + constructor Create(AView: TTBView; AItem: TTBCustomItem; AGroupLevel: Integer); virtual; + destructor Destroy; override; + procedure Execute(AGivePriority: Boolean); + function GetAccObject: IDispatch; + function GetHintText: String; + function IsAccessible: Boolean; + function IsToolbarStyle: Boolean; virtual; + function ScreenToClient(const P: TPoint): TPoint; + end; + PTBItemViewerArray = ^TTBItemViewerArray; + TTBItemViewerArray = array[0..$7FFFFFFF div SizeOf(TTBItemViewer)-1] of TTBItemViewer; + TTBViewOrientation = (tbvoHorizontal, tbvoVertical, tbvoFloating); + TTBEnterToolbarLoopOptions = set of (tbetMouseDown, tbetExecuteSelected, + tbetFromMSAA); + TTBViewState = set of (vsModal, vsMouseInWindow, vsDrawInOrder, vsOppositePopup, + vsIgnoreFirstMouseUp, vsShowAccels, vsDropDownMenus, vsNoAnimation); + TTBViewStyle = set of (vsMenuBar, vsUseHiddenAccels, vsAlwaysShowHints); + TTBViewTimerID = (tiOpen, tiClose, tiScrollUp, tiScrollDown); + + TTBViewClass = class of TTBView; + TTBView = class(TComponent) + private + FActiveTimers: set of TTBViewTimerID; + FBackgroundColor: TColor; + FBaseSize: TPoint; + FCapture: Boolean; + FCaptureWnd: HWND; + FChevronOffset: Integer; + FChevronParentView: TTBView; + FChevronSize: Integer; + FCurParentItem: TTBCustomItem; + FCustomizing: Boolean; + FDoneActionData: TTBDoneActionData; + FInternalViewersAtEnd: Integer; + FInternalViewersAtFront: Integer; + FIsPopup: Boolean; + FIsToolbar: Boolean; + FMaxHeight: Integer; + FMonitorRect: TRect; + FMouseOverSelected: Boolean; + FNewViewersGetHighestPriority: Boolean; + FOpenViewer: TTBItemViewer; + FOpenViewerView: TTBView; + FOpenViewerWindow: TTBPopupWindow; + FParentView: TTBView; + FParentItem: TTBCustomItem; + FPriorityList: TList; + FOrientation: TTBViewOrientation; + FScrollOffset: Integer; + FSelected: TTBItemViewer; + FSelectedViaMouse: Boolean; + FShowDownArrow: Boolean; + FShowUpArrow: Boolean; + FState: TTBViewState; + FStyle: TTBViewStyle; + FUpdating: Integer; + FUsePriorityList: Boolean; + FValidated: Boolean; + FViewerCount: Integer; + FViewers: PTBItemViewerArray; + FWindow: TWinControl; + FWrapOffset: Integer; + + procedure DeletingViewer(Viewer: TTBItemViewer); + procedure DrawItem(Viewer: TTBItemViewer; DrawTo: TCanvas; Offscreen: Boolean); + procedure FreeViewers; + procedure ImagesChanged; + function InsertItemViewers(const NewIndex: Integer; + const AItem: TTBCustomItem; const AGroupLevel: Integer; + const AddToPriorityList, TopOfPriorityList: Boolean): Integer; + procedure ItemNotification(Ancestor: TTBCustomItem; Relayed: Boolean; + Action: TTBItemChangedAction; Index: Integer; Item: TTBCustomItem); + procedure LinkNotification(Ancestor: TTBCustomItem; Relayed: Boolean; + Action: TTBItemChangedAction; Index: Integer; Item: TTBCustomItem); + procedure RecreateItemViewer(const I: Integer); + procedure Scroll(ADown: Boolean); + procedure SetCustomizing(Value: Boolean); + procedure SetSelected(Value: TTBItemViewer); + procedure SetUsePriorityList(Value: Boolean); + procedure StartTimer(const ATimer: TTBViewTimerID; const Interval: Integer); + procedure StopAllTimers; + procedure StopTimer(const ATimer: TTBViewTimerID); + procedure UpdateCurParentItem; + protected + FAccObjectInstance: TTBBaseAccObject; + procedure AutoSize(AWidth, AHeight: Integer); virtual; + function CalculatePositions(const CanMoveControls: Boolean; + const AOrientation: TTBViewOrientation; + AWrapOffset, AChevronOffset, AChevronSize: Integer; + var ABaseSize, TotalSize: TPoint; + var AWrappedLines: Integer): Boolean; + procedure DoUpdatePositions(var ASize: TPoint); virtual; + function GetChevronItem: TTBCustomItem; virtual; + procedure GetMargins(AOrientation: TTBViewOrientation; var Margins: TRect); + virtual; + function GetMDIButtonsItem: TTBCustomItem; virtual; + function GetMDISystemMenuItem: TTBCustomItem; virtual; + function GetParentToolbarView: TTBView; + function GetRootView: TTBView; + function HandleWMGetObject(var Message: TMessage): Boolean; + procedure InitiateActions; + procedure KeyDown(var Key: Word; Shift: TShiftState); virtual; + procedure Notification(AComponent: TComponent; Operation: TOperation); override; + procedure SetAccelsVisibility(AShowAccels: Boolean); + procedure SetState(AState: TTBViewState); + property DoneActionData: TTBDoneActionData read FDoneActionData write FDoneActionData; + property ShowDownArrow: Boolean read FShowDownArrow; {vb+} + property ShowUpArrow: Boolean read FShowUpArrow; {vb+} + public + constructor CreateView(AOwner: TComponent; AParentView: TTBView; + AParentItem: TTBCustomItem; AWindow: TWinControl; + AIsToolbar, ACustomizing, AUsePriorityList: Boolean); virtual; + destructor Destroy; override; + procedure BeginUpdate; + procedure CancelCapture; + procedure CancelChildPopups; + procedure CancelMode; + procedure CloseChildPopups; + function ContainsView(AView: TTBView): Boolean; + procedure DrawSubitems(ACanvas: TCanvas); + procedure EndModal; + procedure EndModalWithClick(AViewer: TTBItemViewer); + procedure EndModalWithHelp(AContextID: Integer); + procedure EndModalWithSystemMenu(AWnd: HWND; AKey: Cardinal); + procedure EndUpdate; + procedure EnterToolbarLoop(Options: TTBEnterToolbarLoopOptions); + procedure ExecuteSelected(AGivePriority: Boolean); + function Find(Item: TTBCustomItem): TTBItemViewer; + function FirstSelectable: TTBItemViewer; + function GetAccObject: IDispatch; + function GetCaptureWnd: HWND; + function GetFont: TFont; virtual; + procedure GetOffEdgeControlList(const List: TList); + procedure GivePriority(AViewer: TTBItemViewer); + function HighestPriorityViewer: TTBItemViewer; + procedure Invalidate(AViewer: TTBItemViewer); + procedure InvalidatePositions; virtual; + function IndexOf(AViewer: TTBItemViewer): Integer; + function IsModalEnding: Boolean; + function NextSelectable(CurViewer: TTBItemViewer; GoForward: Boolean): TTBItemViewer; + function NextSelectableWithAccel(CurViewer: TTBItemViewer; Key: Char; + RequirePrimaryAccel: Boolean; var IsOnlyItemWithAccel: Boolean): TTBItemViewer; + procedure NotifyFocusEvent; + function OpenChildPopup(const SelectFirstItem: Boolean): Boolean; + procedure RecreateAllViewers; + procedure ScrollSelectedIntoView; + procedure Select(Value: TTBItemViewer; ViaMouse: Boolean); + procedure SetCapture; + procedure TryValidatePositions; + procedure UpdateSelection(const P: PPoint; const AllowNewSelection: Boolean); + function UpdatePositions: TPoint; + procedure ValidatePositions; + function ViewerFromPoint(const P: TPoint): TTBItemViewer; + + property BackgroundColor: TColor read FBackgroundColor write FBackgroundColor; + property BaseSize: TPoint read FBaseSize; + property Capture: Boolean read FCapture; + property ChevronOffset: Integer read FChevronOffset write FChevronOffset; + property ChevronSize: Integer read FChevronSize write FChevronSize; + property Customizing: Boolean read FCustomizing write SetCustomizing; + property IsPopup: Boolean read FIsPopup; + property IsToolbar: Boolean read FIsToolbar; + property MouseOverSelected: Boolean read FMouseOverSelected; + property NewViewersGetHighestPriority: Boolean read FNewViewersGetHighestPriority + write FNewViewersGetHighestPriority; + property ParentView: TTBView read FParentView; + property ParentItem: TTBCustomItem read FParentItem; + property OpenViewer: TTBItemViewer read FOpenViewer; + property OpenViewerView: TTBView read FOpenViewerView; + property Orientation: TTBViewOrientation read FOrientation write FOrientation; + property Selected: TTBItemViewer read FSelected write SetSelected; + property SelectedViaMouse: Boolean read FSelectedViaMouse; + property State: TTBViewState read FState; + property Style: TTBViewStyle read FStyle write FStyle; + property UsePriorityList: Boolean read FUsePriorityList write SetUsePriorityList; + property Viewers: PTBItemViewerArray read FViewers; + property ViewerCount: Integer read FViewerCount; + property Window: TWinControl read FWindow; + property WrapOffset: Integer read FWrapOffset write FWrapOffset; + end; + + TTBRootItemClass = class of TTBRootItem; + TTBRootItem = class(TTBCustomItem); + { same as TTBCustomItem, except there's a property editor for it } + + TTBItem = class(TTBCustomItem) + published + property Action; + property AutoCheck; + property Caption; + property Checked; + property DisplayMode; + property Enabled; + property GroupIndex; + property HelpContext; + property Hint; + property ImageIndex; + property Images; + property InheritOptions; + property MaskOptions; + property Options; + property RadioItem; + property ShortCut; + property Visible; + + property OnClick; + property OnSelect; + end; + + TTBGroupItem = class(TTBCustomItem) + public + constructor Create(AOwner: TComponent); override; + published + property InheritOptions; + property LinkSubitems; + property MaskOptions; + property Options; + end; + + TTBSubmenuItem = class(TTBCustomItem) + private + function GetDropdownCombo: Boolean; + procedure SetDropdownCombo(Value: Boolean); + public + constructor Create(AOwner: TComponent); override; + published + property Action; + property AutoCheck; + property Caption; + property Checked; + //property DisplayAsToolbar; + property DisplayMode; + property DropdownCombo: Boolean read GetDropdownCombo write SetDropdownCombo default False; + property Enabled; + property GroupIndex; + property HelpContext; + property Hint; + property ImageIndex; + property Images; + property InheritOptions; + property LinkSubitems; + property MaskOptions; + property Options; + property RadioItem; + property ShortCut; + property SubMenuImages; + property Visible; + + property OnClick; + property OnPopup; + property OnSelect; + end; + + TTBSeparatorItem = class(TTBCustomItem) + private + FBlank: Boolean; + procedure SetBlank(Value: Boolean); + protected + function GetItemViewerClass(AView: TTBView): TTBItemViewerClass; override; + public + constructor Create(AOwner: TComponent); override; + published + property Blank: Boolean read FBlank write SetBlank default False; + property Hint; + property Visible; + end; + + TTBSeparatorItemViewer = class(TTBItemViewer) + protected + procedure CalcSize(const Canvas: TCanvas; + var AWidth, AHeight: Integer); override; + procedure Paint(const Canvas: TCanvas; const ClientAreaRect: TRect; + IsSelected, IsPushed, UseDisabledShadow: Boolean); override; + function UsesSameWidth: Boolean; override; + end; + + TTBControlItem = class(TTBCustomItem) + private + FControl: TControl; + FDontFreeControl: Boolean; + procedure SetControl(Value: TControl); + protected + procedure Notification(AComponent: TComponent; Operation: TOperation); override; + public + constructor Create(AOwner: TComponent); override; + constructor CreateControlItem(AOwner: TComponent; AControl: TControl); + destructor Destroy; override; + property DontFreeControl: Boolean read FDontFreeControl write FDontFreeControl; + published + property Control: TControl read FControl write SetControl; + end; + + TTBPopupView = class(TTBView) + protected + procedure AutoSize(AWidth, AHeight: Integer); override; + public + function GetFont: TFont; override; + end; + + ITBPopupWindow = interface + ['{E45CBE74-1ECF-44CB-B064-6D45B1924708}'] + end; + + TTBPopupWindow = class(TCustomControl, ITBPopupWindow) + private + FAccelsVisibilitySet: Boolean; + FAnimationDirection: TTBAnimationDirection; + FView: TTBView; + procedure CMHintShow(var Message: TCMHintShow); message CM_HINTSHOW; + procedure CMShowingChanged(var Message: TMessage); message CM_SHOWINGCHANGED; + procedure WMClose(var Message: TWMClose); message WM_CLOSE; + procedure WMEraseBkgnd(var Message: TWMEraseBkgnd); message WM_ERASEBKGND; + procedure WMGetObject(var Message: TMessage); message WM_GETOBJECT; + procedure WMNCCalcSize(var Message: TWMNCCalcSize); message WM_NCCALCSIZE; + procedure WMNCPaint(var Message: TMessage); message WM_NCPAINT; + procedure WMPaint(var Message: TWMPaint); message WM_PAINT; + procedure WMPrint(var Message: TMessage); message WM_PRINT; + procedure WMPrintClient(var Message: TMessage); message WM_PRINTCLIENT; + procedure WMTB2kStepAnimation(var Message: TMessage); message WM_TB2K_STEPANIMATION; + procedure WMTB2kAnimationEnded (var Message: TMessage); message WM_TB2K_ANIMATIONENDED; + protected + procedure CreateParams(var Params: TCreateParams); override; + procedure CreateWnd; override; + procedure DestroyWindowHandle; override; + function GetNCSize: TPoint; dynamic; + function GetViewClass: TTBViewClass; dynamic; + procedure Paint; override; + procedure PaintScrollArrows; virtual; + property AnimationDirection: TTBAnimationDirection read FAnimationDirection; + public + constructor CreatePopupWindow(AOwner: TComponent; const AParentView: TTBView; + const AItem: TTBCustomItem; const ACustomizing: Boolean); virtual; + destructor Destroy; override; + procedure BeforeDestruction; override; + + property View: TTBView read FView; + end; + + ITBItems = interface + ['{A5C0D7CC-3EC4-4090-A0F8-3D03271877EA}'] + function GetItems: TTBCustomItem; + end; + + TTBItemContainer = class(TComponent, ITBItems) + private + FItem: TTBRootItem; + function GetImages: TCustomImageList; + function GetItems: TTBCustomItem; + procedure SetImages(Value: TCustomImageList); + protected + procedure GetChildren(Proc: TGetChildProc; Root: TComponent); override; + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + + property Items: TTBRootItem read FItem; + published + property Images: TCustomImageList read GetImages write SetImages; + end; + + TTBPopupMenu = class(TPopupMenu, ITBItems) + private + FItem: TTBRootItem; + //procedure SetItems(Value: TTBCustomItem); + function GetImages: TCustomImageList; + function GetItems: TTBCustomItem; + function GetLinkSubitems: TTBCustomItem; + function GetOptions: TTBItemOptions; + procedure RootItemClick(Sender: TObject); + procedure SetImages(Value: TCustomImageList); + procedure SetLinkSubitems(Value: TTBCustomItem); + procedure SetOptions(Value: TTBItemOptions); + protected + {$IFNDEF JR_D5} + procedure DoPopup(Sender: TObject); + {$ENDIF} + procedure GetChildren(Proc: TGetChildProc; Root: TComponent); override; + function GetRootItemClass: TTBRootItemClass; dynamic; + procedure SetChildOrder(Child: TComponent; Order: Integer); override; + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + function IsShortCut(var Message: TWMKey): Boolean; override; + procedure Popup(X, Y: Integer); override; + function PopupEx(X, Y: Integer; ReturnClickedItemOnly: Boolean = False): TTBCustomItem; + published + property Images: TCustomImageList read GetImages write SetImages; + property Items: TTBRootItem read FItem; + property LinkSubitems: TTBCustomItem read GetLinkSubitems write SetLinkSubitems; + property Options: TTBItemOptions read GetOptions write SetOptions default []; + end; + + TTBCustomImageList = class(TImageList) + private + FCheckedImages: TCustomImageList; + FCheckedImagesChangeLink: TChangeLink; + FDisabledImages: TCustomImageList; + FDisabledImagesChangeLink: TChangeLink; + FHotImages: TCustomImageList; + FHotImagesChangeLink: TChangeLink; + FImagesBitmap: TBitmap; + FImagesBitmapMaskColor: TColor; + procedure ChangeImages(var AImageList: TCustomImageList; + Value: TCustomImageList; AChangeLink: TChangeLink); + procedure ImageListChanged(Sender: TObject); + procedure ImagesBitmapChanged(Sender: TObject); + procedure SetCheckedImages(Value: TCustomImageList); + procedure SetDisabledImages(Value: TCustomImageList); + procedure SetHotImages(Value: TCustomImageList); + procedure SetImagesBitmap(Value: TBitmap); + procedure SetImagesBitmapMaskColor(Value: TColor); + protected + procedure DefineProperties(Filer: TFiler); override; + procedure Notification(AComponent: TComponent; Operation: TOperation); override; + property CheckedImages: TCustomImageList read FCheckedImages write SetCheckedImages; + property DisabledImages: TCustomImageList read FDisabledImages write SetDisabledImages; + property HotImages: TCustomImageList read FHotImages write SetHotImages; + property ImagesBitmap: TBitmap read FImagesBitmap write SetImagesBitmap; + property ImagesBitmapMaskColor: TColor read FImagesBitmapMaskColor + write SetImagesBitmapMaskColor default clFuchsia; + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + procedure DrawState(Canvas: TCanvas; X, Y, Index: Integer; + Enabled, Selected, Checked: Boolean); virtual; + end; + + TTBImageList = class(TTBCustomImageList) + published + property CheckedImages; + property DisabledImages; + property HotImages; + property ImagesBitmap; + property ImagesBitmapMaskColor; + end; + +const + {$IFNDEF TB2K_USE_STRICT_O2K_MENU_STYLE} + tbMenuBkColor = clMenu; + tbMenuTextColor = clMenuText; + {$ELSE} + tbMenuBkColor = clBtnFace; + tbMenuTextColor = clBtnText; + {$ENDIF} + + tbMenuVerticalMargin = 4; + tbMenuImageTextSpace = 1; + tbMenuLeftTextMargin = 2; + tbMenuRightTextMargin = 3; + + tbMenuSeparatorOffset = 12; + + tbMenuScrollArrowHeight = 19; + + tbDropdownArrowWidth = 8; + tbDropdownArrowMargin = 3; + tbDropdownComboArrowWidth = 11; + tbDropdownComboMargin = 2; + + tbLineSpacing = 6; + tbLineSepOffset = 1; + tbDockedLineSepOffset = 4; + + WM_TB2K_CLICKITEM = WM_USER + $100; + +procedure TBInitToolbarSystemFont; + +var + ToolbarFont: TFont; + +type + TTBModalHandler = class + private + FCreatedWnd: Boolean; + FInited: Boolean; + FWnd: HWND; + FRootPopup: TTBPopupWindow; + procedure WndProc(var Msg: TMessage); + public + constructor Create(AExistingWnd: HWND); + destructor Destroy; override; + procedure Loop(const RootView: TTBView; const AMouseDown, AExecuteSelected, + AFromMSAA, TrackRightButton: Boolean); + property RootPopup: TTBPopupWindow read FRootPopup write FRootPopup; + property Wnd: HWND read FWnd; + end; + +function ProcessDoneAction(const DoneActionData: TTBDoneActionData; + const ReturnClickedItemOnly: Boolean): TTBCustomItem; + +implementation + +uses + MMSYSTEM, TB2Consts, TB2Common, IMM, TB2Acc; + +var + LastPos: TPoint; + +threadvar + ClickWndRefCount: Integer; + ClickWnd: HWND; + ClickList: TList; + +type + PItemChangedNotificationData = ^TItemChangedNotificationData; + TItemChangedNotificationData = record + Proc: TTBItemChangedProc; + RefCount: Integer; + end; + + TComponentAccess = class(TComponent); + TControlAccess = class(TControl); + +const + ViewTimerBaseID = 9000; + MaxGroupLevel = 10; + + +{ Misc. } + +procedure DestroyClickWnd; +begin + if ClickWnd <> 0 then begin + {$IFDEF JR_D6}Classes.{$ENDIF} DeallocateHWnd(ClickWnd); + ClickWnd := 0; + end; + FreeAndNil(ClickList); +end; + +procedure ReferenceClickWnd; +begin + Inc(ClickWndRefCount); +end; + +procedure ReleaseClickWnd; +begin + Dec(ClickWndRefCount); + if ClickWndRefCount = 0 then + DestroyClickWnd; +end; + +procedure QueueClick(const AItem: TObject; const AArg: Integer); +{ Adds an item to ClickList and posts a message to handle it. AItem must be + either a TTBCustomItem or TTBItemViewer. } +var + I: Integer; +begin + if ClickWnd = 0 then + ClickWnd := {$IFDEF JR_D6}Classes.{$ENDIF} AllocateHWnd(TTBCustomItem.ClickWndProc); + if ClickList = nil then + ClickList := TList.Create; + + { Add a new item to ClickList or replace an empty one } + I := ClickList.IndexOf(nil); + if I = -1 then + I := ClickList.Add(AItem) + else + ClickList[I] := AItem; + + PostMessage(ClickWnd, WM_TB2K_CLICKITEM, AArg, I); +end; + +procedure RemoveFromClickList(const AItem: TObject); +{ Any class that potentially calls QueueClick needs to call RemoveFromClickList + before an instance is destroyed to ensure that any references to the + instance still in ClickList are removed. } +var + I: Integer; +begin + if Assigned(ClickList) and Assigned(AItem) then + for I := 0 to ClickList.Count-1 do + if ClickList[I] = AItem then + ClickList[I] := Pointer(1); + { ^ The special value of Pointer(1) is assigned to the item instead of + of nil because we want the index to stay reserved until the + WM_TB2K_CLICKITEM message for the index is processed. We don't want + the WM_TB2K_CLICKITEM message that's still in the queue to later + refer to a different item; this would result in queued clicks being + processed in the wrong order in a case like this: + A.PostClick; B.PostClick; A.Free; C.PostClick; + C's click would end up being processed before A's, because C would + get A's index. } +end; + +function ProcessDoneAction(const DoneActionData: TTBDoneActionData; + const ReturnClickedItemOnly: Boolean): TTBCustomItem; +begin + Result := nil; + case DoneActionData.DoneAction of + tbdaNone: ; + tbdaClickItem: begin + if DoneActionData.Sound and NeedToPlaySound('MenuCommand') then + PlaySound('MenuCommand', 0, SND_ALIAS or SND_ASYNC or SND_NODEFAULT or SND_NOSTOP); + Result := DoneActionData.ClickItem; + if not ReturnClickedItemOnly then + Result.PostClick; + end; + tbdaOpenSystemMenu: begin + SendMessage(DoneActionData.Wnd, WM_SYSCOMMAND, SC_KEYMENU, DoneActionData.Key); + end; + tbdaHelpContext: begin + { Based on code in TPopupList.WndProc: } + if Assigned(Screen.ActiveForm) and + (biHelp in Screen.ActiveForm.BorderIcons) then + Application.HelpCommand(HELP_CONTEXTPOPUP, DoneActionData.ContextID) + else + Application.HelpContext(DoneActionData.ContextID); + end; + end; +end; + + +{ TTBItemDataArray routines } + +procedure InsertIntoItemArray(var AItems: PTBItemDataArray; + var AItemCount: Integer; NewIndex: Integer; AItem: TTBCustomItem); +begin + ReallocMem(AItems, (AItemCount+1) * SizeOf(AItems[0])); + if NewIndex < AItemCount then + System.Move(AItems[NewIndex], AItems[NewIndex+1], + (AItemCount-NewIndex) * SizeOf(AItems[0])); + AItems[NewIndex].Item := AItem; + Inc(AItemCount); +end; + +procedure DeleteFromItemArray(var AItems: PTBItemDataArray; + var AItemCount: Integer; Index: Integer); +begin + Dec(AItemCount); + if Index < AItemCount then + System.Move(AItems[Index+1], AItems[Index], + (AItemCount-Index) * SizeOf(AItems[0])); + ReallocMem(AItems, AItemCount * SizeOf(AItems[0])); +end; + +procedure InsertIntoViewerArray(var AItems: PTBItemViewerArray; + var AItemCount: Integer; NewIndex: Integer; AItem: TTBItemViewer); +begin + ReallocMem(AItems, (AItemCount+1) * SizeOf(AItems[0])); + if NewIndex < AItemCount then + System.Move(AItems[NewIndex], AItems[NewIndex+1], + (AItemCount-NewIndex) * SizeOf(AItems[0])); + AItems[NewIndex] := AItem; + Inc(AItemCount); +end; + +procedure DeleteFromViewerArray(var AItems: PTBItemViewerArray; + var AItemCount: Integer; Index: Integer); +begin + Dec(AItemCount); + if Index < AItemCount then + System.Move(AItems[Index+1], AItems[Index], + (AItemCount-Index) * SizeOf(AItems[0])); + ReallocMem(AItems, AItemCount * SizeOf(AItems[0])); +end; + + +{ TTBCustomItemActionLink } + +procedure TTBCustomItemActionLink.AssignClient(AClient: TObject); +begin + FClient := AClient as TTBCustomItem; +end; + +{$IFDEF JR_D6} +function TTBCustomItemActionLink.IsAutoCheckLinked: Boolean; +begin + Result := (FClient.AutoCheck = (Action as TCustomAction).AutoCheck); +end; +{$ENDIF} + +function TTBCustomItemActionLink.IsCaptionLinked: Boolean; +begin + Result := inherited IsCaptionLinked and + (FClient.Caption = (Action as TCustomAction).Caption); +end; + +function TTBCustomItemActionLink.IsCheckedLinked: Boolean; +begin + Result := inherited IsCheckedLinked and + (FClient.Checked = (Action as TCustomAction).Checked); +end; + +function TTBCustomItemActionLink.IsEnabledLinked: Boolean; +begin + Result := inherited IsEnabledLinked and + (FClient.Enabled = (Action as TCustomAction).Enabled); +end; + +function TTBCustomItemActionLink.IsHelpContextLinked: Boolean; +begin + Result := inherited IsHelpContextLinked and + (FClient.HelpContext = (Action as TCustomAction).HelpContext); +end; + +function TTBCustomItemActionLink.IsHintLinked: Boolean; +begin + Result := inherited IsHintLinked and + (FClient.Hint = (Action as TCustomAction).Hint); +end; + +function TTBCustomItemActionLink.IsImageIndexLinked: Boolean; +begin + Result := inherited IsImageIndexLinked and + (FClient.ImageIndex = (Action as TCustomAction).ImageIndex); +end; + +function TTBCustomItemActionLink.IsShortCutLinked: Boolean; +begin + Result := inherited IsShortCutLinked and + (FClient.ShortCut = (Action as TCustomAction).ShortCut); +end; + +function TTBCustomItemActionLink.IsVisibleLinked: Boolean; +begin + Result := inherited IsVisibleLinked and + (FClient.Visible = (Action as TCustomAction).Visible); +end; + +function TTBCustomItemActionLink.IsOnExecuteLinked: Boolean; +begin + Result := inherited IsOnExecuteLinked and + MethodsEqual(TMethod(FClient.OnClick), TMethod(Action.OnExecute)); +end; + +{$IFDEF JR_D6} +procedure TTBCustomItemActionLink.SetAutoCheck(Value: Boolean); +begin + if IsAutoCheckLinked then FClient.AutoCheck := Value; +end; +{$ENDIF} + +procedure TTBCustomItemActionLink.SetCaption(const Value: string); +begin + if IsCaptionLinked then FClient.Caption := Value; +end; + +procedure TTBCustomItemActionLink.SetChecked(Value: Boolean); +begin + if IsCheckedLinked then FClient.Checked := Value; +end; + +procedure TTBCustomItemActionLink.SetEnabled(Value: Boolean); +begin + if IsEnabledLinked then FClient.Enabled := Value; +end; + +procedure TTBCustomItemActionLink.SetHelpContext(Value: THelpContext); +begin + if IsHelpContextLinked then FClient.HelpContext := Value; +end; + +procedure TTBCustomItemActionLink.SetHint(const Value: string); +begin + if IsHintLinked then FClient.Hint := Value; +end; + +procedure TTBCustomItemActionLink.SetImageIndex(Value: Integer); +begin + if IsImageIndexLinked then FClient.ImageIndex := Value; +end; + +procedure TTBCustomItemActionLink.SetShortCut(Value: TShortCut); +begin + if IsShortCutLinked then FClient.ShortCut := Value; +end; + +procedure TTBCustomItemActionLink.SetVisible(Value: Boolean); +begin + if IsVisibleLinked then FClient.Visible := Value; +end; + +procedure TTBCustomItemActionLink.SetOnExecute(Value: TNotifyEvent); +begin + if IsOnExecuteLinked then FClient.OnClick := Value; +end; + + +{ TTBCustomItem } + +{}function ItemContainingItems(const AItem: TTBCustomItem): TTBCustomItem; +begin + if Assigned(AItem) and Assigned(AItem.FLinkSubitems) then + Result := AItem.FLinkSubitems + else + Result := AItem; +end; + +constructor TTBCustomItem.Create(AOwner: TComponent); +begin + inherited; + FEnabled := True; + FImageIndex := -1; + FInheritOptions := True; + FItemStyle := [tbisSelectable, tbisRedrawOnSelChange, tbisRedrawOnMouseOverChange]; + FVisible := True; + ReferenceClickWnd; +end; + +destructor TTBCustomItem.Destroy; +var + I: Integer; +begin + Destroying; + RemoveFromClickList(Self); + { Changed in 0.33. Moved FParent.Remove call *after* the child items are + deleted. } + for I := Count-1 downto 0 do + Items[I].Free; + if Assigned(FParent) then + FParent.Remove(Self); + FreeMem(FItems); + FActionLink.Free; + FActionLink := nil; + FreeAndNil(FSubMenuImagesChangeLink); + FreeAndNil(FImagesChangeLink); + inherited; + if Assigned(FNotifyList) then begin + for I := FNotifyList.Count-1 downto 0 do + Dispose(PItemChangedNotificationData(FNotifyList[I])); + FNotifyList.Free; + end; + FLinkParents.Free; + ReleaseClickWnd; +end; + +{$IFDEF JR_D6} +function TTBCustomItem.IsAutoCheckStored: Boolean; +begin + Result := (ActionLink = nil) or not FActionLink.IsAutoCheckLinked; +end; +{$ENDIF} + +function TTBCustomItem.IsCaptionStored: Boolean; +begin + Result := (ActionLink = nil) or not FActionLink.IsCaptionLinked; +end; + +function TTBCustomItem.IsCheckedStored: Boolean; +begin + Result := (ActionLink = nil) or not FActionLink.IsCheckedLinked; +end; + +function TTBCustomItem.IsEnabledStored: Boolean; +begin + Result := (ActionLink = nil) or not FActionLink.IsEnabledLinked; +end; + +function TTBCustomItem.IsHintStored: Boolean; +begin + Result := (ActionLink = nil) or not FActionLink.IsHintLinked; +end; + +function TTBCustomItem.IsHelpContextStored: Boolean; +begin + Result := (ActionLink = nil) or not FActionLink.IsHelpContextLinked; +end; + +function TTBCustomItem.IsImageIndexStored: Boolean; +begin + Result := (ActionLink = nil) or not FActionLink.IsImageIndexLinked; +end; + +function TTBCustomItem.IsShortCutStored: Boolean; +begin + Result := (ActionLink = nil) or not FActionLink.IsShortCutLinked; +end; + +function TTBCustomItem.IsVisibleStored: Boolean; +begin + Result := (ActionLink = nil) or not FActionLink.IsVisibleLinked; +end; + +function TTBCustomItem.IsOnClickStored: Boolean; +begin + Result := (ActionLink = nil) or not FActionLink.IsOnExecuteLinked; +end; + +function TTBCustomItem.GetAction: TBasicAction; +begin + if FActionLink <> nil then + Result := FActionLink.Action + else + Result := nil; +end; + +function TTBCustomItem.GetActionLinkClass: TTBCustomItemActionLinkClass; +begin + Result := TTBCustomItemActionLink; +end; + +procedure TTBCustomItem.DoActionChange(Sender: TObject); +begin + if Sender = Action then ActionChange(Sender, False); +end; + +procedure TTBCustomItem.ActionChange(Sender: TObject; CheckDefaults: Boolean); +begin + if Action is TCustomAction then + with TCustomAction(Sender) do + begin + {$IFDEF JR_D6} + if not CheckDefaults or (Self.AutoCheck = False) then + Self.AutoCheck := AutoCheck; + {$ENDIF} + if not CheckDefaults or (Self.Caption = '') then + Self.Caption := Caption; + if not CheckDefaults or (Self.Checked = False) then + Self.Checked := Checked; + if not CheckDefaults or (Self.Enabled = True) then + Self.Enabled := Enabled; + if not CheckDefaults or (Self.HelpContext = 0) then + Self.HelpContext := HelpContext; + if not CheckDefaults or (Self.Hint = '') then + Self.Hint := Hint; + if not CheckDefaults or (Self.ImageIndex = -1) then + Self.ImageIndex := ImageIndex; + if not CheckDefaults or (Self.ShortCut = scNone) then + Self.ShortCut := ShortCut; + if not CheckDefaults or (Self.Visible = True) then + Self.Visible := Visible; + if not CheckDefaults or not Assigned(Self.OnClick) then + Self.OnClick := OnExecute; + end; +end; + +procedure TTBCustomItem.SetAction(Value: TBasicAction); +begin + if Value = nil then begin + FActionLink.Free; + FActionLink := nil; + end + else begin + if FActionLink = nil then + FActionLink := GetActionLinkClass.Create(Self); + FActionLink.Action := Value; + FActionLink.OnChange := DoActionChange; + { Note: Delphi's Controls.pas and Menus.pas merely check for + "csLoading in Value.ComponentState" here. But that doesn't help when + the Action property references an action on another form / data module + that has already finished loading. So we check two things: + 1. csLoading in Value.ComponentState + 2. csLoading in ComponentState + In the typical case where the item and action list reside on the same + form, #1 and #2 are both true. + Only #1 is true when Action references an action on another form / data + module that is created *after* the item (e.g. if Form1.TBItem1.Action = + Form2.Action1, and Form1 is created before Form2). + Only #2 is true when Action references an action on another form / data + module that is created *before* the item (e.g. if Form2.TBItem1.Action = + Form1.Action1, and Form1 is created before Form2). } + ActionChange(Value, (csLoading in Value.ComponentState) or + (csLoading in ComponentState)); + Value.FreeNotification(Self); + end; +end; + +procedure TTBCustomItem.InitiateAction; +begin + if FActionLink <> nil then FActionLink.Update; +end; + +procedure TTBCustomItem.Loaded; +begin + inherited; + if Action <> nil then ActionChange(Action, True); +end; + +procedure TTBCustomItem.GetChildren(Proc: TGetChildProc; Root: TComponent); +var + I: Integer; +begin + for I := 0 to FItemCount-1 do + Proc(FItems[I].Item); +end; + +procedure TTBCustomItem.SetChildOrder(Child: TComponent; Order: Integer); +var + I: Integer; +begin + I := IndexOf(Child as TTBCustomItem); + if I <> -1 then + Move(I, Order); +end; + +function TTBCustomItem.HasParent: Boolean; +begin + Result := True; +end; + +function TTBCustomItem.GetParentComponent: TComponent; +begin + if (FParent <> nil) and (FParent.FParentComponent <> nil) then + Result := FParent.FParentComponent + else + Result := FParent; +end; + +procedure TTBCustomItem.SetName(const NewName: TComponentName); +begin + if Name <> NewName then begin + inherited; + if Assigned(FParent) then + FParent.Notify(tbicNameChanged, -1, Self); + end; +end; + +procedure TTBCustomItem.SetParentComponent(Value: TComponent); +var + Intf: ITBItems; +begin + if FParent <> nil then FParent.Remove(Self); + if Value <> nil then begin + if Value is TTBCustomItem then + TTBCustomItem(Value).Add(Self) + else if Value.GetInterface(ITBItems, Intf) then + Intf.GetItems.Add(Self); + end; +end; + +procedure TTBCustomItem.Notification(AComponent: TComponent; + Operation: TOperation); +begin + inherited; + if Operation = opRemove then begin + RemoveFromList(FLinkParents, AComponent); + if AComponent = Action then Action := nil; + if AComponent = Images then Images := nil; + if AComponent = SubMenuImages then SubMenuImages := nil; + if AComponent = LinkSubitems then LinkSubitems := nil; + end; +end; + +procedure TTBCustomItem.IndexError; +begin + raise ETBItemError.Create(STBToolbarIndexOutOfBounds); +end; + +class procedure TTBCustomItem.ClickWndProc(var Message: TMessage); +var + List: TList; + I: Integer; + Item: TObject; +begin + if Message.Msg = WM_TB2K_CLICKITEM then begin + List := ClickList; { optimization... } + if Assigned(List) then begin + I := Message.LParam; + if (I >= 0) and (I < List.Count) then begin + Item := List[I]; + List[I] := nil; + if Item = Pointer(1) then { is it a destroyed item? } + Item := nil; + end + else + Item := nil; + + { Remove trailing nil items from ClickList. This is not *necessary*, but + it will make RemoveFromClickList faster if we clean out items that + aren't used, and may never be used again. } + for I := List.Count-1 downto 0 do begin + if List[I] = nil then + List.Delete(I) + else + Break; + end; + + if Assigned(Item) then begin + try + if Item is TTBCustomItem then + TTBCustomItem(Item).Click + else if Item is TTBItemViewer then + TTBItemViewer(Item).AccSelect(Message.WParam <> 0); + except + Application.HandleException(Item); + end; + end; + end; + end + else + with Message do + Result := DefWindowProc(ClickWnd, Msg, wParam, lParam); +end; + +procedure TTBCustomItem.PostClick; +{ Posts a message to the message queue that causes the item's Click handler to + be executed when control is returned to the message loop. + This should be called instead of Click when a WM_SYSCOMMAND message is + (possibly) currently being handled, because TApplication.WndProc's + CM_APPSYSCOMMAND handler disables the VCL's processing of focus messages + until the Perform(WM_SYSCOMMAND, ...) call returns. (An OnClick handler which + calls TForm.ShowModal needs focus messages to be enabled or else the form + will be shown with no initial focus.) } +begin + QueueClick(Self, 0); +end; + +procedure TTBCustomItem.Click; +begin + if Enabled then begin + { Following code based on D6's TMenuItem.Click } + {$IFDEF JR_D6} + if (not Assigned(ActionLink) and AutoCheck) or + (Assigned(ActionLink) and not ActionLink.IsAutoCheckLinked and AutoCheck) then + {$ELSE} + if AutoCheck then + {$ENDIF} + Checked := not Checked; + { Following code based on D4's TControl.Click } + { Call OnClick if assigned and not equal to associated action's OnExecute. + If associated action's OnExecute assigned then call it, otherwise, call + OnClick. } + if Assigned(FOnClick) and (Action <> nil) and + not MethodsEqual(TMethod(FOnClick), TMethod(Action.OnExecute)) then + FOnClick(Self) + else + if not(csDesigning in ComponentState) and (ActionLink <> nil) then + ActionLink.Execute {$IFDEF JR_D6}(Self){$ENDIF} + else + if Assigned(FOnClick) then + FOnClick(Self); + end; +end; + +function TTBCustomItem.GetItem(Index: Integer): TTBCustomItem; +begin + if (Index < 0) or (Index >= FItemCount) then IndexError; + Result := FItems[Index].Item; +end; + +procedure TTBCustomItem.Add(AItem: TTBCustomItem); +begin + Insert(Count, AItem); +end; + +procedure TTBCustomItem.InternalNotify(Ancestor: TTBCustomItem; + NestingLevel: Integer; Action: TTBItemChangedAction; Index: Integer; + Item: TTBCustomItem); +{ Note: Ancestor is Item's parent, or in the case of a group item relayed + notification, it can also be a group item which *links* to Item's parent + (i.e. ItemContainingItems(Ancestor) = Item.Parent). } + + procedure RelayToParentOf(const AItem: TTBCustomItem); + begin + if NestingLevel > MaxGroupLevel then + Exit; + if (tbisEmbeddedGroup in AItem.ItemStyle) and Assigned(AItem.Parent) then begin + if Ancestor = Self then + AItem.Parent.InternalNotify(AItem, NestingLevel + 1, Action, Index, Item) + else + { Don't alter Ancestor on subsequent relays; only on the first. } + AItem.Parent.InternalNotify(Ancestor, NestingLevel + 1, Action, Index, Item); + end; + end; + +var + I: Integer; + P: TTBCustomItem; + SaveProc: TTBItemChangedProc; +begin + { If Self is a group item, relay the notification to the parent } + RelayToParentOf(Self); + { If any group items are linked to Self, relay the notification to + those items' parents } + if Assigned(FLinkParents) then + for I := 0 to FLinkParents.Count-1 do begin + P := FLinkParents[I]; + if P <> Parent then + RelayToParentOf(P); + end; + if Assigned(FNotifyList) then begin + I := 0; + while I < FNotifyList.Count do begin + with PItemChangedNotificationData(FNotifyList[I])^ do begin + SaveProc := Proc; + Proc(Ancestor, Ancestor <> Self, Action, Index, Item); + end; + { Is I now out of bounds? } + if I >= FNotifyList.Count then + Break; + { Only proceed to the next index if the list didn't change } + if MethodsEqual(TMethod(PItemChangedNotificationData(FNotifyList[I])^.Proc), + TMethod(SaveProc)) then + Inc(I); + end; + end; +end; + +procedure TTBCustomItem.Notify(Action: TTBItemChangedAction; Index: Integer; + Item: TTBCustomItem); +begin + InternalNotify(Self, 0, Action, Index, Item); +end; + +procedure TTBCustomItem.ViewBeginUpdate; +begin + Notify(tbicSubitemsBeginUpdate, -1, nil); +end; + +procedure TTBCustomItem.ViewEndUpdate; +begin + Notify(tbicSubitemsEndUpdate, -1, nil); +end; + +procedure TTBCustomItem.Insert(NewIndex: Integer; AItem: TTBCustomItem); +begin + if Assigned(AItem.FParent) then + raise ETBItemError.Create(STBToolbarItemReinserted); + if (NewIndex < 0) or (NewIndex > FItemCount) then IndexError; + InsertIntoItemArray(FItems, FItemCount, NewIndex, AItem); + AItem.FParent := Self; + ViewBeginUpdate; + try + Notify(tbicInserted, NewIndex, AItem); + AItem.RefreshOptions; + finally + ViewEndUpdate; + end; +end; + +procedure TTBCustomItem.Delete(Index: Integer); +begin + if (Index < 0) or (Index >= FItemCount) then IndexError; + Notify(tbicDeleting, Index, FItems[Index].Item); + FItems[Index].Item.FParent := nil; + DeleteFromItemArray(FItems, FItemCount, Index); +end; + +function TTBCustomItem.IndexOf(AItem: TTBCustomItem): Integer; +var + I: Integer; +begin + for I := 0 to FItemCount-1 do + if FItems[I].Item = AItem then begin + Result := I; + Exit; + end; + Result := -1; +end; + +procedure TTBCustomItem.Remove(Item: TTBCustomItem); +var + I: Integer; +begin + I := IndexOf(Item); + //if I = -1 then raise ETBItemError.Create(STBToolbarItemNotFound); + if I <> -1 then + Delete(I); +end; + +procedure TTBCustomItem.Clear; +var + I: Integer; +begin + for I := Count-1 downto 0 do + Items[I].Free; +end; + +procedure TTBCustomItem.Move(CurIndex, NewIndex: Integer); +var + Item: TTBCustomItem; +begin + if CurIndex <> NewIndex then begin + if (NewIndex < 0) or (NewIndex >= FItemCount) then IndexError; + Item := Items[CurIndex]; + ViewBeginUpdate; + try + Delete(CurIndex); + Insert(NewIndex, Item); + finally + ViewEndUpdate; + end; + end; +end; + +function TTBCustomItem.ContainsItem(AItem: TTBCustomItem): Boolean; +begin + while Assigned(AItem) and (AItem <> Self) do + AItem := AItem.Parent; + Result := Assigned(AItem); +end; + +procedure TTBCustomItem.RegisterNotification(ANotify: TTBItemChangedProc); +var + I: Integer; + Data: PItemChangedNotificationData; +begin + if FNotifyList = nil then FNotifyList := TList.Create; + for I := 0 to FNotifyList.Count-1 do + with PItemChangedNotificationData(FNotifyList[I])^ do + if MethodsEqual(TMethod(ANotify), TMethod(Proc)) then begin + Inc(RefCount); + Exit; + end; + FNotifyList.Expand; + New(Data); + Data.Proc := ANotify; + Data.RefCount := 1; + FNotifyList.Add(Data); +end; + +procedure TTBCustomItem.UnregisterNotification(ANotify: TTBItemChangedProc); +var + I: Integer; + Data: PItemChangedNotificationData; +begin + if Assigned(FNotifyList) then + for I := 0 to FNotifyList.Count-1 do begin + Data := FNotifyList[I]; + if MethodsEqual(TMethod(Data.Proc), TMethod(ANotify)) then begin + Dec(Data.RefCount); + if Data.RefCount = 0 then begin + FNotifyList.Delete(I); + Dispose(Data); + if FNotifyList.Count = 0 then begin + FNotifyList.Free; + FNotifyList := nil; + end; + end; + Break; + end; + end; +end; + +function TTBCustomItem.GetPopupWindowClass: TTBPopupWindowClass; +begin + Result := TTBPopupWindow; +end; + +procedure TTBCustomItem.DoPopup(Sender: TTBCustomItem; FromLink: Boolean); +begin + if Assigned(FOnPopup) then + FOnPopup(Sender, FromLink); + if not(tbisCombo in ItemStyle) then + Click; +end; + +var + PlayedSound: Boolean = False; + +procedure TTBCustomItem.GetPopupPosition(ParentView: TTBView; + PopupWindow: TTBPopupWindow; var PopupPositionRec: TTBPopupPositionRec); +var + X2, Y2: Integer; + RepeatCalcX: Boolean; + + function CountObscured(X, Y, W, H: Integer): Integer; + var + I: Integer; + P: TPoint; + V: TTBItemViewer; + begin + Result := 0; + if ParentView = nil then + Exit; + P := ParentView.FWindow.ClientToScreen(Point(0, 0)); + Dec(X, P.X); + Dec(Y, P.Y); + Inc(W, X); + Inc(H, Y); + for I := 0 to ParentView.FViewerCount-1 do begin + V := ParentView.FViewers[I]; + if V.Show and (V.BoundsRect.Left >= X) and (V.BoundsRect.Right <= W) and + (V.BoundsRect.Top >= Y) and (V.BoundsRect.Bottom <= H) then + Inc(Result); + end; + end; + +begin + with PopupPositionRec do + begin + { Adjust the Y position of the popup window } + { If the window is going off the bottom of the monitor, try placing it + above the parent item } + if (Y + H > MonitorRect.Bottom) and + ((ParentView = nil) or (ParentView.FOrientation <> tbvoVertical)) then begin + if not PositionAsSubmenu then + Y2 := ParentItemRect.Top + else + Y2 := ParentItemRect.Bottom + NCSizeY; + Dec(Y2, H); + { Only place it above the parent item if it isn't going to go off the + top of the monitor } + if Y2 >= MonitorRect.Top then + Y := Y2; + end; + { If it's still going off the bottom (which can be possible if a menu bar + was off the screen to begin with), clip it to the bottom of the monitor } + if Y + H > MonitorRect.Bottom then + Y := MonitorRect.Bottom - H; + if Y < MonitorRect.Top then + Y := MonitorRect.Top; + + { Other adjustments to the position of the popup window } + if not PositionAsSubmenu then begin + if (ParentView = nil) and (Alignment = tbpaRight) and (X < MonitorRect.Left) then + Inc(X, W); + if X + W > MonitorRect.Right then begin + if Assigned(ParentView) or (Alignment <> tbpaLeft) then + X := MonitorRect.Right; + Dec(X, W); + end; + if X < MonitorRect.Left then + X := MonitorRect.Left; + if (ParentView = nil) or (ParentView.FOrientation <> tbvoVertical) then begin + Y2 := ParentItemRect.Top - H; + if Y2 >= MonitorRect.Top then begin + { Would the popup window obscure less items if it popped out to the + top instead? } + if (CountObscured(X, Y2, W, H) < CountObscured(X, Y, W, H)) or + ((Y < ParentItemRect.Bottom) and (Y + H > ParentItemRect.Top) and + (X < ParentItemRect.Right) and (X + W > ParentItemRect.Left)) then + Y := Y2; + end; + { Make sure a tall popup window doesn't overlap the parent item } + if (Y < ParentItemRect.Bottom) and (Y + H > ParentItemRect.Top) and + (X < ParentItemRect.Right) and (X + W > ParentItemRect.Left) then begin + if ParentItemRect.Right + W <= MonitorRect.Right then + X := ParentItemRect.Right + else + X := ParentItemRect.Left - W; + if X < MonitorRect.Top then + X := MonitorRect.Top; + end; + end + else begin + X2 := ParentItemRect.Right; + if X2 + W <= MonitorRect.Right then begin + { Would the popup window obscure less items if it popped out to the + right instead? } + if (CountObscured(X2, Y, W, H) < CountObscured(X, Y, W, H)) or + ((Y < ParentItemRect.Bottom) and (Y + H > ParentItemRect.Top) and + (X < ParentItemRect.Right) and (X + W > ParentItemRect.Left)) then + X := X2; + end; + { Make sure a wide popup window doesn't overlap the parent item } + if (Y < ParentItemRect.Bottom) and (Y + H > ParentItemRect.Top) and + (X < ParentItemRect.Right) and (X + W > ParentItemRect.Left) then begin + if ParentItemRect.Bottom + H <= MonitorRect.Bottom then + Y := ParentItemRect.Bottom + else + Y := ParentItemRect.Top - H; + if Y < MonitorRect.Top then + Y := MonitorRect.Top; + end; + end; + end + else begin + { Make nested submenus go from left to right on the screen. Each it + runs out of space on the screen, switch directions } + repeat + RepeatCalcX := False; + X2 := X; + if Opposite or (X2 + W > MonitorRect.Right) then begin + if Assigned(ParentView) then + X2 := ParentItemRect.Left + NCSizeX; + Dec(X2, W); + if not Opposite then + Include(PopupWindow.View.FState, vsOppositePopup) + else begin + if X2 < MonitorRect.Left then begin + Opposite := False; + RepeatCalcX := True; + end + else + Include(PopupWindow.View.FState, vsOppositePopup); + end; + end; + until not RepeatCalcX; + X := X2; + if X < MonitorRect.Left then + X := MonitorRect.Left; + end; + + { Determine animation direction } + AnimDir := []; + if not PositionAsSubmenu then begin + if Y >= ParentItemRect.Bottom then + Include(AnimDir, tbadDown) + else if Y + H <= ParentItemRect.Top then + Include(AnimDir, tbadUp); + if X >= ParentItemRect.Right then + Include(AnimDir, tbadRight) + else if X + W <= ParentItemRect.Left then + Include(AnimDir, tbadLeft); + end + else begin + if X + W div 2 >= ParentItemRect.Left + (ParentItemRect.Right - ParentItemRect.Left) div 2 then + Include(AnimDir, tbadRight) + else + Include(AnimDir, tbadLeft); + end; + end; +end; + +function TTBCustomItem.CreatePopup(const ParentView: TTBView; + const ParentViewer: TTBItemViewer; const PositionAsSubmenu, SelectFirstItem, + Customizing: Boolean; const APopupPoint: TPoint; + const Alignment: TTBPopupAlignment): TTBPopupWindow; +var + EventItem, ParentItem: TTBCustomItem; + Opposite: Boolean; + ChevronParentView: TTBView; + X, Y, W, H: Integer; + P: TPoint; + ParentItemRect: TRect; + MonitorRect: TRect; + PopupRec: TTBPopupPositionRec; + NCSize: TPoint; +begin + EventItem := ItemContainingItems(Self); + if EventItem <> Self then + EventItem.DoPopup(Self, True); + DoPopup(Self, False); + + ChevronParentView := GetChevronParentView; + if ChevronParentView = nil then + ParentItem := Self + else + ParentItem := ChevronParentView.FParentItem; + + Opposite := Assigned(ParentView) and (vsOppositePopup in ParentView.FState); + Result := GetPopupWindowClass.CreatePopupWindow(nil, ParentView, ParentItem, + Customizing); + try + if Assigned(ChevronParentView) then begin + ChevronParentView.FreeNotification(Result.View); + Result.View.FChevronParentView := ChevronParentView; + Result.View.FIsToolbar := True; + Result.View.Style := Result.View.Style + + (ChevronParentView.Style * [vsAlwaysShowHints]); + Result.Color := clBtnFace; + end; + + { Calculate ParentItemRect, and MonitorRect (the rectangle of the monitor + that the popup window will be confined to) } + if Assigned(ParentView) then begin + ParentView.ValidatePositions; + ParentItemRect := ParentViewer.BoundsRect; + P := ParentView.FWindow.ClientToScreen(Point(0, 0)); + OffsetRect(ParentItemRect, P.X, P.Y); + if not IsRectEmpty(ParentView.FMonitorRect) then + MonitorRect := ParentView.FMonitorRect + else + {MonitorRect := GetRectOfMonitorContainingPoint(APopupPoint, False);} {vb-} + MonitorRect := GetRectOfMonitorContainingPoint(APopupPoint, True); {vb+} + end + else begin + ParentItemRect.TopLeft := APopupPoint; + ParentItemRect.BottomRight := APopupPoint; + {MonitorRect := GetRectOfMonitorContainingPoint(APopupPoint, False);} {vb-} + MonitorRect := GetRectOfMonitorContainingPoint(APopupPoint, True); {vb+} + end; + Result.View.FMonitorRect := MonitorRect; + + { Initialize item positions and size of the popup window } + NCSize := Result.GetNCSize; + if ChevronParentView = nil then + Result.View.FMaxHeight := (MonitorRect.Bottom - MonitorRect.Top) - + (NCSize.Y * 2) + else + Result.View.WrapOffset := (MonitorRect.Right - MonitorRect.Left) - + (NCSize.X * 2); + if SelectFirstItem then + Result.View.Selected := Result.View.FirstSelectable; + Result.View.UpdatePositions; + W := Result.Width; + H := Result.Height; + + { Calculate initial X,Y position of the popup window } + if Assigned(ParentView) then begin + if not PositionAsSubmenu then begin + if ChevronParentView = nil then begin + if (ParentView = nil) or (ParentView.FOrientation <> tbvoVertical) then begin + if GetSystemMetrics(SM_MENUDROPALIGNMENT) = 0 then + X := ParentItemRect.Left + else + X := ParentItemRect.Right - W; + Y := ParentItemRect.Bottom; + end + else begin + X := ParentItemRect.Left - W; + Y := ParentItemRect.Top; + end; + end + else begin + if ChevronParentView.FOrientation <> tbvoVertical then begin + X := ParentItemRect.Right - W; + Y := ParentItemRect.Bottom; + end + else begin + X := ParentItemRect.Left - W; + Y := ParentItemRect.Top; + end; + end; + end + else begin + X := ParentItemRect.Right - NCSize.X; + Y := ParentItemRect.Top - NCSize.Y; + end; + end + else begin + X := APopupPoint.X; + Y := APopupPoint.Y; + case Alignment of + tbpaRight: Dec(X, W); + tbpaCenter: Dec(X, W div 2); + end; + end; + + PopupRec.PositionAsSubmenu := PositionAsSubmenu; + PopupRec.Alignment := Alignment; + PopupRec.Opposite := Opposite; + PopupRec.MonitorRect := MonitorRect; + PopupRec.ParentItemRect := ParentItemRect; + PopupRec.NCSizeX := NCSize.X; + PopupRec.NCSizeY := NCSize.Y; + PopupRec.X := X; + PopupRec.Y := Y; + PopupRec.W := W; + PopupRec.H := H; + PopupRec.AnimDir := []; + PopupRec.PlaySound := True; + GetPopupPosition(ParentView, Result, PopupRec); + X := PopupRec.X; + Y := PopupRec.Y; + W := PopupRec.W; + H := PopupRec.H; + Result.FAnimationDirection := PopupRec.AnimDir; + Result.SetBounds(X, Y, W, H); + if Assigned(ParentView) then begin + Result.FreeNotification(ParentView); + ParentView.FOpenViewerWindow := Result; + ParentView.FOpenViewerView := Result.View; + ParentView.FOpenViewer := ParentViewer; + if ParentView.FIsToolbar then begin + Include(ParentView.FState, vsDropDownMenus); + ParentView.Invalidate(ParentViewer); + ParentView.FWindow.Update; + end; + end; + Include(Result.View.FState, vsDrawInOrder); + if not PopupRec.PlaySound or not NeedToPlaySound('MenuPopup') then begin + { Don't call PlaySound if we don't have to } + Result.Visible := True; + end + else begin + if not PlayedSound then begin + { Work around Windows 2000 "bug" where there's a 1/3 second delay upon the + first call to PlaySound (or sndPlaySound) by painting the window + completely first. This way the delay isn't very noticable. } + PlayedSound := True; + Result.Visible := True; + Result.Update; + PlaySound('MenuPopup', 0, SND_ALIAS or SND_ASYNC or SND_NODEFAULT or SND_NOSTOP); + end + else begin + PlaySound('MenuPopup', 0, SND_ALIAS or SND_ASYNC or SND_NODEFAULT or SND_NOSTOP); + Result.Visible := True; + end; + end; + CallNotifyWinEvent(EVENT_SYSTEM_MENUPOPUPSTART, Result.View.FWindow.Handle, + OBJID_CLIENT, CHILDID_SELF); + { Call NotifyFocusEvent now that the window is visible } + if Assigned(Result.View.Selected) then + Result.View.NotifyFocusEvent; + except + Result.Free; + raise; + end; +end; + +function TTBCustomItem.OpenPopup(const SelectFirstItem, TrackRightButton: Boolean; + const PopupPoint: TPoint; const Alignment: TTBPopupAlignment; + const ReturnClickedItemOnly: Boolean): TTBCustomItem; +var + ModalHandler: TTBModalHandler; + Popup: TTBPopupWindow; + DoneActionData: TTBDoneActionData; +begin + ModalHandler := TTBModalHandler.Create(0); + try + Popup := CreatePopup(nil, nil, False, SelectFirstItem, False, PopupPoint, + Alignment); + try + Include(Popup.View.FState, vsIgnoreFirstMouseUp); + ModalHandler.RootPopup := Popup; + ModalHandler.Loop(Popup.View, False, False, False, TrackRightButton); + DoneActionData := Popup.View.FDoneActionData; + finally + ModalHandler.RootPopup := nil; + { Remove vsModal state from the root view before any TTBView.Destroy + methods get called, so that NotifyFocusEvent becomes a no-op } + Exclude(Popup.View.FState, vsModal); + Popup.Free; + end; + finally + ModalHandler.Free; + end; + Result := ProcessDoneAction(DoneActionData, ReturnClickedItemOnly); +end; + +function TTBCustomItem.Popup(X, Y: Integer; TrackRightButton: Boolean; + Alignment: TTBPopupAlignment = tbpaLeft; + ReturnClickedItemOnly: Boolean = False): TTBCustomItem; +var + P: TPoint; +begin + P.X := X; + P.Y := Y; + Result := OpenPopup(False, TrackRightButton, P, Alignment, + ReturnClickedItemOnly); +end; + +function TTBCustomItem.FindItemWithShortCut(AShortCut: TShortCut; + var ATopmostParent: TTBCustomItem): TTBCustomItem; + + function DoItem(AParentItem: TTBCustomItem; LinkDepth: Integer): TTBCustomItem; + var + I: Integer; + NewParentItem, Item: TTBCustomItem; + begin + Result := nil; + NewParentItem := AParentItem; + if Assigned(NewParentItem.LinkSubitems) then begin + NewParentItem := NewParentItem.LinkSubitems; + Inc(LinkDepth); + if LinkDepth > 25 then + Exit; { prevent infinite link recursion } + end; + for I := 0 to NewParentItem.Count-1 do begin + Item := NewParentItem.Items[I]; + if Item.ShortCut = AShortCut then begin + Result := Item; + Exit; + end; + Result := DoItem(Item, LinkDepth); + if Assigned(Result) then begin + ATopmostParent := Item; + Exit; + end; + end; + end; + +begin + ATopmostParent := nil; + Result := DoItem(Self, 0); +end; + +function TTBCustomItem.IsShortCut(var Message: TWMKey): Boolean; +var + ShortCut: TShortCut; + ShiftState: TShiftState; + ShortCutItem, TopmostItem, Item, EventItem: TTBCustomItem; + I: Integer; +label 1; +begin + Result := False; + ShiftState := KeyDataToShiftState(Message.KeyData); + ShortCut := Menus.ShortCut(Message.CharCode, ShiftState); +1:ShortCutItem := FindItemWithShortCut(ShortCut, TopmostItem); + if Assigned(ShortCutItem) then begin + { Send OnPopup/OnClick events to ShortCutItem's parents so that they can + update the Enabled state of ShortCutItem if needed } + Item := Self; + repeat + if not Item.Enabled then + Exit; + EventItem := ItemContainingItems(Item); + if not(csDesigning in ComponentState) then begin + for I := 0 to EventItem.Count-1 do + EventItem.Items[I].InitiateAction; + end; + if not(tbisEmbeddedGroup in Item.ItemStyle) then begin + if EventItem <> Item then begin + try + EventItem.DoPopup(Item, True); + except + Application.HandleException(Self); + end; + end; + try + Item.DoPopup(Item, False); + except + Application.HandleException(Self); + end; + end; + ShortCutItem := Item.FindItemWithShortCut(ShortCut, TopmostItem); + if ShortCutItem = nil then + { Can no longer find the shortcut inside TopmostItem. Start over + because the shortcut might have moved. } + goto 1; + Item := TopmostItem; + until Item = nil; + if ShortCutItem.Enabled then begin + try + ShortCutItem.Click; + except + Application.HandleException(Self); + end; + Result := True; + end; + end; +end; + +function TTBCustomItem.GetChevronParentView: TTBView; +begin + Result := nil; +end; + +function TTBCustomItem.GetItemViewerClass(AView: TTBView): TTBItemViewerClass; +begin + Result := TTBItemViewer; +end; + +function TTBCustomItem.NeedToRecreateViewer(AViewer: TTBItemViewer): Boolean; +begin + Result := False; +end; + +function TTBCustomItem.GetShortCutText: String; +var + P: Integer; +begin + P := Pos(#9, Caption); + if P = 0 then begin + if ShortCut <> 0 then + Result := ShortCutToText(ShortCut) + else + Result := ''; + end + else + Result := Copy(Caption, P+1, Maxint); +end; + +procedure TTBCustomItem.Change(NeedResize: Boolean); +const + ItemChangedActions: array[Boolean] of TTBItemChangedAction = + (tbicInvalidate, tbicInvalidateAndResize); +begin + if Assigned(FParent) then + FParent.Notify(ItemChangedActions[NeedResize], -1, Self); +end; + +procedure TTBCustomItem.RecreateItemViewers; +begin + if Assigned(FParent) then + FParent.Notify(tbicRecreateItemViewers, -1, Self); +end; + +procedure TTBCustomItem.ImageListChangeHandler(Sender: TObject); +var + Resize: Boolean; +begin + if Sender = FSubMenuImages then begin + FSubMenuImagesChangeLink.FLastWidth := FSubMenuImages.Width; + FSubMenuImagesChangeLink.FLastHeight := FSubMenuImages.Height; + SubMenuImagesChanged; + end + else begin + { Sender is FImages } + Resize := False; + if (FImagesChangeLink.FLastWidth <> FImages.Width) or + (FImagesChangeLink.FLastHeight <> FImages.Height) then begin + FImagesChangeLink.FLastWidth := FImages.Width; + FImagesChangeLink.FLastHeight := FImages.Height; + Resize := True; + end; + Change(Resize); + end; +end; + +procedure TTBCustomItem.SubMenuImagesChanged; +begin + Notify(tbicSubMenuImagesChanged, -1, nil); +end; + +procedure TTBCustomItem.TurnSiblingsOff; +var + I: Integer; + Item: TTBCustomItem; +begin + if (GroupIndex <> 0) and Assigned(FParent) then begin + for I := 0 to FParent.Count-1 do begin + Item := FParent[I]; + if (Item <> Self) and (Item.GroupIndex = GroupIndex) then + Item.Checked := False; + end; + end; +end; + +procedure TTBCustomItem.SetCaption(Value: String); +begin + if FCaption <> Value then begin + FCaption := Value; + Change(True); + end; +end; + +procedure TTBCustomItem.SetChecked(Value: Boolean); +begin + if FChecked <> Value then begin + FChecked := Value; + Change(False); + if Value then + TurnSiblingsOff; + end; +end; + +procedure TTBCustomItem.SetDisplayMode(Value: TTBItemDisplayMode); +begin + if FDisplayMode <> Value then begin + FDisplayMode := Value; + Change(True); + end; +end; + +procedure TTBCustomItem.EnabledChanged; +begin + Change(False); +end; + +procedure TTBCustomItem.SetEnabled(Value: Boolean); +begin + if FEnabled <> Value then begin + FEnabled := Value; + EnabledChanged; + end; +end; + +procedure TTBCustomItem.SetGroupIndex(Value: Integer); +begin + if FGroupIndex <> Value then begin + FGroupIndex := Value; + if Checked then + TurnSiblingsOff; + end; +end; + +procedure TTBCustomItem.SetImageIndex(Value: TImageIndex); +var + HadNoImage: Boolean; +begin + if FImageIndex <> Value then begin + HadNoImage := FImageIndex = -1; + FImageIndex := Value; + Change(HadNoImage xor (Value = -1)); + end; +end; + +function TTBCustomItem.ChangeImages(var AImages: TCustomImageList; + const Value: TCustomImageList; var AChangeLink: TTBImageChangeLink): Boolean; +{ Returns True if image list was resized } +var + LastWidth, LastHeight: Integer; +begin + Result := False; + LastWidth := -1; + LastHeight := -1; + if Assigned(AImages) then begin + LastWidth := AImages.Width; + LastHeight := AImages.Height; + AImages.UnregisterChanges(AChangeLink); + if Value = nil then begin + AChangeLink.Free; + AChangeLink := nil; + Result := True; + end; + end; + AImages := Value; + if Assigned(Value) then begin + Result := (Value.Width <> LastWidth) or (Value.Height <> LastHeight); + if AChangeLink = nil then begin + AChangeLink := TTBImageChangeLink.Create; + AChangeLink.FLastWidth := Value.Width; + AChangeLink.FLastHeight := Value.Height; + AChangeLink.OnChange := ImageListChangeHandler; + end; + Value.RegisterChanges(AChangeLink); + Value.FreeNotification(Self); + end; +end; + +procedure TTBCustomItem.SetImages(Value: TCustomImageList); +begin + if FImages <> Value then + Change(ChangeImages(FImages, Value, FImagesChangeLink)); +end; + +procedure TTBCustomItem.SetSubMenuImages(Value: TCustomImageList); +begin + if FSubMenuImages <> Value then begin + ChangeImages(FSubMenuImages, Value, FSubMenuImagesChangeLink); + SubMenuImagesChanged; + end; +end; + +procedure TTBCustomItem.SetInheritOptions(Value: Boolean); +begin + if FInheritOptions <> Value then begin + FInheritOptions := Value; + RefreshOptions; + end; +end; + +procedure TTBCustomItem.SetLinkSubitems(Value: TTBCustomItem); +begin + if Value = Self then + Value := nil; + if FLinkSubitems <> Value then begin + if Assigned(FLinkSubitems) then + RemoveFromList(FLinkSubitems.FLinkParents, Self); + FLinkSubitems := Value; + if Assigned(Value) then begin + Value.FreeNotification(Self); + AddToList(Value.FLinkParents, Self); + end; + Notify(tbicSubitemsChanged, -1, nil); + end; +end; + +function TTBCustomItem.FixOptions(const AOptions: TTBItemOptions): TTBItemOptions; +begin + Result := AOptions; + if not(tboToolbarStyle in Result) then + Exclude(Result, tboToolbarSize); +end; + +procedure TTBCustomItem.RefreshOptions; +const + NonInheritedOptions = [tboDefault]; + ChangeOptions = [tboDefault, tboDropdownArrow, tboImageAboveCaption, + tboNoRotation, tboSameWidth, tboToolbarStyle, tboToolbarSize]; +var + OldOptions, NewOptions: TTBItemOptions; + I: Integer; + Item: TTBCustomItem; +begin + OldOptions := FEffectiveOptions; + if FInheritOptions and Assigned(FParent) then + NewOptions := FParent.FEffectiveOptions - NonInheritedOptions + else + NewOptions := []; + NewOptions := FixOptions(NewOptions - FMaskOptions + FOptions); + if FEffectiveOptions <> NewOptions then begin + FEffectiveOptions := NewOptions; + if (OldOptions * ChangeOptions) <> (NewOptions * ChangeOptions) then + Change(True); + for I := 0 to FItemCount-1 do begin + Item := FItems[I].Item; + if Item.FInheritOptions then + Item.RefreshOptions; + end; + end; +end; + +procedure TTBCustomItem.SetMaskOptions(Value: TTBItemOptions); +begin + if FMaskOptions <> Value then begin + FMaskOptions := Value; + RefreshOptions; + end; +end; + +procedure TTBCustomItem.SetOptions(Value: TTBItemOptions); +begin + Value := FixOptions(Value); + if FOptions <> Value then begin + FOptions := Value; + RefreshOptions; + end; +end; + +procedure TTBCustomItem.SetRadioItem(Value: Boolean); +begin + if FRadioItem <> Value then begin + FRadioItem := Value; + Change(False); + end; +end; + +procedure TTBCustomItem.SetVisible(Value: Boolean); +begin + if FVisible <> Value then begin + FVisible := Value; + Change(True); + end; +end; + + +{ TTBGroupItem } + +constructor TTBGroupItem.Create(AOwner: TComponent); +begin + inherited; + ItemStyle := ItemStyle + [tbisEmbeddedGroup, tbisSubitemsEditable]; +end; + + +{ TTBSubmenuItem } + +constructor TTBSubmenuItem.Create(AOwner: TComponent); +begin + inherited; + ItemStyle := ItemStyle + [tbisSubMenu, tbisSubitemsEditable]; +end; + +function TTBSubmenuItem.GetDropdownCombo: Boolean; +begin + Result := tbisCombo in ItemStyle; +end; + +procedure TTBSubmenuItem.SetDropdownCombo(Value: Boolean); +begin + if (tbisCombo in ItemStyle) <> Value then begin + if Value then + ItemStyle := ItemStyle + [tbisCombo] + else + ItemStyle := ItemStyle - [tbisCombo]; + Change(True); + end; +end; + + +{ TTBSeparatorItem } + +constructor TTBSeparatorItem.Create(AOwner: TComponent); +begin + inherited; + ItemStyle := ItemStyle - [tbisSelectable, tbisRedrawOnSelChange, + tbisRedrawOnMouseOverChange] + [tbisSeparator, tbisClicksTransparent]; +end; + +function TTBSeparatorItem.GetItemViewerClass(AView: TTBView): TTBItemViewerClass; +begin + Result := TTBSeparatorItemViewer; +end; + +procedure TTBSeparatorItem.SetBlank(Value: Boolean); +begin + if FBlank <> Value then begin + FBlank := Value; + Change(False); + end; +end; + + +{ TTBSeparatorItemViewer } + +procedure TTBSeparatorItemViewer.CalcSize(const Canvas: TCanvas; + var AWidth, AHeight: Integer); +begin + if not IsToolbarStyle then + Inc(AHeight, DivRoundUp(GetTextHeight(Canvas.Handle) * 2, 3)) + else begin + AWidth := 6; + AHeight := 6; + end; +end; + +procedure TTBSeparatorItemViewer.Paint(const Canvas: TCanvas; + const ClientAreaRect: TRect; IsSelected, IsPushed, UseDisabledShadow: Boolean); +var + DC: HDC; + R: TRect; + ToolbarStyle, Horiz, LineSep: Boolean; +begin + DC := Canvas.Handle; + if TTBSeparatorItem(Item).FBlank then + Exit; + + R := ClientAreaRect; + ToolbarStyle := IsToolbarStyle; + Horiz := not ToolbarStyle or (View.FOrientation = tbvoVertical); + LineSep := tbisLineSep in State; + if LineSep then + Horiz := not Horiz; + if Horiz then begin + R.Top := R.Bottom div 2 - 1; + if not ToolbarStyle then + InflateRect(R, -tbMenuSeparatorOffset, 0) + else if LineSep then begin + if View.FOrientation = tbvoFloating then + InflateRect(R, -tbLineSepOffset, 0) + else + InflateRect(R, -tbDockedLineSepOffset, 0); + end; + DrawEdge(DC, R, EDGE_ETCHED, BF_TOP); + end + else begin + R.Left := R.Right div 2 - 1; + if LineSep then + InflateRect(R, 0, -tbDockedLineSepOffset); + DrawEdge(DC, R, EDGE_ETCHED, BF_LEFT); + end; +end; + +function TTBSeparatorItemViewer.UsesSameWidth: Boolean; +begin + Result := False; +end; + + +{ TTBControlItem } + +constructor TTBControlItem.Create(AOwner: TComponent); +begin + inherited; + ItemStyle := ItemStyle - [tbisSelectable] + [tbisClicksTransparent]; +end; + +constructor TTBControlItem.CreateControlItem(AOwner: TComponent; + AControl: TControl); +begin + FControl := AControl; + AControl.FreeNotification(Self); + Create(AOwner); +end; + +destructor TTBControlItem.Destroy; +begin + inherited; + { Free the associated control *after* the item is completely destroyed } + if not FDontFreeControl and Assigned(FControl) and + not(csAncestor in FControl.ComponentState) then + FControl.Free; +end; + +procedure TTBControlItem.Notification(AComponent: TComponent; + Operation: TOperation); +begin + inherited; + if (Operation = opRemove) and (AComponent = FControl) then + Control := nil; +end; + +procedure TTBControlItem.SetControl(Value: TControl); +begin + if FControl <> Value then begin + FControl := Value; + if Assigned(Value) then + Value.FreeNotification(Self); + Change(True); + end; +end; + + +{ TTBItemViewer } + +constructor TTBItemViewer.Create(AView: TTBView; AItem: TTBCustomItem; + AGroupLevel: Integer); +begin + FItem := AItem; + FView := AView; + FGroupLevel := AGroupLevel; + ReferenceClickWnd; +end; + +destructor TTBItemViewer.Destroy; +begin + RemoveFromClickList(Self); + if Assigned(FAccObjectInstance) then begin + FAccObjectInstance.ClientIsDestroying; + FAccObjectInstance := nil; + end; + inherited; + ReleaseClickWnd; +end; + +function TTBItemViewer.GetAccObject: IDispatch; +begin + if FAccObjectInstance = nil then begin + if not InitializeOleAcc then begin + Result := nil; + Exit; + end; + FAccObjectInstance := TTBItemViewerAccObject.Create(Self); + end; + Result := FAccObjectInstance; +end; + +procedure TTBItemViewer.AccSelect(const AExecute: Boolean); +{ Called by ClickWndProc when an item of type TTBItemViewer is in ClickList } +var + Obj: IDispatch; +begin + { Ensure FAccObjectInstance is created by calling GetAccObject } + Obj := GetAccObject; + if Assigned(Obj) then + (FAccObjectInstance as TTBItemViewerAccObject).HandleAccSelect(AExecute); +end; + +procedure TTBItemViewer.PostAccSelect(const AExecute: Boolean); +{ Internally called by TTBItemViewerAccObject. Don't call directly. } +begin + QueueClick(Self, Ord(AExecute)); +end; + +function TTBItemViewer.IsAccessible: Boolean; +{ Returns True if MSAA clients should know about the viewer, specifically + if it's either shown, off-edge, or clipped (in other words, not completely + invisible/inaccessible). } +begin + { Note: Can't simply check Item.Visible because the chevron item's Visible + property is always True } + Result := Show or OffEdge or Clipped; +end; + +function TTBItemViewer.GetCaptionText: String; +var + P: Integer; +begin + Result := Item.Caption; + P := Pos(#9, Result); + if P <> 0 then + SetLength(Result, P-1); +end; + +function TTBItemViewer.GetHintText: String; +var P: Integer; +begin + Result := GetShortHint(Item.Hint); + { If there is no short hint, use the caption for the hint. Like Office, + strip any trailing colon or ellipsis. } + if (Result = '') and not(tboNoAutoHint in Item.EffectiveOptions) and + (not(tbisSubmenu in Item.ItemStyle) or (tbisCombo in Item.ItemStyle) or + not CaptionShown) then + Result := StripAccelChars(StripTrailingPunctuation(GetCaptionText)); + { Call associated action's OnHint event handler to post-process the hint } + if Assigned(Item.ActionLink) and + (Item.ActionLink.Action is TCustomAction) then begin + if not TCustomAction(Item.ActionLink.Action).DoHint(Result) then + Result := ''; + { Note: TControlActionLink.DoShowHint actually misinterprets the result + of DoHint, but we get it right... } + end; + { Add shortcut text } + if (Result <> '') and Application.HintShortCuts then + begin + { Custom shortcut } + P := Pos(#9, Item.Caption); + if (P <> 0) and (P < Length(Item.Caption)) then + Result := Format('%s (%s)', [Result, Copy(Item.Caption, P+ 1, MaxInt)]) + else + if (Item.ShortCut <> scNone) then + Result := Format('%s (%s)', [Result, ShortCutToText(Item.ShortCut)]); + end; +end; + +function TTBItemViewer.CaptionShown: Boolean; +begin + Result := (GetCaptionText <> '') and (not IsToolbarSize or + (Item.ImageIndex < 0) or (Item.DisplayMode in [nbdmTextOnly, nbdmImageAndText])) or + (tboImageAboveCaption in Item.EffectiveOptions); +end; + +function TTBItemViewer.ImageShown: Boolean; +begin + {}{should also return false if Images=nil (use UsedImageList?)} + ImageShown := (Item.ImageIndex >= 0) and + ((Item.DisplayMode in [nbdmDefault, nbdmImageAndText]) or + (IsToolbarStyle and (Item.DisplayMode = nbdmTextOnlyInMenus))); +end; + +function TTBItemViewer.GetImageList: TCustomImageList; +var + V: TTBView; +begin + Result := Item.Images; + if Assigned(Result) then + Exit; + V := View; + repeat + if Assigned(V.FCurParentItem) then begin + Result := V.FCurParentItem.SubMenuImages; + if Assigned(Result) then + Break; + end; + if Assigned(V.FParentItem) then begin + Result := V.FParentItem.SubMenuImages; + if Assigned(Result) then + Break; + end; + V := V.FParentView; + until V = nil; +end; + +function TTBItemViewer.IsRotated: Boolean; +{ Returns True if the caption should be drawn with rotated (vertical) text, + underneath the image } +begin + Result := (View.Orientation = tbvoVertical) and + not (tboNoRotation in Item.EffectiveOptions) and + not (tboImageAboveCaption in Item.EffectiveOptions); +end; + +procedure TTBItemViewer.CalcSize(const Canvas: TCanvas; + var AWidth, AHeight: Integer); +var + ToolbarStyle: Boolean; + DC: HDC; + TextMetrics: TTextMetric; + H, LeftMargin: Integer; + ImgList: TCustomImageList; + S: String; + RotatedFont, SaveFont: HFONT; +begin + ToolbarStyle := IsToolbarStyle; + DC := Canvas.Handle; + ImgList := GetImageList; + if ToolbarStyle then begin + AWidth := 6; + AHeight := 6; + end + else begin + AWidth := 0; + AHeight := 0; + end; + if not ToolbarStyle or CaptionShown then begin + if not IsRotated then begin + GetTextMetrics(DC, TextMetrics); + Inc(AHeight, TextMetrics.tmHeight); + Inc(AWidth, GetTextWidth(DC, GetCaptionText, True)); + if ToolbarStyle then + Inc(AWidth, 6); + end + else begin + { Vertical text isn't always the same size as horizontal text, so we have + to select the rotated font into the DC to get an accurate size } + RotatedFont := CreateRotatedFont(DC); + SaveFont := SelectObject(DC, RotatedFont); + GetTextMetrics(DC, TextMetrics); + Inc(AWidth, TextMetrics.tmHeight); + Inc(AHeight, GetTextWidth(DC, GetCaptionText, True)); + if ToolbarStyle then + Inc(AHeight, 6); + SelectObject(DC, SaveFont); + DeleteObject(RotatedFont); + end; + end; + if ToolbarStyle and ImageShown and Assigned(ImgList) then begin + if not IsRotated and not(tboImageAboveCaption in Item.EffectiveOptions) then begin + Inc(AWidth, ImgList.Width + 1); + if AHeight < ImgList.Height + 6 then + AHeight := ImgList.Height + 6; + end + else begin + Inc(AHeight, ImgList.Height); + if AWidth < ImgList.Width + 7 then + AWidth := ImgList.Width + 7; + end; + end; + if ToolbarStyle and (tbisSubmenu in Item.ItemStyle) then begin + if tbisCombo in Item.ItemStyle then + Inc(AWidth, tbDropdownComboArrowWidth) + else + if tboDropdownArrow in Item.EffectiveOptions then begin + if View.Orientation <> tbvoVertical then + Inc(AWidth, tbDropdownArrowWidth) + else + Inc(AHeight, tbDropdownArrowWidth); + end; + end; + if not ToolbarStyle then begin + Inc(AHeight, TextMetrics.tmExternalLeading + tbMenuVerticalMargin); + if Assigned(ImgList) then begin + H := ImgList.Height + 3; + if H > AHeight then + AHeight := H; + LeftMargin := MulDiv(ImgList.Width + 3, AHeight, H); + end + else + LeftMargin := AHeight; + Inc(AWidth, LeftMargin + tbMenuImageTextSpace + tbMenuLeftTextMargin + + tbMenuRightTextMargin); + S := Item.GetShortCutText; + if S <> '' then + Inc(AWidth, (AHeight - 6) + GetTextWidth(DC, S, True)); + Inc(AWidth, AHeight); + end; +end; + +procedure TTBItemViewer.DrawItemCaption(const Canvas: TCanvas; ARect: TRect; + const ACaption: String; ADrawDisabledShadow: Boolean; AFormat: UINT); +var + DC: HDC; + + procedure Draw; + begin + if not IsRotated then + DrawText(DC, PChar(ACaption), Length(ACaption), ARect, AFormat) + else + DrawRotatedText(DC, ACaption, ARect, AFormat); + end; + +var + ShadowColor, HighlightColor, SaveTextColor: DWORD; +begin + DC := Canvas.Handle; + if not ADrawDisabledShadow then + Draw + else begin + ShadowColor := GetSysColor(COLOR_BTNSHADOW); + HighlightColor := GetSysColor(COLOR_BTNHIGHLIGHT); + OffsetRect(ARect, 1, 1); + SaveTextColor := SetTextColor(DC, HighlightColor); + Draw; + OffsetRect(ARect, -1, -1); + SetTextColor(DC, ShadowColor); + Draw; + SetTextColor(DC, SaveTextColor); + end; +end; + +procedure TTBItemViewer.Paint(const Canvas: TCanvas; + const ClientAreaRect: TRect; IsSelected, IsPushed, UseDisabledShadow: Boolean); +var + ShowEnabled, HasArrow: Boolean; + MenuCheckWidth, MenuCheckHeight: Integer; + + function GetDrawTextFlags: UINT; + begin + Result := 0; + if not AreKeyboardCuesEnabled and (vsUseHiddenAccels in View.FStyle) and + not(vsShowAccels in View.FState) then + Result := DT_HIDEPREFIX; + end; + + procedure DrawSubmenuArrow; + var + BR: TRect; + Bmp: TBitmap; + + procedure DrawWithColor(AColor: TColor); + const + ROP_DSPDxax = $00E20746; + var + DC: HDC; + SaveTextColor, SaveBkColor: TColorRef; + begin + Canvas.Brush.Color := AColor; + DC := Canvas.Handle; + SaveTextColor := SetTextColor(DC, clWhite); + SaveBkColor := SetBkColor(DC, clBlack); + BitBlt(DC, BR.Left, BR.Top, MenuCheckWidth, MenuCheckHeight, + Bmp.Canvas.Handle, 0, 0, ROP_DSPDxax); + SetBkColor(DC, SaveBkColor); + SetTextColor(DC, SaveTextColor); + Canvas.Brush.Style := bsClear; + end; + + begin + Bmp := TBitmap.Create; + try + Bmp.Monochrome := True; + Bmp.Width := MenuCheckWidth; + Bmp.Height := MenuCheckHeight; + BR := Rect(0, 0, MenuCheckWidth, MenuCheckHeight); + DrawFrameControl(Bmp.Canvas.Handle, BR, DFC_MENU, DFCS_MENUARROW); + OffsetRect(BR, ClientAreaRect.Right - MenuCheckWidth, + ClientAreaRect.Top + ((ClientAreaRect.Bottom - ClientAreaRect.Top) - MenuCheckHeight) div 2); + if not UseDisabledShadow then begin + if ShowEnabled and (tbisCombo in Item.ItemStyle) and IsSelected then begin + OffsetRect(BR, 1, 1); + DrawWithColor(clBtnText); + end + else + DrawWithColor(Canvas.Font.Color); + end + else begin + OffsetRect(BR, 1, 1); + DrawWithColor(clBtnHighlight); + OffsetRect(BR, -1, -1); + DrawWithColor(clBtnShadow); + end; + finally + Bmp.Free; + end; + end; + + procedure DrawDropdownArrow(R: TRect; Rotated: Boolean); + + procedure DrawWithColor(AColor: TColor); + var + X, Y: Integer; + P: array[0..2] of TPoint; + begin + X := (R.Left + R.Right) div 2; + Y := (R.Top + R.Bottom) div 2; + if not Rotated then begin + Dec(Y); + P[0].X := X-2; + P[0].Y := Y; + P[1].X := X+2; + P[1].Y := Y; + P[2].X := X; + P[2].Y := Y+2; + end + else begin + Dec(X); + P[0].X := X; + P[0].Y := Y+2; + P[1].X := X; + P[1].Y := Y-2; + P[2].X := X-2; + P[2].Y := Y; + end; + Canvas.Pen.Color := AColor; + Canvas.Brush.Color := AColor; + Canvas.Polygon(P); + end; + + begin + if not UseDisabledShadow then + DrawWithColor(Canvas.Font.Color) + else begin + OffsetRect(R, 1, 1); + DrawWithColor(clBtnHighlight); + OffsetRect(R, -1, -1); + DrawWithColor(clBtnShadow); + end; + end; + + function GetDitherBitmap: TBitmap; + begin + Result := AllocPatternBitmap(clBtnFace, clBtnHighlight); + Result.HandleType := bmDDB; { needed for Win95, or else brush is solid white } + end; + +const + EdgeStyles: array[Boolean] of UINT = (BDR_RAISEDINNER, BDR_SUNKENOUTER); + CheckMarkPoints: array[0..11] of TPoint = ( + { Black } + (X: -2; Y: -2), (X: 0; Y: 0), (X: 4; Y: -4), + (X: 4; Y: -3), (X: 0; Y: 1), (X: -2; Y: -1), + (X: -2; Y: -2), + { White } + (X: -3; Y: -2), (X: -3; Y: -1), (X: 0; Y: 2), + (X: 5; Y: -3), (X: 5; Y: -5)); +var + ToolbarStyle, ImageIsShown: Boolean; + R, RC, RD: TRect; + S: String; + ImgList: TCustomImageList; + I, X, Y: Integer; + Points: array[0..11] of TPoint; + DrawTextFlags: UINT; + LeftMargin: Integer; + TextMetrics: TTextMetric; +begin + ToolbarStyle := IsToolbarStyle; + ShowEnabled := Item.Enabled or View.Customizing; + HasArrow := (tbisSubmenu in Item.ItemStyle) and + ((tbisCombo in Item.ItemStyle) or (tboDropdownArrow in Item.EffectiveOptions)); + MenuCheckWidth := GetSystemMetrics(SM_CXMENUCHECK); + MenuCheckHeight := GetSystemMetrics(SM_CYMENUCHECK); + ImgList := GetImageList; + ImageIsShown := ImageShown and Assigned(ImgList); + LeftMargin := 0; + if not ToolbarStyle then begin + if Assigned(ImgList) then + LeftMargin := MulDiv(ImgList.Width + 3, ClientAreaRect.Bottom, ImgList.Height + 3) + else + LeftMargin := ClientAreaRect.Bottom; + end; + + { Border } + RC := ClientAreaRect; + if ToolbarStyle then begin + if HasArrow then begin + if tbisCombo in Item.ItemStyle then begin + Dec(RC.Right, tbDropdownComboMargin); + RD := RC; + Dec(RC.Right, tbDropdownComboArrowWidth - tbDropdownComboMargin); + RD.Left := RC.Right; + end + else begin + if View.Orientation <> tbvoVertical then + RD := Rect(RC.Right - tbDropdownArrowWidth - tbDropdownArrowMargin, 0, + RC.Right - tbDropdownArrowMargin, RC.Bottom) + else + RD := Rect(0, RC.Bottom - tbDropdownArrowWidth - tbDropdownArrowMargin, + RC.Right, RC.Bottom - tbDropdownArrowMargin); + end; + end + else + SetRectEmpty(RD); + if (IsSelected and ShowEnabled) or Item.Checked or + (csDesigning in Item.ComponentState) then begin + if not(tbisCombo in Item.ItemStyle) then + DrawEdge(Canvas.Handle, RC, EdgeStyles[IsPushed or Item.Checked], BF_RECT) + else begin + DrawEdge(Canvas.Handle, RC, EdgeStyles[(IsPushed and View.FCapture) or Item.Checked], BF_RECT); + if (IsSelected and ShowEnabled) or + (csDesigning in Item.ComponentState) then + DrawEdge(Canvas.Handle, RD, EdgeStyles[IsPushed and not View.FCapture], BF_RECT); + end; + end; + if HasArrow then begin + if not(tbisCombo in Item.ItemStyle) and IsPushed then + OffsetRect(RD, 1, 1); + DrawDropdownArrow(RD, not(tbisCombo in Item.ItemStyle) and + (View.Orientation = tbvoVertical)); + end; + InflateRect(RC, -1, -1); + if Item.Checked and not (IsSelected and ShowEnabled) then begin + Canvas.Brush.Bitmap := GetDitherBitmap; + Canvas.FillRect(RC); + Canvas.Brush.Style := bsClear; + end; + InflateRect(RC, -1, -1); + if Item.Checked or + ((IsSelected and IsPushed) and + (not(tbisCombo in Item.ItemStyle) or View.FCapture)) then + OffsetRect(RC, 1, 1); + if HasArrow and not(tbisCombo in Item.ItemStyle) then begin + if View.Orientation <> tbvoVertical then + Dec(RC.Right, tbDropdownArrowWidth) + else + Dec(RC.Bottom, tbDropdownArrowWidth); + end; + end + else begin + { On selected menu items, fill the background with the selected color. + Note: This assumes the brush color was not changed from the initial + value. } + if IsSelected then begin + R := RC; + if ImageIsShown or Item.Checked then + Inc(R.Left, LeftMargin + tbMenuImageTextSpace); + if (tbisCombo in Item.ItemStyle) and IsSelected and ShowEnabled then + Dec(R.Right, MenuCheckWidth); + Canvas.FillRect(R); + end; + end; + + { Adjust brush & font } + Canvas.Brush.Style := bsClear; + if tboDefault in Item.EffectiveOptions then + with Canvas.Font do Style := Style + [fsBold]; + GetTextMetrics(Canvas.Handle, TextMetrics); + + { Caption } + if CaptionShown then begin + S := GetCaptionText; + R := RC; + DrawTextFlags := GetDrawTextFlags; + if ToolbarStyle then begin + if ImageIsShown then begin + if not IsRotated and not(tboImageAboveCaption in Item.EffectiveOptions) then + Inc(R.Left, ImgList.Width + 1) + else + Inc(R.Top, ImgList.Height + 1); + end; + DrawItemCaption(Canvas, R, S, UseDisabledShadow, + DT_SINGLELINE or DT_CENTER or DT_VCENTER or DrawTextFlags) + end + else begin + Inc(R.Left, LeftMargin + tbMenuImageTextSpace + tbMenuLeftTextMargin); + { Like standard menus, shift the text up one pixel if the text height + is 4 pixels less than the total item height. This is done so underlined + characters aren't displayed too low. } + if (R.Bottom - R.Top) - (TextMetrics.tmHeight + TextMetrics.tmExternalLeading) = tbMenuVerticalMargin then + Dec(R.Bottom); + Inc(R.Top, TextMetrics.tmExternalLeading); + DrawItemCaption(Canvas, R, S, UseDisabledShadow, + DT_SINGLELINE or DT_LEFT or DT_VCENTER or DrawTextFlags); + end; + end; + + { Shortcut and/or submenu arrow (menus only) } + if not ToolbarStyle then begin + S := Item.GetShortCutText; + if S <> '' then begin + R := RC; + R.Left := R.Right - (R.Bottom - R.Top) - GetTextWidth(Canvas.Handle, S, True); + { Like standard menus, shift the text up one pixel if the text height + is 4 pixels less than the total item height. This is done so underlined + characters aren't displayed too low. } + if (R.Bottom - R.Top) - (TextMetrics.tmHeight + TextMetrics.tmExternalLeading) = tbMenuVerticalMargin then + Dec(R.Bottom); + Inc(R.Top, TextMetrics.tmExternalLeading); + DrawItemCaption(Canvas, R, S, UseDisabledShadow, + DT_SINGLELINE or DT_LEFT or DT_VCENTER or DT_NOPREFIX); + end; + if tbisSubmenu in Item.ItemStyle then begin + if tbisCombo in Item.ItemStyle then begin + R := RC; + R.Left := R.Right - MenuCheckWidth; + if IsSelected and ShowEnabled then + DrawEdge(Canvas.Handle, R, BDR_SUNKENOUTER, BF_RECT or BF_MIDDLE) + else begin + Dec(R.Left); + if not IsSelected then + DrawEdge(Canvas.Handle, R, EDGE_ETCHED, BF_LEFT) + else + DrawEdge(Canvas.Handle, R, BDR_SUNKENOUTER, BF_LEFT); + end; + end; + DrawSubmenuArrow; + end; + end; + + { Image, or check box } + if ImageIsShown or (not ToolbarStyle and Item.Checked) then begin + R := RC; + if ToolbarStyle then begin + if not IsRotated and not(tboImageAboveCaption in Item.EffectiveOptions) then + R.Right := R.Left + ImgList.Width + 2 + else + R.Bottom := R.Top + ImgList.Height + 2; + end + else begin + R.Right := R.Left + LeftMargin; + if (IsSelected and ShowEnabled) or Item.Checked then + DrawEdge(Canvas.Handle, R, EdgeStyles[Item.Checked], BF_RECT or BF_MIDDLE); + if Item.Checked and not IsSelected then begin + InflateRect(R, -1, -1); + Canvas.Brush.Bitmap := GetDitherBitmap; + Canvas.FillRect(R); + Canvas.Brush.Style := bsClear; + InflateRect(R, 1, 1); + end; + if Item.Checked then + OffsetRect(R, 1, 1); + end; + if ImageIsShown then begin + X := R.Left + ((R.Right - R.Left) - ImgList.Width) div 2; + Y := R.Top + ((R.Bottom - R.Top) - ImgList.Height) div 2; + if ImgList is TTBCustomImageList then + TTBCustomImageList(ImgList).DrawState(Canvas, X, Y, Item.ImageIndex, + ShowEnabled, IsSelected, Item.Checked) + else + ImgList.Draw(Canvas, X, Y, Item.ImageIndex, ShowEnabled); + end + else + if not ToolbarStyle and Item.Checked then begin + { Draw default check mark or radio button image when user hasn't + specified their own } + X := (R.Left + R.Right) div 2; + Y := (R.Top + R.Bottom) div 2; + if Item.RadioItem then begin + Canvas.Pen.Color := clBtnText; + Canvas.Brush.Color := clBtnText; + Canvas.RoundRect(X-3, Y-3, X+2, Y+2, 2, 2); + Canvas.Pen.Color := clBtnHighlight; + Canvas.Brush.Style := bsClear; + Canvas.RoundRect(X-4, Y-4, X+3, Y+3, 6, 6); + end + else begin + Dec(X, 2); + Inc(Y); + System.Move(CheckMarkPoints, Points, 12 * SizeOf(TPoint)); + for I := Low(Points) to High(Points) do begin + Inc(Points[I].X, X); + Inc(Points[I].Y, Y); + end; + Canvas.Pen.Color := clBtnText; + Polyline(Canvas.Handle, Points[0], 7); + Canvas.Pen.Color := clBtnHighlight; + Polyline(Canvas.Handle, Points[7], 5); + end; + end; + end; +end; + +procedure TTBItemViewer.GetCursor(const Pt: TPoint; var ACursor: HCURSOR); +begin +end; + +function TTBItemViewer.GetIndex: Integer; +begin + Result := View.IndexOf(Self); +end; + +function TTBItemViewer.IsToolbarSize: Boolean; +begin + Result := View.FIsToolbar or (tboToolbarSize in Item.FEffectiveOptions); +end; + +function TTBItemViewer.IsToolbarStyle: Boolean; +begin + Result := View.FIsToolbar or (tboToolbarStyle in Item.FEffectiveOptions); +end; + +function TTBItemViewer.IsPtInButtonPart(X, Y: Integer): Boolean; +var + W: Integer; +begin + Result := not(tbisSubmenu in Item.ItemStyle); + if tbisCombo in Item.ItemStyle then begin + if IsToolbarStyle then + W := tbDropdownComboArrowWidth + else + W := GetSystemMetrics(SM_CXMENUCHECK); + Result := X < (BoundsRect.Right - BoundsRect.Left) - W; + end; +end; + +procedure TTBItemViewer.MouseDown(Shift: TShiftState; X, Y: Integer; + var MouseDownOnMenu: Boolean); + + procedure HandleDefaultDoubleClick(const View: TTBView); + { Looks for a tboDefault item in View and ends the modal loop if it finds + one. } + var + I: Integer; + Viewer: TTBItemViewer; + Item: TTBCustomItem; + begin + for I := 0 to View.FViewerCount-1 do begin + Viewer := View.FViewers[I]; + Item := Viewer.Item; + if (Viewer.Show or Viewer.Clipped) and (tboDefault in Item.EffectiveOptions) and + (tbisSelectable in Item.ItemStyle) and Item.Enabled and Item.Visible then begin + Viewer.Execute(True); + Break; + end; + end; + end; + +var + WasAlreadyOpen: Boolean; +begin + if not Item.Enabled then begin + if (View.FParentView = nil) and not View.FIsPopup then + View.EndModal; + Exit; + end; + if IsPtInButtonPart(X, Y) then begin + if IsToolbarStyle then begin + View.CancelChildPopups; + View.SetCapture; + View.Invalidate(Self); + end; + end + else begin + WasAlreadyOpen := (View.FOpenViewer = Self); + if View.OpenChildPopup(False) then begin + if WasAlreadyOpen and ((View.FParentView = nil) and not View.FIsPopup) then + MouseDownOnMenu := True; + if (ssDouble in Shift) and not(tbisCombo in Item.ItemStyle) then + HandleDefaultDoubleClick(View.FOpenViewerView); + end; + end; +end; + +procedure TTBItemViewer.MouseMove(X, Y: Integer); +begin +end; + +procedure TTBItemViewer.MouseUp(X, Y: Integer; MouseWasDownOnMenu: Boolean); +var + HadCapture, IsToolbarItem: Boolean; +begin + HadCapture := View.FCapture; + View.CancelCapture; + IsToolbarItem := (View.FParentView = nil) and not View.FIsPopup; + if not View.FMouseOverSelected or not Item.Enabled or + (tbisClicksTransparent in Item.ItemStyle) then begin + if IsToolbarItem then + View.EndModal; + Exit; + end; + if (tbisSubmenu in Item.ItemStyle) and not IsPtInButtonPart(X, Y) then begin + if IsToolbarItem and MouseWasDownOnMenu then + View.EndModal; + end + else begin + { it's a 'normal' item } + if not IsToolbarStyle or HadCapture then + Execute(True); + end; +end; + +procedure TTBItemViewer.MouseWheel(WheelDelta, X, Y: Integer); +begin +end; + +procedure TTBItemViewer.LosingCapture; +begin + View.Invalidate(Self); +end; + +procedure TTBItemViewer.Entering(OldSelected: TTBItemViewer); +begin + if Assigned(Item.FOnSelect) then + Item.FOnSelect(Item, Self, True); +end; + +procedure TTBItemViewer.Leaving; +begin + if Assigned(Item.FOnSelect) then + Item.FOnSelect(Item, Self, False); +end; + +procedure TTBItemViewer.KeyDown(var Key: Word; Shift: TShiftState); +begin +end; + +function TTBItemViewer.ScreenToClient(const P: TPoint): TPoint; +begin + Result := View.FWindow.ScreenToClient(P); + Dec(Result.X, BoundsRect.Left); + Dec(Result.Y, BoundsRect.Top); +end; + +function TTBItemViewer.UsesSameWidth: Boolean; +{ If UsesSameWidth returns True, the item viewer's width will be expanded to + match the widest item viewer on the same view whose UsesSameWidth method + also returns True. } +begin + Result := (tboImageAboveCaption in Item.FEffectiveOptions) and + (tboSameWidth in Item.FEffectiveOptions) and IsToolbarSize; +end; + +function TTBItemViewer.DoExecute: Boolean; +{ Low-level 'execute' handler. Returns True if the caller should call + GivePriority on the viewer (normally, if the 'execute' operation was a + success and the modal loop is ending). } +begin + View.EndModalWithClick(Self); + Result := True; +end; + +procedure TTBItemViewer.Execute(AGivePriority: Boolean); +{ Calls DoExecute and, if applicable, View.GivePriority. Note that it is up to + the caller to check the viewer's visibility and enabled state. } +begin + if DoExecute and AGivePriority then + View.GivePriority(Self); +end; + +function TTBItemViewer.GetAccRole: Integer; +{ Returns the MSAA "role" of the viewer. } +const + { Constants from OleAcc.h } + ROLE_SYSTEM_CLIENT = $a; + ROLE_SYSTEM_MENUITEM = $c; + ROLE_SYSTEM_SEPARATOR = $15; + ROLE_SYSTEM_PUSHBUTTON = $2b; + ROLE_SYSTEM_BUTTONMENU = $39; +begin + if Item is TTBControlItem then + Result := ROLE_SYSTEM_CLIENT + else if tbisSeparator in Item.ItemStyle then + Result := ROLE_SYSTEM_SEPARATOR + else if View.IsPopup or (vsMenuBar in View.Style) then + Result := ROLE_SYSTEM_MENUITEM + else if tbisSubmenu in Item.ItemStyle then + Result := ROLE_SYSTEM_BUTTONMENU + else + Result := ROLE_SYSTEM_PUSHBUTTON; +end; + +function TTBItemViewer.GetAccValue(var Value: WideString): Boolean; +{ Gets the MSAA "value" text of the viewer. Returns True if something was + assigned to Value, or False if the viewer does not possess a "value". } +begin + Result := False; +end; + + +{ TTBView } + +constructor TTBView.CreateView(AOwner: TComponent; AParentView: TTBView; + AParentItem: TTBCustomItem; AWindow: TWinControl; + AIsToolbar, ACustomizing, AUsePriorityList: Boolean); +begin + Create(AOwner); + FBackgroundColor := clDefault; + FCustomizing := ACustomizing; + FIsPopup := not AIsToolbar; + FIsToolbar := AIsToolbar; + FNewViewersGetHighestPriority := True; + FParentView := AParentView; + FParentItem := AParentItem; + if Assigned(FParentItem) then begin + //FIsToolbar := FIsToolbar or FParentItem.FDisplayAsToolbar; + FParentItem.RegisterNotification(LinkNotification); + FParentItem.FreeNotification(Self); + end; + FUsePriorityList := AUsePriorityList; + FWindow := AWindow; + UpdateCurParentItem; +end; + +destructor TTBView.Destroy; +begin + CloseChildPopups; + if Assigned(FAccObjectInstance) then begin + FAccObjectInstance.ClientIsDestroying; + { Get rid of our own reference to FAccObjectInstance. Normally the + reference count will be now be zero and FAccObjectInstance will be + freed, unless MSAA still holds a reference. } + FAccObjectInstance._Release; + FAccObjectInstance := nil; + end; + { If parent view is a toolbar, invalidate the open item so that it's + redrawn back in the "up" position } + if Assigned(ParentView) and ParentView.FIsToolbar then begin + Include(ParentView.FState, vsNoAnimation); + if Assigned(ParentView.FOpenViewer) then + ParentView.Invalidate(ParentView.FOpenViewer); + end; + if Assigned(FCurParentItem) then + FCurParentItem.UnregisterNotification(ItemNotification); + if Assigned(FParentItem) then + FParentItem.UnregisterNotification(LinkNotification); + inherited; + FPriorityList.Free; + FreeViewers; + { Now that we're destroyed, "focus" the parent view } + if Assigned(FParentView) then + FParentView.NotifyFocusEvent; +end; + +function TTBView.GetAccObject: IDispatch; +begin + if FAccObjectInstance = nil then begin + if not InitializeOleAcc then begin + Result := nil; + Exit; + end; + FAccObjectInstance := TTBViewAccObject.Create(Self); + { Strictly as an optimization, take a reference for ourself and keep it + for the lifetime of the view. (Destroy calls _Release.) } + FAccObjectInstance._AddRef; + end; + Result := FAccObjectInstance; +end; + +function TTBView.HandleWMGetObject(var Message: TMessage): Boolean; +begin + if (Message.LParam = Integer(OBJID_CLIENT)) and InitializeOleAcc then begin + Message.Result := LresultFromObjectFunc(ITBAccessible, Message.WParam, GetAccObject); + Result := True; + end + else + Result := False; +end; + +procedure TTBView.UpdateCurParentItem; +var + Value: TTBCustomItem; +begin + Value := ItemContainingItems(FParentItem); + if FCurParentItem <> Value then begin + CloseChildPopups; + if Assigned(FCurParentItem) then + FCurParentItem.UnregisterNotification(ItemNotification); + FCurParentItem := Value; + if Assigned(Value) then + Value.RegisterNotification(ItemNotification); + RecreateAllViewers; + if Assigned(Value) and not(csDesigning in Value.ComponentState) then + InitiateActions; + end; +end; + +procedure TTBView.InitiateActions; +var + I: Integer; +begin + { Use a 'while' instead of a 'for' since an InitiateAction implementation + may add/delete items } + I := 0; + while I < FViewerCount do begin + FViewers[I].Item.InitiateAction; + Inc(I); + end; +end; + +procedure TTBView.Notification(AComponent: TComponent; Operation: TOperation); +begin + inherited; + if Operation = opRemove then begin + if AComponent = FParentItem then begin + FParentItem := nil; + UpdateCurParentItem; + if Assigned(FParentView) then + FParentView.CloseChildPopups; + end + else if AComponent = FOpenViewerWindow then begin + FOpenViewerWindow := nil; + FOpenViewerView := nil; + FOpenViewer := nil; + end + else if AComponent = FChevronParentView then + FChevronParentView := nil; + end +end; + +function TTBView.ContainsView(AView: TTBView): Boolean; +begin + while Assigned(AView) and (AView <> Self) do + AView := AView.FParentView; + Result := Assigned(AView); +end; + +function TTBView.GetRootView: TTBView; +begin + Result := Self; + while Assigned(Result.FParentView) do + Result := Result.FParentView; +end; + +function TTBView.GetParentToolbarView: TTBView; +begin + Result := Self; + while Assigned(Result) and not Result.FIsToolbar do + Result := Result.FParentView; +end; + +procedure TTBView.FreeViewers; +var + VI: PTBItemViewerArray; + I, C: Integer; +begin + if Assigned(FViewers) then begin + VI := FViewers; + C := FViewerCount; + FViewers := nil; + FViewerCount := 0; + for I := C-1 downto 0 do + FreeAndNil(VI[I]); + FreeMem(VI); + end; +end; + +procedure TTBView.InvalidatePositions; +begin + if FValidated then begin + FValidated := False; + if Assigned(FWindow) and FWindow.HandleAllocated then + InvalidateRect(FWindow.Handle, nil, True); + end; +end; + +procedure TTBView.ValidatePositions; +begin + if not FValidated then + UpdatePositions; +end; + +procedure TTBView.TryValidatePositions; +begin + if (FUpdating = 0) and + (not Assigned(FParentItem) or not(csLoading in FParentItem.ComponentState)) and + (not Assigned(FParentItem.Owner) or not(csLoading in FParentItem.Owner.ComponentState)) then + ValidatePositions; +end; + +(*procedure TTBView.TryRevalidatePositions; +begin + if FValidated then begin + if FUpdating = 0 then begin + FreePositions; + UpdatePositions; + end + else + InvalidatePositions; + end; +end;*) + +function TTBView.Find(Item: TTBCustomItem): TTBItemViewer; +var + I: Integer; +begin + for I := 0 to FViewerCount-1 do + if FViewers[I].Item = Item then begin + Result := FViewers[I]; + Exit; + end; + raise ETBItemError.Create(STBViewerNotFound); +end; + +function TTBView.IndexOf(AViewer: TTBItemViewer): Integer; +var + I: Integer; +begin + if Assigned(AViewer) then + for I := 0 to FViewerCount-1 do + if FViewers[I] = AViewer then begin + Result := I; + Exit; + end; + Result := -1; +end; + + +procedure TTBView.DeletingViewer(Viewer: TTBItemViewer); +begin + if FSelected = Viewer then + FSelected := nil; + if FOpenViewer = Viewer then + CloseChildPopups; +end; + +procedure TTBView.RecreateItemViewer(const I: Integer); +var + OldViewer, NewViewer: TTBItemViewer; + J: Integer; +begin + OldViewer := FViewers[I]; + DeletingViewer(OldViewer); + NewViewer := OldViewer.Item.GetItemViewerClass(Self).Create(Self, + OldViewer.Item, OldViewer.FGroupLevel); + FViewers[I] := NewViewer; + if Assigned(FPriorityList) then begin + J := FPriorityList.IndexOf(OldViewer); + if J <> -1 then + FPriorityList[J] := NewViewer; + end; + OldViewer.Free; +end; + +function TTBView.InsertItemViewers(const NewIndex: Integer; + const AItem: TTBCustomItem; const AGroupLevel: Integer; + const AddToPriorityList, TopOfPriorityList: Boolean): Integer; +var + NewViewer: TTBItemViewer; + LinkItem: TTBCustomItem; + I: Integer; +begin + if AGroupLevel > MaxGroupLevel then begin + Result := 0; + Exit; + end; + + NewViewer := AItem.GetItemViewerClass(Self).Create(Self, AItem, + AGroupLevel); + InsertIntoViewerArray(FViewers, FViewerCount, NewIndex, + NewViewer); + if AddToPriorityList and FUsePriorityList then begin + if not TopOfPriorityList then + AddToList(FPriorityList, NewViewer) + else + { When new items are inserted programmatically at run-time, place + them at the top of FPriorityList } + AddToFrontOfList(FPriorityList, NewViewer); + end; + Result := 1; + + { If a new group item is being inserted, insert all its child items too } + if not FCustomizing and (tbisEmbeddedGroup in AItem.ItemStyle) then begin + LinkItem := ItemContainingItems(AItem); + for I := 0 to LinkItem.Count-1 do begin + Inc(Result, InsertItemViewers(NewIndex + Result, LinkItem.FItems[I].Item, + AGroupLevel + 1, AddToPriorityList, TopOfPriorityList)); + end; + end; +end; + +procedure TTBView.ItemNotification(Ancestor: TTBCustomItem; Relayed: Boolean; + Action: TTBItemChangedAction; Index: Integer; Item: TTBCustomItem); + + procedure ItemInserted; + var + NewLevel, Start, InsertPoint, Last: Integer; + GroupItem, NextItem: TTBCustomItem; + Found, SearchAgain: Boolean; + begin + InvalidatePositions; + NewLevel := 0; + Start := 0; + if Ancestor = FCurParentItem then + InsertPoint := FViewerCount + else begin + { Ancestor <> FCurParentItem, so apparently an item has been inserted + inside a group item } + repeat + Found := False; + while Start < FViewerCount do begin + GroupItem := FViewers[Start].Item; + if (tbisEmbeddedGroup in GroupItem.ItemStyle) and (GroupItem = Ancestor) then begin + NewLevel := FViewers[Start].FGroupLevel + 1; + Inc(Start); + Found := True; + Break; + end; + Inc(Start); + end; + if not Found then + { Couldn't find Ancestor; it shouldn't get here } + Exit; + InsertPoint := Start; + SearchAgain := False; + while (InsertPoint < FViewerCount) and + (FViewers[InsertPoint].FGroupLevel >= NewLevel) do begin + if (FViewers[InsertPoint].Item = Item) and + (FViewers[InsertPoint].FGroupLevel = NewLevel) then begin + { If the item we were going to insert already exists, then there + must be multiple instances of the same group item. This can + happen when are two group items on the same toolbar each + linking to the same submenu item, with the submenu item + containing a group item of its own, and an item is inserted + inside that. } + SearchAgain := True; + Break; + end; + Inc(InsertPoint); + end; + until not SearchAgain; + end; + if InsertPoint = FViewerCount then begin + { Don't add items after the chevron or MDI buttons item } + Dec(InsertPoint, FInternalViewersAtEnd); + if InsertPoint < 0 then + InsertPoint := 0; { just in case? } + end; + { If the new item wasn't placed at the end, adjust InsertPoint accordingly } + if Index < Item.Parent.Count-1 then begin + Last := InsertPoint; + InsertPoint := Start; + NextItem := Item.Parent.FItems[Index+1].Item; + while (InsertPoint < Last) and + ((FViewers[InsertPoint].Item <> NextItem) or + (FViewers[InsertPoint].FGroupLevel <> NewLevel)) do + Inc(InsertPoint); + end; + InsertItemViewers(InsertPoint, Item, NewLevel, True, + not(csLoading in Item.ComponentState) and FNewViewersGetHighestPriority); + end; + + procedure ItemDeleting; + + procedure DeleteItem(DeleteIndex: Integer); + var + Viewer: TTBItemViewer; + begin + Viewer := FViewers[DeleteIndex]; + DeletingViewer(Viewer); + RemoveFromList(FPriorityList, Viewer); + FreeAndNil(Viewer); + DeleteFromViewerArray(FViewers, FViewerCount, DeleteIndex); + end; + + var + I: Integer; + DeleteLevel: Integer; + begin + InvalidatePositions; + I := 0; + DeleteLevel := 0; + while I < FViewerCount do begin + if DeleteLevel > 0 then begin + if FViewers[I].FGroupLevel >= DeleteLevel then begin + DeleteItem(I); + Continue; + end + else + DeleteLevel := 0; + end; + if FViewers[I].Item = Item then begin + { Delete the item, and any group item children afterward } + DeleteLevel := FViewers[I].FGroupLevel + 1; + DeleteItem(I); + Continue; + end; + Inc(I); + end; + end; + +var + I: Integer; +begin + case Action of + tbicInserted: ItemInserted; + tbicDeleting: ItemDeleting; + tbicSubitemsChanged: begin + { If Relayed=True, LinkSubitems must have changed on a child group + item. Currently there isn't any optimized way of handling this + situation; just recreate all viewers. } + if Relayed then + RecreateAllViewers; + end; + tbicSubitemsBeginUpdate: BeginUpdate; + tbicSubitemsEndUpdate: EndUpdate; + tbicInvalidate: begin + for I := 0 to FViewerCount-1 do + if FViewers[I].Item = Item then + Invalidate(FViewers[I]); + end; + tbicInvalidateAndResize: InvalidatePositions; + tbicRecreateItemViewers: begin + InvalidatePositions; + for I := 0 to FViewerCount-1 do + if FViewers[I].Item = Item then + RecreateItemViewer(I); + end; + tbicSubMenuImagesChanged: ImagesChanged; + else + { Prevent TryValidatePositions from being called below on Actions other than + those listed above. Currently there are no other Actions, but for forward + compatibility, we should ignore unknown Actions completely. } + Exit; + end; + TryValidatePositions; +end; + +procedure TTBView.LinkNotification(Ancestor: TTBCustomItem; Relayed: Boolean; + Action: TTBItemChangedAction; Index: Integer; Item: TTBCustomItem); +{ This notification procedure watches for tbicSubitemsChanged notifications + from FParentItem } +begin + case Action of + tbicSubitemsChanged: begin + { LinkSubitems may have changed on FParentItem, e.g. on the root item + of a toolbar, so see if FCurParentItem needs updating } + UpdateCurParentItem; + end; + tbicSubMenuImagesChanged: begin + { In case the images were inherited from the actual parent instead of + the linked parent... } + if FParentItem <> FCurParentItem then + ImagesChanged; + end; + end; +end; + +procedure TTBView.ImagesChanged; +begin + InvalidatePositions; + TryValidatePositions; + if Assigned(FOpenViewerView) then + FOpenViewerView.ImagesChanged; +end; + +procedure TTBView.GivePriority(AViewer: TTBItemViewer); +{ Move item to top of priority list. Rearranges items if necessary. } +var + I: Integer; +begin + if Assigned(FChevronParentView) then begin + I := AViewer.Index + FChevronParentView.FInternalViewersAtFront; + if I < FChevronParentView.FViewerCount then { range check just in case } + FChevronParentView.GivePriority(FChevronParentView.FViewers[I]); + Exit; + end; + if Assigned(FPriorityList) then begin + I := FPriorityList.IndexOf(AViewer); + if I <> -1 then begin + FPriorityList.Move(I, 0); + if not FValidated or AViewer.OffEdge then + UpdatePositions; + end; + end; + { Call GivePriority on parent view, so that if an item on a submenu is + clicked, the parent item of the submenu gets priority. } + if Assigned(FParentView) and Assigned(FParentView.FOpenViewer) then + FParentView.GivePriority(FParentView.FOpenViewer); +end; + +function TTBView.HighestPriorityViewer: TTBItemViewer; +{ Returns index of first visible, non-separator item at top of priority list, + or -1 if there are no items found } +var + I: Integer; + J: TTBItemViewer; +begin + ValidatePositions; + Result := nil; + if Assigned(FPriorityList) then begin + for I := 0 to FPriorityList.Count-1 do begin + J := FPriorityList[I]; + if J.Show and not(tbisSeparator in J.Item.ItemStyle) then begin + Result := J; + Break; + end; + end; + end + else begin + for I := 0 to FViewerCount-1 do begin + J := FViewers[I]; + if J.Show and not(tbisSeparator in J.Item.ItemStyle) then begin + Result := J; + Break; + end; + end; + end; +end; + +procedure TTBView.StartTimer(const ATimer: TTBViewTimerID; + const Interval: Integer); +{ Starts a timer. Stops any previously set timer of the same ID first. + Note: WM_TIMER messages generated by timers set by the method are handled + in PopupMessageLoop. } +begin + StopTimer(ATimer); + if (FWindow is TTBPopupWindow) and FWindow.HandleAllocated then begin + SetTimer(FWindow.Handle, ViewTimerBaseID + Ord(ATimer), Interval, nil); + Include(FActiveTimers, ATimer); + end; +end; + +procedure TTBView.StopAllTimers; +var + I: TTBViewTimerID; +begin + for I := Low(I) to High(I) do + StopTimer(I); +end; + +procedure TTBView.StopTimer(const ATimer: TTBViewTimerID); +begin + if ATimer in FActiveTimers then begin + if (FWindow is TTBPopupWindow) and FWindow.HandleAllocated then + KillTimer(FWindow.Handle, ViewTimerBaseID + Ord(ATimer)); + Exclude(FActiveTimers, ATimer); + end; +end; + +function TTBView.OpenChildPopup(const SelectFirstItem: Boolean): Boolean; +var + Item: TTBCustomItem; +begin + StopTimer(tiClose); + StopTimer(tiOpen); + if FSelected <> FOpenViewer then begin + CloseChildPopups; + if Assigned(FSelected) then begin + Item := FSelected.Item; + if Item.Enabled and (tbisSubmenu in Item.ItemStyle) then + Item.CreatePopup(Self, FSelected, not FIsToolbar, SelectFirstItem, + False, Point(0, 0), tbpaLeft); + end; + end; + Result := Assigned(FOpenViewer); +end; + +procedure TTBView.CloseChildPopups; +begin + if Assigned(FOpenViewerView) then + FOpenViewerView.CloseChildPopups; + StopTimer(tiClose); + FOpenViewerWindow.Free; + FOpenViewerWindow := nil; + FOpenViewerView := nil; + FOpenViewer := nil; +end; + +procedure TTBView.CancelChildPopups; +begin + if FIsToolbar then + Exclude(FState, vsDropDownMenus); + CloseChildPopups; +end; + +function TTBView.ViewerFromPoint(const P: TPoint): TTBItemViewer; +var + I: Integer; +begin + ValidatePositions; + for I := 0 to FViewerCount-1 do begin + if FViewers[I].Show and + PtInRect(FViewers[I].BoundsRect, P) then begin + Result := FViewers[I]; + Exit; + end; + end; + Result := nil; +end; + +procedure TTBView.NotifyFocusEvent; +{ Notifies Active Accessibility of a change in "focus". Has no effect if the + view or the root view lacks the vsModal state, or if the modal loop is + ending (EndModal* was called). } +var + I, ChildID, J: Integer; +begin + { Note: We don't notify about windows not yet shown (e.g. a popup menu that + is still initializing) because that would probably confuse screen readers. + Also allocating a window handle at this point *might* not be a good idea. } + if (vsModal in FState) and (vsModal in GetRootView.FState) and + not IsModalEnding and + FWindow.HandleAllocated and IsWindowVisible(FWindow.Handle) then begin + if Assigned(FSelected) and FSelected.IsAccessible then + I := IndexOf(FSelected) + else + I := -1; + if (I < 0) and Assigned(FParentView) then begin + { If we have no selected item, report the the selected item on the parent + view as having the "focus". + Note: With standard menus, when you go from having a selection to no + selection on a submenu, it sends two focus events - first with the + client window as having the focus, then with the parent item. I + figure that's probably a bug, so I don't try to emulate that behavior + here. } + FParentView.NotifyFocusEvent; + end + else begin + if I >= 0 then begin + { Convert viewer index into a one-based child index. + (TTBViewAccObject.get_accChild does the inverse.) } + ChildID := 1; + for J := 0 to I-1 do + if FViewers[J].IsAccessible then + Inc(ChildID); + end + else begin + { If there is no (accessible) selection and no parent view, report + the client window itself as being "focused". This is what happens + when a standard context menu has no selection. } + ChildID := CHILDID_SELF; + end; + CallNotifyWinEvent(EVENT_OBJECT_FOCUS, FWindow.Handle, OBJID_CLIENT, ChildID); + end; + end; +end; + +procedure TTBView.SetSelected(Value: TTBItemViewer); +begin + Select(Value, False); +end; + +procedure TTBView.Select(Value: TTBItemViewer; ViaMouse: Boolean); +{ Sets the current selection. + When the selection is changing it will also, if necessary, open/close child + popups. How exactly this works depends on the setting of ViaMouse. If + ViaMouse is True it will delay the opening/closing of popups using timers. } +var + OldSelected: TTBItemViewer; + NewMouseOverSelected: Boolean; + P: TPoint; +begin + OldSelected := FSelected; + if Value <> OldSelected then begin + { If there's a new selection and the parent item on the parent view + isn't currently selected, select it. Also stop any timer running on + the parent view. } + if Assigned(Value) and Assigned(FParentView) and + Assigned(FParentView.FOpenViewer) and + (FParentView.FSelected <> FParentView.FOpenViewer) then begin + FParentView.Selected := FParentView.FOpenViewer; + FParentView.StopTimer(tiClose); + FParentView.StopTimer(tiOpen); + end; + + { Handle automatic closing of child popups } + if vsModal in FState then begin + { If the view is a toolbar, or if the new selection didn't come from + the mouse, close child popups immediately } + if FIsToolbar or not ViaMouse then begin + { Always stop any close timer because CloseChildPopups may not be + called below } + StopTimer(tiClose); + if Value <> FOpenViewer then + { ^ But don't close if selection is returning to the open item. + Needed for the "FParentView.Selected := FParentView.FOpenViewer" + line above to work. } + CloseChildPopups; + end + else begin + { Otherwise, delay-close any child popup } + if Assigned(FOpenViewerView) and not(tiClose in FActiveTimers) then + StartTimer(tiClose, GetMenuShowDelay); + end; + end; + + CancelCapture; + if Assigned(OldSelected) then + OldSelected.Leaving; + FSelected := Value; + FSelectedViaMouse := ViaMouse; + end; + + NewMouseOverSelected := False; + if Assigned(Value) and Assigned(FWindow) then begin + P := SmallPointToPoint(TSmallPoint(GetMessagePos())); + if FindDragTarget(P, True) = FWindow then begin + P := FWindow.ScreenToClient(P); + NewMouseOverSelected := (ViewerFromPoint(P) = Value); + if NewMouseOverSelected and FCapture and + not Value.IsPtInButtonPart(P.X - Value.BoundsRect.Left, + P.Y - Value.BoundsRect.Top) then + NewMouseOverSelected := False; + end; + end; + + if Value <> OldSelected then begin + FMouseOverSelected := NewMouseOverSelected; + if Assigned(OldSelected) and (tbisRedrawOnSelChange in OldSelected.Item.ItemStyle) then + Invalidate(OldSelected); + if Assigned(Value) then begin + if tbisRedrawOnSelChange in Value.Item.ItemStyle then + Invalidate(Value); + Value.Entering(OldSelected); + end; + NotifyFocusEvent; + + { Handle automatic opening of a child popup } + if vsModal in FState then begin + { If the view is a toolbar, immediately open any child popup } + if FIsToolbar then begin + if Assigned(Value) then begin + if ViaMouse and Assigned(FParentView) then begin + { On chevron popups, always drop down menus when mouse passes + over them, like Office 2000 } + Include(FState, vsDropDownMenus); + end; + if (vsDropDownMenus in FState) and + (ViaMouse or not(tbisNoAutoOpen in Value.Item.ItemStyle)) then + OpenChildPopup(not ViaMouse); + end; + end + else begin + { Otherwise, delay-open any child popup if the selection came from + the mouse } + StopTimer(tiOpen); + if ViaMouse and Assigned(Value) and (tbisSubmenu in Value.Item.ItemStyle) then + StartTimer(tiOpen, GetMenuShowDelay); + end; + end; + end + else if FMouseOverSelected <> NewMouseOverSelected then begin + FMouseOverSelected := NewMouseOverSelected; + if Assigned(Value) and FCapture and (tbisRedrawOnMouseOverChange in Value.Item.ItemStyle) then + Invalidate(Value); + end; +end; + +procedure TTBView.UpdateSelection(const P: PPoint; const AllowNewSelection: Boolean); +{ Called in response to a mouse movement, this method updates the current + selection, updates the vsMouseInWindow view state, and enables/disables + scroll timers. } + + function IsPtInScrollArrow(ADownArrow: Boolean): Boolean; + var + P2: TPoint; + R: TRect; + begin + Result := False; + if (vsModal in FState) and (vsMouseInWindow in FState) and + Assigned(P) then begin + P2 := FWindow.ScreenToClient(P^); + R := FWindow.ClientRect; + if PtInRect(R, P2) then begin + if ADownArrow then + Result := FShowDownArrow and (P2.Y >= R.Bottom - tbMenuScrollArrowHeight) + else + Result := FShowUpArrow and (P2.Y < tbMenuScrollArrowHeight); + end; + end; + end; + +var + NewSelected, ViewerAtPoint: TTBItemViewer; + P2: TPoint; + MouseWasInWindow: Boolean; +begin + ValidatePositions; + + { If modal, default to keeping the existing selection } + if vsModal in FState then + NewSelected := FSelected + else + NewSelected := nil; + + { Is the mouse inside the window? } + MouseWasInWindow := vsMouseInWindow in FState; + if Assigned(P) and Assigned(FWindow) and (FindDragTarget(P^, True) = FWindow) then begin + { If we're a popup window and the mouse is inside, default to no selection } + if FIsPopup then + NewSelected := nil; + Include(FState, vsMouseInWindow); + if AllowNewSelection or Assigned(FSelected) then begin + P2 := FWindow.ScreenToClient(P^); + ViewerAtPoint := ViewerFromPoint(P2); + if Assigned(ViewerAtPoint) then + NewSelected := ViewerAtPoint; + end; + end + else + Exclude(FState, vsMouseInWindow); + + { If FCapture is True, don't allow the selection to change } + if FCapture and (NewSelected <> FSelected) then + NewSelected := FSelected; + + { If we're a popup window and there is a selection... } + if FIsPopup and Assigned(NewSelected) then begin + { If the mouse just moved out of the window and no submenu was open, + remove the highlight } + if not FCapture and MouseWasInWindow and not(vsMouseInWindow in FState) and + (not Assigned(FOpenViewerView) or not(tbisSubmenu in NewSelected.Item.ItemStyle)) then + NewSelected := nil; + end; + + { Now we set the new Selected value } + Select(NewSelected, True); + + { Update scroll arrow timers } + if IsPtInScrollArrow(False) then begin + StopTimer(tiScrollDown); + if not(tiScrollUp in FActiveTimers) then + StartTimer(tiScrollUp, 100); + end + else if IsPtInScrollArrow(True) then begin + StopTimer(tiScrollUp); + if not(tiScrollDown in FActiveTimers) then + StartTimer(tiScrollDown, 100); + end + else begin + StopTimer(tiScrollUp); + StopTimer(tiScrollDown); + end; +end; + +procedure TTBView.RecreateAllViewers; +var + Item: TTBCustomItem; + I: Integer; +begin + { Since the FViewers list is being rebuilt, FOpenViewer and FSelected + will no longer be valid, so ensure they're set to nil. } + CloseChildPopups; + Selected := nil; + + InvalidatePositions; + + FreeAndNil(FPriorityList); + FreeViewers; + FInternalViewersAtFront := 0; + FInternalViewersAtEnd := 0; + + { MDI system menu item } + Item := GetMDISystemMenuItem; + if Assigned(Item) then + Inc(FInternalViewersAtFront, InsertItemViewers(FViewerCount, Item, 0, + False, False)); + + { Items } + if Assigned(FCurParentItem) then begin + for I := 0 to FCurParentItem.Count-1 do + InsertItemViewers(FViewerCount, FCurParentItem.FItems[I].Item, 0, + True, False); + end; + + { MDI buttons item } + Item := GetMDIButtonsItem; + if Assigned(Item) then begin + for I := 0 to Item.Count-1 do + Inc(FInternalViewersAtEnd, InsertItemViewers(FViewerCount, + Item.FItems[I].Item, 0, False, False)); + end; + + { Chevron item } + Item := GetChevronItem; + if Assigned(Item) then + Inc(FInternalViewersAtEnd, InsertItemViewers(FViewerCount, Item, 0, + False, False)); +end; + +function TTBView.CalculatePositions(const CanMoveControls: Boolean; + const AOrientation: TTBViewOrientation; + AWrapOffset, AChevronOffset, AChevronSize: Integer; + var ABaseSize, TotalSize: TPoint; + var AWrappedLines: Integer): Boolean; +{ Returns True if the positions have changed } +type + PTempPosition = ^TTempPosition; + TTempPosition = record + BoundsRect: TRect; + Show, OffEdge, LineSep, Clipped, SameWidth: Boolean; + end; + PTempPositionArray = ^TTempPositionArray; + TTempPositionArray = array[0..$7FFFFFFF div SizeOf(TTempPosition)-1] of TTempPosition; +var + DC: HDC; + LeftX, TopY, CurX, CurY, I: Integer; + NewPositions: PTempPositionArray; + GroupSplit, DidWrap: Boolean; + LineStart, HighestHeightOnLine, HighestWidthOnLine: Integer; + + function GetSizeOfGroup(const StartingIndex: Integer): Integer; + var + I: Integer; + begin + Result := 0; + for I := StartingIndex to FViewerCount-1 do begin + if not NewPositions[I].Show then + Continue; + if tbisSeparator in FViewers[I].Item.ItemStyle then + Break; + with NewPositions[I] do begin + if AOrientation <> tbvoVertical then + Inc(Result, BoundsRect.Right) + else + Inc(Result, BoundsRect.Bottom); + end; + end; + end; + + procedure Mirror; + { Reverses the horizontal ordering (i.e. first item becomes last) } + var + I, NewRight: Integer; + begin + for I := 0 to FViewerCount-1 do + with NewPositions[I] do + if Show then begin + NewRight := TotalSize.X - BoundsRect.Left; + BoundsRect.Left := TotalSize.X - BoundsRect.Right; + BoundsRect.Right := NewRight; + end; + end; + + procedure HandleMaxHeight; + { Decreases, if necessary, the height of the view to FMaxHeight, and adjusts + the visibility of the scroll arrows } + var + MaxOffset, I, MaxTop, MaxBottom: Integer; + begin + FShowUpArrow := False; + FShowDownArrow := False; + if (FMaxHeight > 0) and (TotalSize.Y > FMaxHeight) then begin + MaxOffset := TotalSize.Y - FMaxHeight; + if FScrollOffset > MaxOffset then + FScrollOffset := MaxOffset; + if FScrollOffset < 0 then + FScrollOffset := 0; + FShowUpArrow := (FScrollOffset > 0); + FShowDownArrow := (FScrollOffset < MaxOffset); + MaxTop := 0; + if FShowUpArrow then + MaxTop := tbMenuScrollArrowHeight; + MaxBottom := FMaxHeight; + if FShowDownArrow then + Dec(MaxBottom, tbMenuScrollArrowHeight); + for I := 0 to FViewerCount-1 do begin + if not IsRectEmpty(NewPositions[I].BoundsRect) then begin + OffsetRect(NewPositions[I].BoundsRect, 0, -FScrollOffset); + if NewPositions[I].Show and + ((NewPositions[I].BoundsRect.Top < MaxTop) or + (NewPositions[I].BoundsRect.Bottom > MaxBottom)) then begin + NewPositions[I].Show := False; + NewPositions[I].Clipped := True; + end; + end; + end; + TotalSize.Y := FMaxHeight; + end + else + FScrollOffset := 0; + end; + + procedure FinalizeLine(const LineEnd: Integer; const LastLine: Boolean); + var + I, RightAlignStart: Integer; + Item: TTBCustomItem; + IsButton: Boolean; + Pos: PTempPosition; + Z: Integer; + begin + if LineStart <> -1 then begin + if DidWrap and (FChevronParentView = nil) then begin + { When wrapping on a docked toolbar, extend TotalSize.X/Y to + AWrapOffset so that the toolbar always fills the whole row } + if (AOrientation = tbvoHorizontal) and (TotalSize.X < AWrapOffset) then + TotalSize.X := AWrapOffset + else if (AOrientation = tbvoVertical) and (TotalSize.Y < AWrapOffset) then + TotalSize.Y := AWrapOffset; + end; + RightAlignStart := -1; + for I := LineStart to LineEnd do begin + Pos := @NewPositions[I]; + if not Pos.Show then + Continue; + Item := FViewers[I].Item; + if (RightAlignStart < 0) and (tbisRightAlign in Item.ItemStyle) then + RightAlignStart := I; + IsButton := FIsToolbar or (tboToolbarSize in Item.FEffectiveOptions); + if FIsToolbar then begin + if LastLine and not DidWrap and (AOrientation <> tbvoFloating) then begin + { In case the toolbar is docked next to a taller/wider toolbar... } + HighestWidthOnLine := TotalSize.X; + HighestHeightOnLine := TotalSize.Y; + end; + { Make separators on toolbars as tall/wide as the tallest/widest item } + if [tbisSeparator, tbisStretch] * Item.ItemStyle <> [] then begin + if AOrientation <> tbvoVertical then + Pos.BoundsRect.Bottom := Pos.BoundsRect.Top + HighestHeightOnLine + else + Pos.BoundsRect.Right := Pos.BoundsRect.Left + HighestWidthOnLine; + end + else begin + { Center the item } + if AOrientation <> tbvoVertical then begin + Z := (HighestHeightOnLine - (Pos.BoundsRect.Bottom - Pos.BoundsRect.Top)) div 2; + Inc(Pos.BoundsRect.Top, Z); + Inc(Pos.BoundsRect.Bottom, Z); + end + else begin + Z := (HighestWidthOnLine - (Pos.BoundsRect.Right - Pos.BoundsRect.Left)) div 2; + Inc(Pos.BoundsRect.Left, Z); + Inc(Pos.BoundsRect.Right, Z); + end; + end; + end + else begin + { Make items in a menu as wide as the widest item } + if not IsButton then begin + with Pos.BoundsRect do Right := Left + HighestWidthOnLine; + end; + end; + end; + if RightAlignStart >= 0 then begin + Z := 0; + for I := LineEnd downto RightAlignStart do begin + Pos := @NewPositions[I]; + if not Pos.Show then + Continue; + if AOrientation <> tbvoVertical then + Z := Min(AWrapOffset, TotalSize.X) - Pos.BoundsRect.Right + else + Z := Min(AWrapOffset, TotalSize.Y) - Pos.BoundsRect.Bottom; + Break; + end; + if Z > 0 then begin + for I := RightAlignStart to LineEnd do begin + Pos := @NewPositions[I]; + if not Pos.Show then + Continue; + if AOrientation <> tbvoVertical then begin + Inc(Pos.BoundsRect.Left, Z); + Inc(Pos.BoundsRect.Right, Z); + end + else begin + Inc(Pos.BoundsRect.Top, Z); + Inc(Pos.BoundsRect.Bottom, Z); + end; + end; + end; + end; + end; + LineStart := -1; + HighestHeightOnLine := 0; + HighestWidthOnLine := 0; + end; + + procedure PositionItem(const CurIndex: Integer; var Pos: TTempPosition); + var + O, X, Y: Integer; + IsLineSep, Vert: Boolean; + begin + if LineStart = -1 then begin + LineStart := CurIndex; + HighestHeightOnLine := 0; + HighestWidthOnLine := 0; + end; + IsLineSep := False; + Vert := (AOrientation = tbvoVertical); + if not Vert then + O := CurX + else + O := CurY; + if (AWrapOffset > 0) and (O > 0) then begin + if not Vert then + Inc(O, Pos.BoundsRect.Right) + else + Inc(O, Pos.BoundsRect.Bottom); + if (tbisSeparator in FViewers[CurIndex].Item.ItemStyle) and + ((GroupSplit and not(tbisNoLineBreak in FViewers[CurIndex].Item.ItemStyle)) + or (O + GetSizeOfGroup(CurIndex+1) > AWrapOffset)) then begin + DidWrap := True; + Inc(AWrappedLines); + if not Vert then begin + CurX := 0; + Inc(CurY, HighestHeightOnLine); + end + else begin + CurY := 0; + Inc(CurX, HighestWidthOnLine); + end; + FinalizeLine(CurIndex-1, False); + LineStart := CurIndex+1; + if not Vert then begin + Pos.BoundsRect.Right := 0; + Pos.BoundsRect.Bottom := tbLineSpacing; + end + else begin + Pos.BoundsRect.Right := tbLineSpacing; + Pos.BoundsRect.Bottom := 0; + end; + Pos.LineSep := True; + IsLineSep := True; + end + else if O > AWrapOffset then begin + { proceed to next row } + DidWrap := True; + Inc(AWrappedLines); + if not Vert then begin + CurX := LeftX; + Inc(CurY, HighestHeightOnLine); + end + else begin + CurY := TopY; + Inc(CurX, HighestWidthOnLine); + end; + GroupSplit := True; + FinalizeLine(CurIndex-1, False); + LineStart := CurIndex; + end; + end; + if Pos.BoundsRect.Bottom > HighestHeightOnLine then + HighestHeightOnLine := Pos.BoundsRect.Bottom; + if Pos.BoundsRect.Right > HighestWidthOnLine then + HighestWidthOnLine := Pos.BoundsRect.Right; + X := CurX; + Y := CurY; + if X < 0 then X := 0; + if Y < 0 then Y := 0; + OffsetRect(Pos.BoundsRect, X, Y); + if IsLineSep then begin + if not Vert then begin + CurX := LeftX; + Inc(CurY, tbLineSpacing); + end + else begin + CurY := TopY; + Inc(CurX, tbLineSpacing); + end; + GroupSplit := False; + end; + end; + +var + SaveOrientation: TTBViewOrientation; + ChevronItem: TTBCustomItem; + CalcCanvas: TCanvas; + LastWasSep, LastWasButton, IsButton, IsControl: Boolean; + Item: TTBCustomItem; + Ctl: TControl; + ChangedBold: Boolean; + HighestSameWidthViewerWidth, Total, J, TotalVisibleItems: Integer; + IsFirst: Boolean; + Viewer: TTBItemViewer; + UseChevron, NonControlsOffEdge, TempViewerCreated: Boolean; + Margins: TRect; +label 1; +begin + SaveOrientation := FOrientation; + AWrappedLines := 1; + ChevronItem := GetChevronItem; + NewPositions := nil; + DC := 0; + CalcCanvas := nil; + try + FOrientation := AOrientation; + + CalcCanvas := TCanvas.Create; + DC := GetDC(0); + CalcCanvas.Handle := DC; + CalcCanvas.Font.Assign(GetFont); + + NewPositions := AllocMem(FViewerCount * SizeOf(TTempPosition)); + + { Figure out which items should be shown } + LastWasSep := True; { set to True initially so it won't show leading seps } + for I := 0 to FViewerCount-1 do begin + Item := FViewers[I].Item; + IsControl := Item is TTBControlItem; + with NewPositions[I] do begin + { Show is initially False since AllocMem initializes to zero } + if Item = ChevronItem then + Continue; + if Assigned(FChevronParentView) then begin + if IsControl then + Continue; + FChevronParentView.ValidatePositions; + J := I + FChevronParentView.FInternalViewersAtFront; + if J < FChevronParentView.FViewerCount then + { range check just in case } + Viewer := FChevronParentView.FViewers[J] + else + Viewer := nil; + if (Viewer = nil) or (not Viewer.OffEdge and not(tbisSeparator in Item.ItemStyle)) then + Continue; + end; + if not IsControl then begin + if not(tbisEmbeddedGroup in Item.ItemStyle) or FCustomizing then begin + Show := Item.Visible; + { Don't display two consecutive separators } + if Show then begin + if (tbisSeparator in Item.ItemStyle) and LastWasSep then + Show := False; + LastWasSep := tbisSeparator in Item.ItemStyle; + end; + end; + end + else begin + { Controls can only be rendered on a single Parent, so only + include the control if its parent is currently equal to + FWindow } + Ctl := TTBControlItem(Item).FControl; + if Assigned(Ctl) and Assigned(FWindow) and (Ctl.Parent = FWindow) and + (Ctl.Visible or (csDesigning in Ctl.ComponentState)) then begin + Show := True; + LastWasSep := False; + end; + end; + end; + end; + + { Hide any trailing separators, so that they aren't included in the + base size } + for I := FViewerCount-1 downto 0 do begin + with NewPositions[I] do + if Show then begin + if not(tbisSeparator in FViewers[I].Item.ItemStyle) then + Break; + Show := False; + end; + end; + + { Calculate sizes of all the items } + HighestSameWidthViewerWidth := 0; + for I := 0 to FViewerCount-1 do begin + Item := FViewers[I].Item; + IsControl := Item is TTBControlItem; + with NewPositions[I] do begin + { BoundsRect is currently empty since AllocMem initializes to zero } + if not Show then + Continue; + if not IsControl then begin + ChangedBold := False; + if tboDefault in Item.EffectiveOptions then + with CalcCanvas.Font do + if not(fsBold in Style) then begin + ChangedBold := True; + Style := Style + [fsBold]; + end; + Viewer := FViewers[I]; + TempViewerCreated := False; + if Item.NeedToRecreateViewer(Viewer) then begin + if CanMoveControls then begin + RecreateItemViewer(I); + Viewer := FViewers[I]; + end + else begin + Viewer := Item.GetItemViewerClass(Self).Create(Self, Item, 0); + TempViewerCreated := True; + end; + end; + try + Viewer.CalcSize(CalcCanvas, BoundsRect.Right, BoundsRect.Bottom); + if Viewer.UsesSameWidth then begin + SameWidth := True; + if (BoundsRect.Right > HighestSameWidthViewerWidth) then + HighestSameWidthViewerWidth := BoundsRect.Right; + end; + finally + if TempViewerCreated then + Viewer.Free; + end; + if ChangedBold then + with CalcCanvas.Font do + Style := Style - [fsBold]; + end + else begin + Ctl := TTBControlItem(Item).FControl; + BoundsRect.Right := Ctl.Width; + BoundsRect.Bottom := Ctl.Height; + end; + end; + end; + + { Increase widths of SameWidth items if necessary. Also calculate + ABaseSize.X (or Y). } + ABaseSize.X := 0; + ABaseSize.Y := 0; + for I := 0 to FViewerCount-1 do begin + with NewPositions[I] do begin + if SameWidth and (BoundsRect.Right < HighestSameWidthViewerWidth) then + BoundsRect.Right := HighestSameWidthViewerWidth; + if AOrientation <> tbvoVertical then + Inc(ABaseSize.X, BoundsRect.Right) + else + Inc(ABaseSize.Y, BoundsRect.Bottom); + end; + end; + + { Hide partially visible items, mark them as 'OffEdge' } + if AOrientation <> tbvoVertical then + Total := ABaseSize.X + else + Total := ABaseSize.Y; + NonControlsOffEdge := False; + UseChevron := Assigned(ChevronItem) and (AChevronOffset > 0) and + (Total > AChevronOffset); + if UseChevron then begin + Dec(AChevronOffset, AChevronSize); + while Total > AChevronOffset do begin + { Count number of items. Stop loop if <= 1 } + TotalVisibleItems := 0; + for I := FViewerCount-1 downto 0 do begin + if NewPositions[I].Show and not(tbisSeparator in FViewers[I].Item.ItemStyle) then + Inc(TotalVisibleItems); + end; + if TotalVisibleItems <= 1 then + Break; + { Hide any trailing separators } + for I := FViewerCount-1 downto 0 do begin + with NewPositions[I] do + if Show then begin + if not(tbisSeparator in FViewers[I].Item.ItemStyle) then + Break; + Show := False; + if AOrientation <> tbvoVertical then + Dec(Total, BoundsRect.Right) + else + Dec(Total, BoundsRect.Bottom); + goto 1; + end; + end; + { Find an item to hide } + if Assigned(FPriorityList) then + I := FPriorityList.Count-1 + else + I := FViewerCount-1; + while I >= 0 do begin + if Assigned(FPriorityList) then begin + Viewer := FPriorityList[I]; + J := Viewer.Index; + end + else begin + Viewer := FViewers[I]; + J := I; + end; + if NewPositions[J].Show and not(tbisSeparator in Viewer.Item.ItemStyle) then begin + NewPositions[J].Show := False; + NewPositions[J].OffEdge := True; + if AOrientation <> tbvoVertical then + Dec(Total, NewPositions[J].BoundsRect.Right) + else + Dec(Total, NewPositions[J].BoundsRect.Bottom); + if not NonControlsOffEdge and not(Viewer.Item is TTBControlItem) then + NonControlsOffEdge := True; + goto 1; + end; + Dec(I); + end; + Break; { prevent endless loop } + 1: + { Don't show two consecutive separators } + LastWasSep := True; { set to True initially so it won't show leading seps } + for J := 0 to FViewerCount-1 do begin + Item := FViewers[J].Item; + with NewPositions[J] do begin + if Show then begin + if (tbisSeparator in Item.ItemStyle) and LastWasSep then begin + Show := False; + if AOrientation <> tbvoVertical then + Dec(Total, BoundsRect.Right) + else + Dec(Total, BoundsRect.Bottom); + end; + LastWasSep := tbisSeparator in Item.ItemStyle; + end; + end; + end; + end; + end; + + { Hide any trailing separators after items were hidden } + for I := FViewerCount-1 downto 0 do begin + with NewPositions[I] do + if Show then begin + if not(tbisSeparator in FViewers[I].Item.ItemStyle) then + Break; + Show := False; + end; + end; + + { Set the ABaseSize.Y (or X) *after* items were hidden } + for I := 0 to FViewerCount-1 do begin + with NewPositions[I] do + if Show then begin + if AOrientation <> tbvoVertical then begin + if BoundsRect.Bottom > ABaseSize.Y then + ABaseSize.Y := BoundsRect.Bottom; + end + else begin + if BoundsRect.Right > ABaseSize.X then + ABaseSize.X := BoundsRect.Right; + end; + end; + end; + + { On menus, set all non-separator items to be as tall as the tallest item } + {if not FIsToolbar then begin + J := 0; + for I := 0 to FViewerCount-1 do begin + Item := FViewers[I].Item; + with NewPositions[I] do + if Show and not(tbisSeparator in Item.ItemStyle) and + not(tboToolbarSize in Item.FEffectiveOptions) and + (BoundsRect.Bottom - BoundsRect.Top > J) then + J := BoundsRect.Bottom - BoundsRect.Top; + end; + for I := 0 to FViewerCount-1 do begin + Item := FViewers[I].Item; + with NewPositions[I] do + if Show and not(tbisSeparator in Item.ItemStyle) and + not(tboToolbarSize in Item.FEffectiveOptions) then + BoundsRect.Bottom := BoundsRect.Top + J; + end; + end;} + + { Calculate the position of the items } + GetMargins(AOrientation, Margins); + LeftX := Margins.Left; + TopY := Margins.Top; + if AWrapOffset > 0 then begin + Dec(AWrapOffset, Margins.Right); + if AWrapOffset < 1 then AWrapOffset := 1; + end; + CurX := LeftX; + CurY := TopY; + GroupSplit := False; + DidWrap := False; + LastWasButton := FIsToolbar; + LineStart := -1; + for I := 0 to FViewerCount-1 do begin + Item := FViewers[I].Item; + with NewPositions[I] do begin + if not Show then + Continue; + IsButton := FIsToolbar or (tboToolbarSize in Item.FEffectiveOptions); + if LastWasButton and not IsButton then begin + { On a menu, if last item was a button and the current item isn't, + proceed to next row } + CurX := LeftX; + CurY := TotalSize.Y; + end; + LastWasButton := IsButton; + PositionItem(I, NewPositions[I]); + if IsButton and (AOrientation <> tbvoVertical) then + Inc(CurX, BoundsRect.Right - BoundsRect.Left) + else + Inc(CurY, BoundsRect.Bottom - BoundsRect.Top); + if BoundsRect.Right > TotalSize.X then + TotalSize.X := BoundsRect.Right; + if BoundsRect.Bottom > TotalSize.Y then + TotalSize.Y := BoundsRect.Bottom; + end; + end; + if FViewerCount <> 0 then + FinalizeLine(FViewerCount-1, True); + Inc(TotalSize.X, Margins.Right); + Inc(TotalSize.Y, Margins.Bottom); + if AOrientation = tbvoVertical then + Mirror; + HandleMaxHeight; + if CanMoveControls then begin + for I := 0 to FViewerCount-1 do begin + Item := FViewers[I].Item; + if Item is TTBControlItem then begin + if NewPositions[I].Show then begin + Ctl := TTBControlItem(Item).FControl; + if not EqualRect(NewPositions[I].BoundsRect, Ctl.BoundsRect) then + Ctl.BoundsRect := NewPositions[I].BoundsRect; + end + else if NewPositions[I].OffEdge or NewPositions[I].Clipped then begin + { Simulate hiding of OddEdge controls by literally moving them + off the edge. Do the same for Clipped controls. } + Ctl := TTBControlItem(Item).FControl; + Ctl.SetBounds(FWindow.ClientWidth, FWindow.ClientHeight, + Ctl.Width, Ctl.Height); + end; + end; + end; + end; + { Set size of line separators } + if FIsToolbar then + for I := 0 to FViewerCount-1 do begin + Item := FViewers[I].Item; + with NewPositions[I] do + if Show and (tbisSeparator in Item.ItemStyle) and + LineSep then begin + if AOrientation <> tbvoVertical then + BoundsRect.Right := TotalSize.X + else + BoundsRect.Bottom := TotalSize.Y; + end; + end; + + { Position the chevron item } + if UseChevron then begin + if CanMoveControls then + ChevronItem.Enabled := NonControlsOffEdge; + NewPositions[FViewerCount-1].Show := True; + I := AChevronOffset; + if AOrientation <> tbvoVertical then begin + if I < TotalSize.X then + I := TotalSize.X; + NewPositions[FViewerCount-1].BoundsRect := Bounds(I, 0, + AChevronSize, TotalSize.Y); + end + else begin + if I < TotalSize.Y then + I := TotalSize.Y; + NewPositions[FViewerCount-1].BoundsRect := Bounds(0, I, + TotalSize.X, AChevronSize); + end; + end; + + { Commit changes } + Result := False; + if CanMoveControls then begin + for I := 0 to FViewerCount-1 do begin + if not Result and + (not EqualRect(FViewers[I].BoundsRect, NewPositions[I].BoundsRect) or + (FViewers[I].Show <> NewPositions[I].Show) or + (tbisLineSep in FViewers[I].State <> NewPositions[I].LineSep)) then + Result := True; + FViewers[I].FBoundsRect := NewPositions[I].BoundsRect; + FViewers[I].FShow := NewPositions[I].Show; + FViewers[I].FOffEdge := NewPositions[I].OffEdge; + FViewers[I].FClipped := NewPositions[I].Clipped; + if NewPositions[I].LineSep then + Include(FViewers[I].State, tbisLineSep) + else + Exclude(FViewers[I].State, tbisLineSep); + end; + end; + finally + FOrientation := SaveOrientation; + if Assigned(CalcCanvas) then + CalcCanvas.Handle := 0; + if DC <> 0 then ReleaseDC(0, DC); + CalcCanvas.Free; + FreeMem(NewPositions); + end; + if (ABaseSize.X = 0) or (ABaseSize.Y = 0) then begin + { If there are no visible items... } + {}{scale this?} + ABaseSize.X := 23; + ABaseSize.Y := 22; + if TotalSize.X < 23 then TotalSize.X := 23; + if TotalSize.Y < 22 then TotalSize.Y := 22; + end; +end; + +procedure TTBView.DoUpdatePositions(var ASize: TPoint); +{ This is called by UpdatePositions } +var + Bmp: TBitmap; + CtlCanvas: TControlCanvas; + WrappedLines: Integer; +begin + { Don't call InvalidatePositions before CalculatePositions so that + endless recursion doesn't happen if an item's CalcSize uses a method that + calls ValidatePositions } + if not CalculatePositions(True, FOrientation, FWrapOffset, FChevronOffset, + FChevronSize, FBaseSize, ASize, WrappedLines) then begin + { If the new positions are identical to the previous ones, continue using + the previous ones, and don't redraw } + FValidated := True; + { Just because the positions are the same doesn't mean the size hasn't + changed. (If a shrunken toolbar moves between docks, the positions of + the non-OffEdge items may be the same on the new dock as on the old + dock.) } + AutoSize(ASize.X, ASize.Y); + end + else begin + if not(csDesigning in ComponentState) then begin + FValidated := True; + { Need to call ValidateRect before AutoSize, otherwise Windows will + erase the client area during a resize } + if FWindow.HandleAllocated then + ValidateRect(FWindow.Handle, nil); + AutoSize(ASize.X, ASize.Y); + if Assigned(FWindow) and FWindow.HandleAllocated and + IsWindowVisible(FWindow.Handle) and + (FWindow.ClientWidth > 0) and (FWindow.ClientHeight > 0) then begin + CtlCanvas := nil; + Bmp := TBitmap.Create; + try + CtlCanvas := TControlCanvas.Create; + CtlCanvas.Control := FWindow; + Bmp.Width := FWindow.ClientWidth; + Bmp.Height := FWindow.ClientHeight; + + SendMessage(FWindow.Handle, WM_ERASEBKGND, WPARAM(Bmp.Canvas.Handle), 0); + SendMessage(FWindow.Handle, WM_PAINT, WPARAM(Bmp.Canvas.Handle), 0); + BitBlt(CtlCanvas.Handle, 0, 0, Bmp.Width, Bmp.Height, + Bmp.Canvas.Handle, 0, 0, SRCCOPY); + ValidateRect(FWindow.Handle, nil); + finally + CtlCanvas.Free; + Bmp.Free; + end; + end; + end + else begin + { Delphi's handling of canvases is different at design time -- child + controls aren't clipped from a parent control's canvas, so the above + offscreen rendering code doesn't work right at design-time } + InvalidatePositions; + FValidated := True; + AutoSize(ASize.X, ASize.Y); + end; + end; +end; + +function TTBView.UpdatePositions: TPoint; +{ Called whenever the size or orientation of a view changes. When items are + added or removed from the view, InvalidatePositions must be called instead, + otherwise the view may not be redrawn properly. } +begin + Result.X := 0; + Result.Y := 0; + DoUpdatePositions(Result); +end; + +procedure TTBView.AutoSize(AWidth, AHeight: Integer); +begin +end; + +function TTBView.GetChevronItem: TTBCustomItem; +begin + Result := nil; +end; + +procedure TTBView.GetMargins(AOrientation: TTBViewOrientation; + var Margins: TRect); +begin + if AOrientation = tbvoFloating then begin + Margins.Left := 4; + Margins.Top := 2; + Margins.Right := 4; + Margins.Bottom := 1; + end + else begin + Margins.Left := 0; + Margins.Top := 0; + Margins.Right := 0; + Margins.Bottom := 0; + end; +end; + +function TTBView.GetMDIButtonsItem: TTBCustomItem; +begin + Result := nil; +end; + +function TTBView.GetMDISystemMenuItem: TTBCustomItem; +begin + Result := nil; +end; + +function TTBView.GetFont: TFont; +begin + if Assigned(ToolbarFont) then + Result := ToolbarFont + else begin + { ToolbarFont is destroyed during unit finalization, but in rare cases + this method may end up being called from ValidatePositions *after* + unit finalization if Application.Run is never called; see the + "EConvertError" newsgroup thread. We can't return nil because that would + cause an exception in the calling function, so just return the window + font. It's not the *right* font, but it shouldn't matter since the app + is exiting anyway. } + Result := TControlAccess(FWindow).Font; + end; +end; + +procedure TTBView.DrawItem(Viewer: TTBItemViewer; DrawTo: TCanvas; + Offscreen: Boolean); +const + COLOR_MENUHILIGHT = 29; + clMenuHighlight = TColor(COLOR_MENUHILIGHT or $80000000); +var + Bmp: TBitmap; + DrawToDC, BmpDC: HDC; + DrawCanvas: TCanvas; + R1, R2, R3: TRect; + IsOpen, IsSelected, IsPushed: Boolean; + ToolbarStyle: Boolean; + UseDisabledShadow: Boolean; + SaveIndex, SaveIndex2: Integer; + BkColor: TColor; +begin + ValidatePositions; + + if tbisInvalidated in Viewer.State then begin + Offscreen := True; + Exclude(Viewer.State, tbisInvalidated); + end; + + R1 := Viewer.BoundsRect; + if not Viewer.Show or IsRectEmpty(R1) or (Viewer.Item is TTBControlItem) then + Exit; + R2 := R1; + OffsetRect(R2, -R2.Left, -R2.Top); + + IsOpen := FOpenViewer = Viewer; + IsSelected := (FSelected = Viewer); + IsPushed := IsSelected and (IsOpen or (FMouseOverSelected and FCapture)); + ToolbarStyle := Viewer.IsToolbarStyle; + + DrawToDC := DrawTo.Handle; + Bmp := nil; + { Must deselect any currently selected handles before calling SaveDC, because + if they are left selected and DeleteObject gets called on them after the + SaveDC call, it will fail on Win9x/Me, and thus leak GDI resources. } + DrawTo.Refresh; + SaveIndex := SaveDC(DrawToDC); + try + IntersectClipRect(DrawToDC, R1.Left, R1.Top, R1.Right, R1.Bottom); + GetClipBox(DrawToDC, R3); + if IsRectEmpty(R3) then + Exit; + + if not Offscreen then begin + MoveWindowOrg(DrawToDC, R1.Left, R1.Top); + { Tweak the brush origin so that the checked background drawn behind + checked items always looks the same regardless of whether the item + is positioned on an even or odd Left or Top coordinate. } + SetBrushOrgEx(DrawToDC, R1.Left and 1, R1.Top and 1, nil); + DrawCanvas := DrawTo; + end + else begin + Bmp := TBitmap.Create; + Bmp.Width := R2.Right; + Bmp.Height := R2.Bottom; + DrawCanvas := Bmp.Canvas; + BmpDC := DrawCanvas.Handle; + SaveIndex2 := SaveDC(BmpDC); + SetWindowOrgEx(BmpDC, R1.Left, R1.Top, nil); + FWindow.Perform(WM_ERASEBKGND, WPARAM(BmpDC), 0); + RestoreDC(BmpDC, SaveIndex2); + end; + + { Initialize brush } + if not ToolbarStyle and IsSelected then begin + {$IFNDEF TB2K_USE_STRICT_O2K_MENU_STYLE} + if AreFlatMenusEnabled then + { Windows XP uses a different fill color for selected menu items when + flat menus are enabled } + DrawCanvas.Brush.Color := clMenuHighlight + else + {$ENDIF} + DrawCanvas.Brush.Color := clHighlight; + end + else + DrawCanvas.Brush.Style := bsClear; + + { Initialize font } + DrawCanvas.Font.Assign(GetFont); + if Viewer.Item.Enabled then begin + if not ToolbarStyle and IsSelected then + DrawCanvas.Font.Color := clHighlightText + else begin + if ToolbarStyle then + DrawCanvas.Font.Color := clBtnText + else + DrawCanvas.Font.Color := tbMenuTextColor; + end; + UseDisabledShadow := False; + end + else begin + DrawCanvas.Font.Color := clGrayText; + { Use the disabled shadow if either: + 1. The item is a toolbar-style item. + 2. The item is not selected, and the background color equals the + button-face color. + 3. The gray-text color is the same as the background color. + Note: Windows actually uses dithered text in this case. } + BkColor := ColorToRGB(TControlAccess(FWindow).Color); + UseDisabledShadow := ToolbarStyle or + (not IsSelected and (BkColor = ColorToRGB(clBtnFace))) or + (ColorToRGB(clGrayText) = BkColor); + end; + + Viewer.Paint(DrawCanvas, R2, IsSelected, IsPushed, UseDisabledShadow); + + if Offscreen then + BitBlt(DrawToDC, R1.Left, R1.Top, Bmp.Width, Bmp.Height, DrawCanvas.Handle, + 0, 0, SRCCOPY); + finally + DrawTo.Refresh; { must do this before a RestoreDC } + RestoreDC(DrawToDC, SaveIndex); + Bmp.Free; + end; +end; + +procedure TTBView.DrawSubitems(ACanvas: TCanvas); +var + I: Integer; +begin + for I := 0 to FViewerCount-1 do begin + if (vsDrawInOrder in FState) or (FViewers[I] <> FSelected) then + DrawItem(FViewers[I], ACanvas, False); + end; + if not(vsDrawInOrder in FState) and Assigned(FSelected) then + DrawItem(FSelected, ACanvas, False); + + Exclude(FState, vsDrawInOrder); +end; + +procedure TTBView.Invalidate(AViewer: TTBItemViewer); +begin + if not FValidated or not Assigned(FWindow) or not FWindow.HandleAllocated then + Exit; + if AViewer.Show and not IsRectEmpty(AViewer.BoundsRect) and + not(AViewer.Item is TTBControlItem) then begin + Include(AViewer.State, tbisInvalidated); + InvalidateRect(FWindow.Handle, @AViewer.BoundsRect, False); + end; +end; + +procedure TTBView.SetAccelsVisibility(AShowAccels: Boolean); +var + I: Integer; + Viewer: TTBItemViewer; +begin + { Always show accels when keyboard cues are enabled } + AShowAccels := AShowAccels or not(vsUseHiddenAccels in FStyle) or + AreKeyboardCuesEnabled; + if AShowAccels <> (vsShowAccels in FState) then begin + if AShowAccels then + Include(FState, vsShowAccels) + else + Exclude(FState, vsShowAccels); + if Assigned(FWindow) and FWindow.HandleAllocated and + IsWindowVisible(FWindow.Handle) then + { ^ the visibility check is just an optimization } + for I := 0 to FViewerCount-1 do begin + Viewer := FViewers[I]; + if Viewer.CaptionShown and + (FindAccelChar(Viewer.GetCaptionText) <> #0) then + Invalidate(Viewer); + end; + end; +end; + +function TTBView.FirstSelectable: TTBItemViewer; +var + FirstViewer: TTBItemViewer; +begin + Result := NextSelectable(nil, True); + if Assigned(Result) then begin + FirstViewer := Result; + while tbisDontSelectFirst in Result.Item.ItemStyle do begin + Result := NextSelectable(Result, True); + if Result = FirstViewer then + { don't loop endlessly if all items have the tbisDontSelectFirst style } + Break; + end; + end; +end; + +function TTBView.NextSelectable(CurViewer: TTBItemViewer; + GoForward: Boolean): TTBItemViewer; +var + I, J: Integer; +begin + ValidatePositions; + Result := nil; + if FViewerCount = 0 then Exit; + J := -1; + I := IndexOf(CurViewer); + while True do begin + if GoForward then begin + Inc(I); + if I >= FViewerCount then I := 0; + end + else begin + Dec(I); + if I < 0 then I := FViewerCount-1; + end; + if J = -1 then + J := I + else + if I = J then + Exit; + if (FViewers[I].Show or FViewers[I].Clipped) and FViewers[I].Item.Visible and + (tbisSelectable in FViewers[I].Item.ItemStyle) then + Break; + end; + Result := FViewers[I]; +end; + +function TTBView.NextSelectableWithAccel(CurViewer: TTBItemViewer; + Key: Char; RequirePrimaryAccel: Boolean; var IsOnlyItemWithAccel: Boolean): TTBItemViewer; + + function IsAccelItem(const Index: Integer; + const Primary, EnabledItems: Boolean): Boolean; + var + S: String; + LastAccel: Char; + Viewer: TTBItemViewer; + Item: TTBCustomItem; + begin + Result := False; + Viewer := FViewers[Index]; + Item := Viewer.Item; + if (Viewer.Show or Viewer.Clipped) and (tbisSelectable in Item.ItemStyle) and + (Item.Enabled = EnabledItems) and + Item.Visible and Viewer.CaptionShown then begin + S := Viewer.GetCaptionText; + if S <> '' then begin + LastAccel := FindAccelChar(S); + if Primary then begin + if LastAccel <> #0 then + Result := AnsiCompareText(LastAccel, Key) = 0; + end + else + if (LastAccel = #0) and (Key <> ' ') then + Result := AnsiCompareText(S[1], Key) = 0; + end; + end; + end; + + function FindAccel(I: Integer; + const Primary, EnabledItems: Boolean): Integer; + var + J: Integer; + begin + Result := -1; + J := -1; + while True do begin + Inc(I); + if I >= FViewerCount then I := 0; + if J = -1 then + J := I + else + if I = J then + Break; + if IsAccelItem(I, Primary, EnabledItems) then begin + Result := I; + Break; + end; + end; + end; + +var + Start, I: Integer; + Primary, EnabledItems: Boolean; +begin + ValidatePositions; + Result := nil; + IsOnlyItemWithAccel := False; + if FViewerCount = 0 then Exit; + + Start := IndexOf(CurViewer); + for Primary := True downto False do + if not RequirePrimaryAccel or Primary then + for EnabledItems := True downto False do begin + I := FindAccel(Start, Primary, EnabledItems); + if I <> -1 then begin + Result := FViewers[I]; + IsOnlyItemWithAccel := not EnabledItems or + (FindAccel(I, Primary, EnabledItems) = I); + Exit; + end; + end; +end; + +procedure TTBView.EnterToolbarLoop(Options: TTBEnterToolbarLoopOptions); +var + ModalHandler: TTBModalHandler; + P: TPoint; +begin + if vsModal in FState then Exit; + ModalHandler := TTBModalHandler.Create(FWindow.Handle); + try + { remove all states except... } + FState := FState * [vsShowAccels]; + try + Include(FState, vsModal); + { Must ensure that DoneAction is reset to tbdaNone *before* calling + NotifyFocusEvent so that the IsModalEnding call it makes won't return + True } + FDoneActionData.DoneAction := tbdaNone; + { Now that the vsModal state has been added, send an MSAA focus event } + if Assigned(Selected) then + NotifyFocusEvent; + ModalHandler.Loop(Self, tbetMouseDown in Options, + tbetExecuteSelected in Options, tbetFromMSAA in Options, False); + finally + { Remove vsModal state from the root view before any TTBView.Destroy + methods get called (as a result of the CloseChildPopups call below), + so that NotifyFocusEvent becomes a no-op } + Exclude(FState, vsModal); + StopAllTimers; + CloseChildPopups; + GetCursorPos(P); + UpdateSelection(@P, True); + end; + finally + ModalHandler.Free; + end; + SetAccelsVisibility(False); + Selected := nil; + // caused flicker: FWindow.Update; + ProcessDoneAction(FDoneActionData, False); +end; + +procedure TTBView.SetCustomizing(Value: Boolean); +begin + if FCustomizing <> Value then begin + FCustomizing := Value; + RecreateAllViewers; + end; +end; + +procedure TTBView.BeginUpdate; +begin + Inc(FUpdating); +end; + +procedure TTBView.EndUpdate; +begin + Dec(FUpdating); + if FUpdating = 0 then + TryValidatePositions; +end; + +procedure TTBView.GetOffEdgeControlList(const List: TList); +var + I: Integer; + Item: TTBCustomItem; +begin + for I := 0 to FViewerCount-1 do begin + Item := FViewers[I].Item; + if (Item is TTBControlItem) and FViewers[I].OffEdge and + (TTBControlItem(Item).FControl is TWinControl) then + List.Add(TTBControlItem(Item).FControl); + end; +end; + +procedure TTBView.SetCapture; +begin + FCapture := True; +end; + +procedure TTBView.CancelCapture; +begin + if FCapture then begin + FCapture := False; + LastPos.X := Low(LastPos.X); + if Assigned(FSelected) then + FSelected.LosingCapture; + end; +end; + +procedure TTBView.KeyDown(var Key: Word; Shift: TShiftState); + + procedure SelNextItem(const ParentView: TTBView; const GoForward: Boolean); + begin + ParentView.Selected := ParentView.NextSelectable(ParentView.FSelected, + GoForward); + ParentView.ScrollSelectedIntoView; + end; + + procedure HelpKey; + var + V: TTBView; + ContextID: Integer; + begin + ContextID := 0; + V := Self; + while Assigned(V) do begin + if Assigned(V.FSelected) then begin + ContextID := V.FSelected.Item.HelpContext; + if ContextID <> 0 then Break; + end; + V := V.FParentView; + end; + if ContextID <> 0 then + EndModalWithHelp(ContextID); + end; + +var + ParentTBView: TTBView; +begin + ParentTBView := GetParentToolbarView; + case Key of + VK_TAB: begin + SelNextItem(Self, GetKeyState(VK_SHIFT) >= 0); + end; + VK_RETURN: begin + ExecuteSelected(True); + end; + VK_MENU, VK_F10: begin + EndModal; + end; + VK_ESCAPE: begin + Key := 0; + if FParentView = nil then + EndModal + else + FParentView.CancelChildPopups; + end; + VK_LEFT, VK_RIGHT: begin + if (Self = ParentTBView) and (Orientation = tbvoVertical) then + OpenChildPopup(True) + else if Key = VK_LEFT then begin + if Assigned(ParentTBView) and (ParentTBView.Orientation <> tbvoVertical) then begin + if (Self = ParentTBView) or + (FParentView = ParentTBView) then + SelNextItem(ParentTBView, False) + else + FParentView.CloseChildPopups; + end + else begin + if Assigned(FParentView) then + FParentView.CancelChildPopups; + end; + end + else begin + if ((Self = ParentTBView) or not OpenChildPopup(True)) and + (Assigned(ParentTBView) and (ParentTBView.Orientation <> tbvoVertical)) then begin + { If we're on ParentTBView, or if the selected item can't display + a submenu, proceed to next item on ParentTBView } + SelNextItem(ParentTBView, True); + end; + end; + end; + VK_UP, VK_DOWN: begin + if (Self = ParentTBView) and (Orientation <> tbvoVertical) then + OpenChildPopup(True) + else + SelNextItem(Self, Key = VK_DOWN); + end; + VK_HOME, VK_END: begin + Selected := NextSelectable(nil, Key = VK_HOME); + ScrollSelectedIntoView; + end; + VK_F1: HelpKey; + else + Exit; { don't set Key to 0 for unprocessed keys } + end; + Key := 0; +end; + +function TTBView.IsModalEnding: Boolean; +begin + Result := (GetRootView.FDoneActionData.DoneAction <> tbdaNone); +end; + +procedure TTBView.EndModal; +var + RootView: TTBView; +begin + RootView := GetRootView; + RootView.FDoneActionData.DoneAction := tbdaCancel; +end; + +procedure TTBView.EndModalWithClick(AViewer: TTBItemViewer); +var + RootView: TTBView; +begin + RootView := GetRootView; + RootView.FDoneActionData.ClickItem := AViewer.Item; + RootView.FDoneActionData.Sound := AViewer.FView.FIsPopup; + RootView.FDoneActionData.DoneAction := tbdaClickItem; +end; + +procedure TTBView.EndModalWithHelp(AContextID: Integer); +var + RootView: TTBView; +begin + RootView := GetRootView; + RootView.FDoneActionData.ContextID := AContextID; + RootView.FDoneActionData.DoneAction := tbdaHelpContext; +end; + +procedure TTBView.EndModalWithSystemMenu(AWnd: HWND; AKey: Cardinal); +var + RootView: TTBView; +begin + RootView := GetRootView; + RootView.FDoneActionData.Wnd := AWnd; + RootView.FDoneActionData.Key := AKey; + RootView.FDoneActionData.DoneAction := tbdaOpenSystemMenu; +end; + +procedure TTBView.ExecuteSelected(AGivePriority: Boolean); +{ Normally called after an Enter or accelerator key press on the view, this + method 'executes' or opens the selected item. It ends the modal loop, except + when a submenu is opened. } +var + Item: TTBCustomItem; +begin + if Assigned(FSelected) and FSelected.Item.Enabled then begin + Item := FSelected.Item; + if (tbisCombo in Item.ItemStyle) or not OpenChildPopup(True) then begin + if tbisSelectable in Item.ItemStyle then + FSelected.Execute(AGivePriority) + else + EndModal; + end + end + else + EndModal; + Exit; asm db 0,'Toolbar2000 (C) 1998-2005 Jordan Russell',0 end; +end; + +procedure TTBView.Scroll(ADown: Boolean); +var + CurPos, NewPos, I: Integer; +begin + ValidatePositions; + if ADown then begin + NewPos := High(NewPos); + CurPos := FMaxHeight - tbMenuScrollArrowHeight; + for I := 0 to FViewerCount-1 do begin + with FViewers[I] do + if Clipped and not(tbisSeparator in Item.ItemStyle) and + (BoundsRect.Bottom < NewPos) and (BoundsRect.Bottom > CurPos) then + NewPos := BoundsRect.Bottom; + end; + if NewPos = High(NewPos) then + Exit; + Dec(NewPos, FMaxHeight - tbMenuScrollArrowHeight); + end + else begin + NewPos := Low(NewPos); + CurPos := tbMenuScrollArrowHeight; + for I := 0 to FViewerCount-1 do begin + with FViewers[I] do + if Clipped and not(tbisSeparator in Item.ItemStyle) and + (BoundsRect.Top > NewPos) and (BoundsRect.Top < CurPos) then + NewPos := BoundsRect.Top; + end; + if NewPos = Low(NewPos) then + Exit; + Dec(NewPos, tbMenuScrollArrowHeight); + end; + Inc(FScrollOffset, NewPos); + UpdatePositions; +end; + +procedure TTBView.ScrollSelectedIntoView; +begin + ValidatePositions; + if (FSelected = nil) or not FSelected.Clipped then + Exit; + + if FSelected.BoundsRect.Top < tbMenuScrollArrowHeight then begin + Dec(FScrollOffset, tbMenuScrollArrowHeight - FSelected.BoundsRect.Top); + UpdatePositions; + end + else if FSelected.BoundsRect.Bottom > FMaxHeight - tbMenuScrollArrowHeight then begin + Dec(FScrollOffset, (FMaxHeight - tbMenuScrollArrowHeight) - + FSelected.BoundsRect.Bottom); + UpdatePositions; + end; +end; + +procedure TTBView.SetUsePriorityList(Value: Boolean); +begin + if FUsePriorityList <> Value then begin + FUsePriorityList := Value; + RecreateAllViewers; + end; +end; + +function TTBView.GetCaptureWnd: HWND; +begin + Result := GetRootView.FCaptureWnd; +end; + +procedure TTBView.CancelMode; +var + View: TTBView; +begin + EndModal; + + { Hide all parent/child popup windows. Can't actually destroy them using + CloseChildPopups because this method may be called while inside + TTBEditItemViewer's message loop, and it could result in the active + TTBEditItemViewer instance being destroyed (leading to an AV). } + View := Self; + while Assigned(View.FOpenViewerView) do + View := View.FOpenViewerView; + repeat + View.StopAllTimers; + if View.FWindow is TTBPopupWindow then + View.FWindow.Visible := False; + View := View.FParentView; + until View = nil; + + { Note: This doesn't remove the selection from a top-level toolbar item. + Unfortunately, we can't do 'Selected := nil' because it would destroy + child popups and that must'nt happen for the reason stated above. } +end; + +procedure TTBView.SetState(AState: TTBViewState); +begin + FState := AState; +end; + +{ TTBModalHandler } + +const + LSFW_LOCK = 1; + LSFW_UNLOCK = 2; + +var + LockSetForegroundWindowInited: BOOL; + LockSetForegroundWindow: function(uLockCode: UINT): BOOL; stdcall; + +constructor TTBModalHandler.Create(AExistingWnd: HWND); +begin + inherited Create; + if not LockSetForegroundWindowInited then begin + LockSetForegroundWindow := GetProcAddress(GetModuleHandle(user32), + 'LockSetForegroundWindow'); + InterlockedExchange(Integer(LockSetForegroundWindowInited), Ord(True)); + end; + LastPos := SmallPointToPoint(TSmallPoint(GetMessagePos())); + if AExistingWnd <> 0 then + FWnd := AExistingWnd + else begin + FWnd := {$IFDEF JR_D6}Classes.{$ENDIF} AllocateHWnd(WndProc); + FCreatedWnd := True; + end; + if Assigned(LockSetForegroundWindow) then begin + { Like standard menus, don't allow other apps to steal the focus during + our modal loop. This also prevents us from losing activation when + "active window tracking" is enabled and the user moves the mouse over + another application's window. } + LockSetForegroundWindow(LSFW_LOCK); + end; + SetCapture(FWnd); + SetCursor(LoadCursor(0, IDC_ARROW)); + CallNotifyWinEvent(EVENT_SYSTEM_MENUSTART, FWnd, OBJID_CLIENT, CHILDID_SELF); + FInited := True; +end; + +destructor TTBModalHandler.Destroy; +begin + if Assigned(LockSetForegroundWindow) then + LockSetForegroundWindow(LSFW_UNLOCK); + if FWnd <> 0 then begin + if GetCapture = FWnd then + ReleaseCapture; + if FInited then + CallNotifyWinEvent(EVENT_SYSTEM_MENUEND, FWnd, OBJID_CLIENT, CHILDID_SELF); + if FCreatedWnd then + {$IFDEF JR_D6}Classes.{$ENDIF} DeallocateHWnd(FWnd); + end; + inherited; +end; + +procedure TTBModalHandler.WndProc(var Msg: TMessage); +begin + Msg.Result := DefWindowProc(FWnd, Msg.Msg, Msg.WParam, Msg.LParam); + if (Msg.Msg = WM_CANCELMODE) and Assigned(FRootPopup) then begin + try + { We can receive a WM_CANCELMODE message during a modal loop if a dialog + pops up. Respond by hiding menus to make it look like the modal loop + has returned, even though it really hasn't yet. + Note: Similar code in TTBCustomToolbar.WMCancelMode. } + FRootPopup.View.CancelMode; + except + Application.HandleException(Self); + end; + end; +end; + +procedure TTBModalHandler.Loop(const RootView: TTBView; + const AMouseDown, AExecuteSelected, AFromMSAA, TrackRightButton: Boolean); +var + OriginalActiveWindow: HWND; + + function GetActiveView: TTBView; + begin + Result := RootView; + while Assigned(Result.FOpenViewerView) do + Result := Result.FOpenViewerView; + end; + + procedure UpdateAllSelections(const P: TPoint; const AllowNewSelection: Boolean); + var + View, CapView: TTBView; + begin + View := GetActiveView; + + CapView := View; + while Assigned(CapView) and not CapView.FCapture do + CapView := CapView.FParentView; + + while Assigned(View) do begin + if (CapView = nil) or (View = CapView) then + View.UpdateSelection(@P, AllowNewSelection); + View := View.FParentView; + end; + end; + + function GetSelectedViewer(var AView: TTBView; var AViewer: TTBItemViewer): Boolean; + { Returns True if AViewer <> nil. } + var + View: TTBView; + begin + AView := nil; + AViewer := nil; + { Look for a capture item first } + View := RootView; + repeat + if View.FCapture then begin + AView := View; + AViewer := View.FSelected; + Break; + end; + View := View.FOpenViewerView; + until View = nil; + if View = nil then begin + View := RootView; + repeat + if Assigned(View.FSelected) and View.FMouseOverSelected then begin + AView := View; + AViewer := View.FSelected; + Break; + end; + if vsMouseInWindow in View.FState then begin + { ...there is no current selection, but the mouse is still in the + window. This can happen if the mouse is over the non-client area + of the toolbar or popup window, or in an area not containing an + item. } + AView := View; + Break; + end; + View := View.FOpenViewerView; + until View = nil; + end; + Result := Assigned(AViewer); + end; + + function ContinueLoop: Boolean; + begin + { Don't continue if the mouse capture is lost, if a (modeless) top-level + window is shown causing the active window to change, or if EndModal* was + called. } + Result := (GetCapture = FWnd) and (GetActiveWindow = OriginalActiveWindow) + and not RootView.IsModalEnding; + end; + + function SendKeyEvent(const View: TTBView; var Key: Word; + const Shift: TShiftState): Boolean; + begin + Result := True; + if Assigned(View.FSelected) then begin + View.FSelected.KeyDown(Key, Shift); + if RootView.IsModalEnding then + Exit; + end; + if Key <> 0 then begin + View.KeyDown(Key, Shift); + if RootView.IsModalEnding then + Exit; + end; + Result := False; + end; + + procedure DoHintMouseMessage(const Ctl: TControl; const P: TPoint); + var + M: TWMMouseMove; + begin + M.Msg := WM_MOUSEMOVE; + M.Keys := 0; + M.Pos := PointToSmallPoint(P); + Application.HintMouseMessage(Ctl, TMessage(M)); + end; + + procedure MouseMoved; + var + View: TTBView; + Cursor: HCURSOR; + Item: TTBCustomItem; + P: TPoint; + R: TRect; + begin + UpdateAllSelections(LastPos, True); + View := GetActiveView; + Cursor := 0; + if Assigned(View.FSelected) and Assigned(View.FWindow) then begin + Item := View.FSelected.Item; + P := View.FWindow.ScreenToClient(LastPos); + if ((vsAlwaysShowHints in View.FStyle) or + (tboShowHint in Item.FEffectiveOptions)) and not View.FCapture then begin + { Display popup hint for the item. Update is called + first to minimize flicker caused by the hiding & + showing of the hint window. } + View.FWindow.Update; + DoHintMouseMessage(View.FWindow, P); + end + else + Application.CancelHint; + R := View.FSelected.BoundsRect; + Dec(P.X, R.Left); + Dec(P.Y, R.Top); + View.FSelected.GetCursor(P, Cursor); + end + else + Application.CancelHint; + if Cursor = 0 then + Cursor := LoadCursor(0, IDC_ARROW); + SetCursor(Cursor); + end; + + procedure UpdateAppHint; + var + View: TTBView; + begin + View := RootView; + while Assigned(View.FOpenViewerView) and Assigned(View.FOpenViewerView.FSelected) do + View := View.FOpenViewerView; + if Assigned(View.FSelected) then + Application.Hint := GetLongHint(View.FSelected.Item.Hint) + else + Application.Hint := ''; + end; + + procedure HandleTimer(const View: TTBView; const ID: TTBViewTimerID); + begin + case ID of + tiOpen: begin + { Similar to standard menus, always close child popups, even if + Selected = OpenViewer. + Note: CloseChildPopups and OpenChildPopup will stop the tiClose + and tiOpen timers respectively. } + View.CloseChildPopups; + View.OpenChildPopup(False); + end; + tiClose: begin + { Note: CloseChildPopups stops the tiClose timer. } + View.CloseChildPopups; + end; + tiScrollUp: begin + if View.FShowUpArrow then + View.Scroll(False) + else + View.StopTimer(tiScrollUp); + end; + tiScrollDown: begin + if View.FShowDownArrow then + View.Scroll(True) + else + View.StopTimer(tiScrollDown); + end; + end; + end; + +var + MouseDownOnMenu: Boolean; + Msg: TMsg; + P: TPoint; + Ctl: TControl; + View: TTBView; + IsOnlyItemWithAccel: Boolean; + MouseIsDown: Boolean; + Key: Word; + Shift: TShiftState; + Viewer: TTBItemViewer; +begin + FillChar(RootView.FDoneActionData, SizeOf(RootView.FDoneActionData), 0); + RootView.ValidatePositions; + try + try + RootView.FCaptureWnd := FWnd; + MouseDownOnMenu := False; + if AMouseDown then begin + P := RootView.FSelected.ScreenToClient(SmallPointToPoint(TSmallPoint(GetMessagePos()))); + RootView.FSelected.MouseDown([], P.X, P.Y, MouseDownOnMenu); + if RootView.IsModalEnding then + Exit; + MouseDownOnMenu := False; { never set MouseDownOnMenu to True on first click } + end + else if AExecuteSelected then begin + RootView.ExecuteSelected(not AFromMSAA); + if RootView.IsModalEnding then + Exit; + end; + OriginalActiveWindow := GetActiveWindow; + while ContinueLoop do begin + { Examine the next message before popping it out of the queue } + if not PeekMessage(Msg, 0, 0, 0, PM_NOREMOVE) then begin + WaitMessage; + Continue; + end; + case Msg.message of + WM_LBUTTONDOWN, WM_RBUTTONDOWN: begin + P := SmallPointToPoint(TSmallPoint(Msg.lParam)); + Windows.ClientToScreen(Msg.hwnd, P); + Ctl := FindDragTarget(P, True); + { Was the mouse not clicked on a popup, or was it clicked on a + popup that is not a child of RootView? + (The latter can happen when in customization mode, for example, + if the user right-clicks a popup menu being customized and + the context menu is displayed.) } + if not(Ctl is TTBPopupWindow) or + not RootView.ContainsView(TTBPopupWindow(Ctl).View) then begin + { If the root view is a popup, or if the root view is a toolbar + and the user clicked outside the toolbar or in its non-client + area (e.g. on its drag handle), exit } + if RootView.FIsPopup or (Ctl <> RootView.FWindow) or + not PtInRect(RootView.FWindow.ClientRect, RootView.FWindow.ScreenToClient(P)) then + Exit + else + if Msg.message = WM_LBUTTONDOWN then begin + { If the user clicked inside a toolbar on anything but an + item, exit } + UpdateAllSelections(P, True); + if (RootView.FSelected = nil) or not RootView.FMouseOverSelected or + (tbisClicksTransparent in RootView.FSelected.Item.ItemStyle) then + Exit; + end; + end; + end; + end; + { Now pop the message out of the queue } + if not PeekMessage(Msg, 0, Msg.message, Msg.message, PM_REMOVE or PM_NOYIELD) then + Continue; + case Msg.message of + $4D: + { This undocumented message is sent to the focused window when + F1 is pressed. Windows handles it by sending a WM_HELP message + to the same window. We don't want this to happen while a menu + is up, so swallow the message. } + ; + WM_CONTEXTMENU: + { Windows still sends WM_CONTEXTMENU messages for "context menu" + keystrokes even if WM_KEYUP messages are never dispatched, + so it must specifically ignore this message } + ; + WM_KEYFIRST..WM_KEYLAST: begin + Application.CancelHint; + MouseIsDown := (GetKeyState(VK_LBUTTON) < 0) or + (TrackRightButton and (GetKeyState(VK_RBUTTON) < 0)); + case Msg.message of + WM_KEYDOWN, WM_SYSKEYDOWN: + begin + if Msg.wParam = VK_PROCESSKEY then + { Don't let IME process the key } + Msg.wParam := ImmGetVirtualKey(Msg.hwnd); + if not MouseIsDown or (Msg.wParam = VK_F1) then begin + Key := Word(Msg.wParam); + if SendKeyEvent(GetActiveView, Key, + KeyDataToShiftState(Msg.lParam)) then + Exit; + { If it's not handled by a KeyDown method, translate + it into a WM_*CHAR message } + if Key <> 0 then + TranslateMessage(Msg); + end; + end; + WM_CHAR, WM_SYSCHAR: + if not MouseIsDown then begin + View := GetActiveView; + Viewer := View.NextSelectableWithAccel(View.FSelected, + Chr(Msg.WParam), False, IsOnlyItemWithAccel); + if Viewer = nil then begin + if (Msg.WParam in [VK_SPACE, Ord('-')]) and + not RootView.FIsPopup and (View = RootView) and + (GetActiveWindow <> 0) then begin + RootView.EndModalWithSystemMenu(GetActiveWindow, + Msg.WParam); + Exit; + end + else + MessageBeep(0); + end + else begin + View.Selected := Viewer; + View.ScrollSelectedIntoView; + if IsOnlyItemWithAccel then + View.ExecuteSelected(True); + end; + end; + end; + end; + WM_TIMER: + begin + Ctl := FindControl(Msg.hwnd); + if Assigned(Ctl) and (Ctl is TTBPopupWindow) and + (Msg.wParam >= ViewTimerBaseID + Ord(Low(TTBViewTimerID))) and + (Msg.wParam <= ViewTimerBaseID + Ord(High(TTBViewTimerID))) then begin + if Assigned(TTBPopupWindow(Ctl).FView) then + HandleTimer(TTBPopupWindow(Ctl).FView, + TTBViewTimerID(WPARAM(Msg.wParam - ViewTimerBaseID))); + end + else + DispatchMessage(Msg); + end; + $118: ; + { ^ Like standard menus, don't dispatch WM_SYSTIMER messages + (the internal Windows message used for things like caret + blink and list box scrolling). } + WM_MOUSEFIRST..WM_MOUSELAST: + case Msg.message of + WM_MOUSEMOVE: begin + if (Msg.pt.X <> LastPos.X) or (Msg.pt.Y <> LastPos.Y) then begin + LastPos := Msg.pt; + MouseMoved; + end; + if GetSelectedViewer(View, Viewer) then begin + P := Viewer.ScreenToClient(Msg.pt); + Viewer.MouseMove(P.X, P.Y); + end; + end; + WM_MOUSEWHEEL: + if GetSelectedViewer(View, Viewer) then begin + P := Viewer.ScreenToClient(Msg.pt); + Viewer.MouseWheel(Smallint(LongRec(Msg.wParam).Hi), P.X, P.Y); + end; + WM_LBUTTONDOWN, WM_LBUTTONDBLCLK, WM_RBUTTONDOWN: + if (Msg.message <> WM_RBUTTONDOWN) or TrackRightButton then begin + Application.CancelHint; + MouseDownOnMenu := False; + Exclude(RootView.FState, vsIgnoreFirstMouseUp); + UpdateAllSelections(Msg.pt, True); + if GetSelectedViewer(View, Viewer) then begin + if Msg.message <> WM_LBUTTONDBLCLK then + Shift := [] + else + Shift := [ssDouble]; + P := Viewer.ScreenToClient(Msg.pt); + Viewer.MouseDown(Shift, P.X, P.Y, MouseDownOnMenu); + LastPos := SmallPointToPoint(TSmallPoint(GetMessagePos())); + end; + end; + WM_LBUTTONUP, WM_RBUTTONUP: + if (Msg.message = WM_LBUTTONUP) or TrackRightButton then begin + UpdateAllSelections(Msg.pt, False); + { ^ False is used so that when a popup menu is + displayed with the cursor currently inside it, the item + under the cursor won't be accidentally selected when the + user releases the button. The user must move the mouse at + at least one pixel (generating a WM_MOUSEMOVE message), + and then release the button. } + if not GetSelectedViewer(View, Viewer) then begin + { Mouse was not released over any item. Cancel out of the + loop if it's outside all views, or is inside unused + space on a topmost toolbar } + if not Assigned(View) or + ((View = RootView) and RootView.FIsToolbar) then begin + if not(vsIgnoreFirstMouseUp in RootView.FState) then + Exit + else + Exclude(RootView.FState, vsIgnoreFirstMouseUp); + end; + end + else begin + P := Viewer.ScreenToClient(Msg.pt); + Viewer.MouseUp(P.X, P.Y, MouseDownOnMenu); + end; + end; + end; + else + DispatchMessage(Msg); + end; + if not ContinueLoop then + Exit; + if LastPos.X = Low(LastPos.X) then begin + LastPos := SmallPointToPoint(TSmallPoint(GetMessagePos())); + MouseMoved; + end; + UpdateAppHint; + end; + finally + RootView.CancelCapture; + end; + finally + RootView.FCaptureWnd := 0; + Application.Hint := ''; + { Make sure there are no outstanding WM_*CHAR messages } + RemoveMessages(WM_CHAR, WM_DEADCHAR); + RemoveMessages(WM_SYSCHAR, WM_SYSDEADCHAR); + { Nor any outstanding 'send WM_HELP' messages caused by an earlier press + of the F1 key } + RemoveMessages($4D, $4D); + end; +end; + + +{ TTBPopupView } + +procedure TTBPopupView.AutoSize(AWidth, AHeight: Integer); +begin + with TTBPopupWindow(FWindow) do + with GetNCSize do + SetBounds(Left, Top, AWidth + (X * 2), + AHeight + (Y * 2)); +end; + +function TTBPopupView.GetFont: TFont; +begin + Result := (Owner as TTBPopupWindow).Font; +end; + + +{ TTBPopupWindow } + +constructor TTBPopupWindow.CreatePopupWindow(AOwner: TComponent; + const AParentView: TTBView; const AItem: TTBCustomItem; + const ACustomizing: Boolean); +begin + inherited Create(AOwner); + Visible := False; + SetBounds(0, 0, 320, 240); + ControlStyle := ControlStyle - [csCaptureMouse]; + ShowHint := True; + Color := tbMenuBkColor; + FView := GetViewClass.CreateView(Self, AParentView, AItem, Self, False, + ACustomizing, False); + Include(FView.FState, vsModal); + + { Inherit the font from the parent view, or use the system menu font if + there is no parent view } + if Assigned(AParentView) then + Font.Assign(AParentView.GetFont) + else + Font.Assign(ToolbarFont); + + { Inherit the accelerator visibility state from the parent view. If there + is no parent view (i.e. it's a standalone popup menu), then default to + hiding accelerator keys, but change this in CreateWnd if the last input + came from the keyboard. } + if Assigned(AParentView) then begin + if vsUseHiddenAccels in AParentView.FStyle then + Include(FView.FStyle, vsUseHiddenAccels); + if vsShowAccels in AParentView.FState then + Include(FView.FState, vsShowAccels); + end + else + Include(FView.FStyle, vsUseHiddenAccels); + + if Application.Handle <> 0 then + { Use Application.Handle if possible so that the taskbar button for the app + doesn't pop up when a TTBEditItem on a popup menu is focused } + ParentWindow := Application.Handle + else + { When Application.Handle is zero, use GetDesktopWindow() as the parent + window, not zero, otherwise UpdateControlState won't show the window } + ParentWindow := GetDesktopWindow; +end; + +destructor TTBPopupWindow.Destroy; +begin + Destroying; + { Ensure window handle is destroyed *before* FView is freed, since + DestroyWindowHandle calls CallNotifyWinEvent which may result in + FView.HandleWMObject being called } + if HandleAllocated then + DestroyWindowHandle; + FreeAndNil(FView); + inherited; +end; + +procedure TTBPopupWindow.BeforeDestruction; +begin + { The inherited BeforeDestruction method hides the form. We need to close + any child popups first, so that pixels behind the popups are properly + restored without generating a WM_PAINT message. } + if Assigned(FView) then + FView.CloseChildPopups; + inherited; +end; + +function TTBPopupWindow.GetNCSize: TPoint; +begin + Result.X := PopupMenuWindowNCSize; + Result.Y := PopupMenuWindowNCSize; +end; + +function TTBPopupWindow.GetViewClass: TTBViewClass; +begin + Result := TTBPopupView; +end; + +procedure TTBPopupWindow.CreateParams(var Params: TCreateParams); +const + CS_DROPSHADOW = $00020000; +begin + inherited; + with Params do begin + Style := (Style and not (WS_CHILD or WS_GROUP or WS_TABSTOP)) or WS_POPUP; + ExStyle := ExStyle or WS_EX_TOPMOST or WS_EX_TOOLWINDOW; + WindowClass.Style := WindowClass.Style or CS_SAVEBITS; + { Enable drop shadow effect on Windows XP and later } + if IsWindowsXP then + WindowClass.Style := WindowClass.Style or CS_DROPSHADOW; + end; +end; + +procedure TTBPopupWindow.CreateWnd; +const + WM_CHANGEUISTATE = $0127; + WM_QUERYUISTATE = $0129; + UIS_INITIALIZE = 3; + UISF_HIDEACCEL = $2; +var + B: Boolean; +begin + inherited; + { On a top-level popup window, send WM_CHANGEUISTATE & WM_QUERYUISTATE + messages to the window to see if the last input came from the keyboard + and if the accelerator keys should be shown } + if (FView.ParentView = nil) and not FAccelsVisibilitySet then begin + FAccelsVisibilitySet := True; + SendMessage(Handle, WM_CHANGEUISTATE, UIS_INITIALIZE, 0); + B := (SendMessage(Handle, WM_QUERYUISTATE, 0, 0) and UISF_HIDEACCEL = 0); + FView.SetAccelsVisibility(B); + end; +end; + +procedure TTBPopupWindow.DestroyWindowHandle; +begin + { Before destroying the window handle, we must stop any animation, otherwise + the animation thread will use an invalid handle } + TBEndAnimation(WindowHandle); + { Cleanly destroy any timers before the window handle is destroyed } + if Assigned(FView) then + FView.StopAllTimers; + CallNotifyWinEvent(EVENT_SYSTEM_MENUPOPUPEND, WindowHandle, OBJID_CLIENT, + CHILDID_SELF); + inherited; +end; + +procedure TTBPopupWindow.WMGetObject(var Message: TMessage); +begin + if not FView.HandleWMGetObject(Message) then + inherited; +end; + +procedure TTBPopupWindow.CMShowingChanged(var Message: TMessage); +const + ShowFlags: array[Boolean] of UINT = ( + SWP_NOSIZE or SWP_NOMOVE or SWP_NOZORDER or SWP_NOACTIVATE or SWP_HIDEWINDOW, + SWP_NOSIZE or SWP_NOMOVE or SWP_NOZORDER or SWP_NOACTIVATE or SWP_SHOWWINDOW); + SPI_GETMENUFADE = $1012; +var + Animate: BOOL; + Blend: Boolean; +begin + { Must override TCustomForm/TForm's CM_SHOWINGCHANGED handler so that the + form doesn't get activated when Visible is set to True. } + + { Handle animation. NOTE: I do not recommend trying to enable animation on + Windows 95 and NT 4.0 because there's a difference in the way the + SetWindowPos works on those versions. See the comment in the + TBStartAnimation function of TB2Anim.pas. } + {$IFNDEF TB2K_NO_ANIMATION} + if ((FView.ParentView = nil) or not(vsNoAnimation in FView.FParentView.FState)) and + Showing and (FView.Selected = nil) and not IsWindowVisible(WindowHandle) and + SystemParametersInfo(SPI_GETMENUANIMATION, 0, @Animate, 0) and Animate then begin + Blend := SystemParametersInfo(SPI_GETMENUFADE, 0, @Animate, 0) and Animate; + if Blend or (FAnimationDirection <> []) then begin + if SendMessage(WindowHandle, WM_TB2K_POPUPSHOWING, TPS_ANIMSTART, 0) = 0 then + begin + { Start animation only if WM_TB2K_POPUPSHOWING returns zero (or not handled) } + TBStartAnimation(WindowHandle, Blend, FAnimationDirection); + Exit; + end; + end; + end; + {$ENDIF} + + { No animation... } + if not Showing then begin + { Call TBEndAnimation to ensure WS_EX_LAYERED style is removed before + hiding, otherwise windows under the popup window aren't repainted + properly. } + TBEndAnimation(WindowHandle); + end; + SetWindowPos(WindowHandle, 0, 0, 0, 0, 0, ShowFlags[Showing]); + if Showing then SendNotifyMessage(WindowHandle, WM_TB2K_POPUPSHOWING, TPS_NOANIM, 0); +end; + +procedure TTBPopupWindow.WMTB2kAnimationEnded(var Message: TMessage); +begin + SendNotifyMessage(WindowHandle, WM_TB2K_POPUPSHOWING, TPS_ANIMFINISHED, 0); +end; + +procedure TTBPopupWindow.WMTB2kStepAnimation(var Message: TMessage); +begin + TBStepAnimation(Message); +end; + +procedure TTBPopupWindow.WMEraseBkgnd(var Message: TWMEraseBkgnd); +begin + { May be necessary in some cases... } + TBEndAnimation(WindowHandle); + inherited; +end; + +procedure TTBPopupWindow.WMPaint(var Message: TWMPaint); +begin + { Must abort animation when a WM_PAINT message is received } + TBEndAnimation(WindowHandle); + inherited; +end; + +procedure TTBPopupWindow.Paint; +begin + FView.DrawSubitems(Canvas); + PaintScrollArrows; +end; + +procedure TTBPopupWindow.PaintScrollArrows; + + procedure DrawArrow(const R: TRect; ADown: Boolean); + var + X, Y: Integer; + P: array[0..2] of TPoint; + begin + X := (R.Left + R.Right) div 2; + Y := (R.Top + R.Bottom) div 2; + Dec(Y); + P[0].X := X-3; + P[0].Y := Y; + P[1].X := X+3; + P[1].Y := Y; + P[2].X := X; + P[2].Y := Y; + if ADown then + Inc(P[2].Y, 3) + else begin + Inc(P[0].Y, 3); + Inc(P[1].Y, 3); + end; + Canvas.Pen.Color := tbMenuTextColor; + Canvas.Brush.Color := tbMenuTextColor; + Canvas.Polygon(P); + end; + +begin + if FView.FShowUpArrow then + DrawArrow(Rect(0, 0, ClientWidth, tbMenuScrollArrowHeight), False); + if FView.FShowDownArrow then + DrawArrow(Bounds(0, ClientHeight - tbMenuScrollArrowHeight, + ClientWidth, tbMenuScrollArrowHeight), True); +end; + +procedure TTBPopupWindow.WMClose(var Message: TWMClose); +begin + { do nothing -- ignore Alt+F4 keypresses } +end; + +procedure TTBPopupWindow.WMNCCalcSize(var Message: TWMNCCalcSize); +begin + with GetNCSize do + InflateRect(Message.CalcSize_Params^.rgrc[0], -X, -Y); + inherited; +end; + +procedure PopupWindowNCPaintProc(Wnd: HWND; DC: HDC; AppData: Longint); +var + R: TRect; + {$IFNDEF TB2K_USE_STRICT_O2K_MENU_STYLE} + Brush: HBRUSH; + {$ENDIF} +begin + GetWindowRect(Wnd, R); OffsetRect(R, -R.Left, -R.Top); + {$IFNDEF TB2K_USE_STRICT_O2K_MENU_STYLE} + if not AreFlatMenusEnabled then begin + {$ENDIF} + DrawEdge(DC, R, EDGE_RAISED, BF_RECT or BF_ADJUST); + FrameRect(DC, R, GetSysColorBrush(COLOR_BTNFACE)); + {$IFNDEF TB2K_USE_STRICT_O2K_MENU_STYLE} + end + else begin + FrameRect(DC, R, GetSysColorBrush(COLOR_BTNSHADOW)); + Brush := CreateSolidBrush(ColorToRGB(TTBPopupWindow(AppData).Color)); + InflateRect(R, -1, -1); + FrameRect(DC, R, Brush); + InflateRect(R, -1, -1); + FrameRect(DC, R, Brush); + DeleteObject(Brush); + end; + {$ENDIF} +end; + +procedure TTBPopupWindow.WMNCPaint(var Message: TMessage); +var + DC: HDC; +begin + DC := GetWindowDC(Handle); + try + SelectNCUpdateRgn(Handle, DC, HRGN(Message.WParam)); + PopupWindowNCPaintProc(Handle, DC, Longint(Self)); + finally + ReleaseDC(Handle, DC); + end; +end; + +procedure TTBPopupWindow.WMPrint(var Message: TMessage); +begin + HandleWMPrint(Handle, Message, PopupWindowNCPaintProc, Longint(Self)); +end; + +procedure TTBPopupWindow.WMPrintClient(var Message: TMessage); +begin + HandleWMPrintClient(Self, Message); +end; + +procedure TTBPopupWindow.CMHintShow(var Message: TCMHintShow); +begin + with Message.HintInfo^ do begin + HintStr := ''; + if Assigned(FView.Selected) then begin + CursorRect := FView.Selected.BoundsRect; + HintStr := FView.FSelected.GetHintText; + end; + end; +end; + + +{ TTBItemContainer } + +constructor TTBItemContainer.Create(AOwner: TComponent); +begin + inherited; + FItem := TTBRootItem.Create(Self); + FItem.ParentComponent := Self; +end; + +destructor TTBItemContainer.Destroy; +begin + FItem.Free; + inherited; +end; + +function TTBItemContainer.GetItems: TTBCustomItem; +begin + Result := FItem; +end; + +procedure TTBItemContainer.GetChildren(Proc: TGetChildProc; Root: TComponent); +begin + FItem.GetChildren(Proc, Root); +end; + +function TTBItemContainer.GetImages: TCustomImageList; +begin + Result := FItem.SubMenuImages; +end; + +procedure TTBItemContainer.SetImages(Value: TCustomImageList); +begin + FItem.SubMenuImages := Value; +end; + + +{ TTBPopupMenu } + +constructor TTBPopupMenu.Create(AOwner: TComponent); +begin + inherited; + FItem := GetRootItemClass.Create(Self); + FItem.ParentComponent := Self; + FItem.OnClick := RootItemClick; +end; + +destructor TTBPopupMenu.Destroy; +begin + FItem.Free; + inherited; +end; + +function TTBPopupMenu.GetItems: TTBCustomItem; +begin + Result := FItem; +end; + +procedure TTBPopupMenu.GetChildren(Proc: TGetChildProc; Root: TComponent); +begin + FItem.GetChildren(Proc, Root); +end; + +procedure TTBPopupMenu.SetChildOrder(Child: TComponent; Order: Integer); +begin + FItem.SetChildOrder(Child, Order); +end; + +function TTBPopupMenu.GetRootItemClass: TTBRootItemClass; +begin + Result := TTBRootItem; +end; + +function TTBPopupMenu.GetImages: TCustomImageList; +begin + Result := FItem.SubMenuImages; +end; + +function TTBPopupMenu.GetLinkSubitems: TTBCustomItem; +begin + Result := FItem.LinkSubitems; +end; + +function TTBPopupMenu.GetOptions: TTBItemOptions; +begin + Result := FItem.Options; +end; + +procedure TTBPopupMenu.SetImages(Value: TCustomImageList); +begin + FItem.SubMenuImages := Value; +end; + +procedure TTBPopupMenu.SetLinkSubitems(Value: TTBCustomItem); +begin + FItem.LinkSubitems := Value; +end; + +procedure TTBPopupMenu.SetOptions(Value: TTBItemOptions); +begin + FItem.Options := Value; +end; + +procedure TTBPopupMenu.RootItemClick(Sender: TObject); +begin + if Sender = FItem then + Sender := Self; + DoPopup(Sender); +end; + +{$IFNDEF JR_D5} +procedure TTBPopupMenu.DoPopup(Sender: TObject); +begin + if Assigned(OnPopup) then OnPopup(Sender); +end; +{$ENDIF} + +procedure TTBPopupMenu.Popup(X, Y: Integer); +begin + PopupEx(X, Y, False); +end; + +function TTBPopupMenu.PopupEx(X, Y: Integer; + ReturnClickedItemOnly: Boolean = False): TTBCustomItem; +begin + {$IFDEF JR_D5} + {$IFDEF JR_D9} + SetPopupPoint(Point(X, Y)); + {$ELSE} + PPoint(@PopupPoint)^ := Point(X, Y); + {$ENDIF} + {$ENDIF} + Result := FItem.Popup(X, Y, TrackButton = tbRightButton, + TTBPopupAlignment(Alignment), ReturnClickedItemOnly); +end; + +function TTBPopupMenu.IsShortCut(var Message: TWMKey): Boolean; +begin + Result := FItem.IsShortCut(Message); +end; + + +{ TTBImageList } + +constructor TTBCustomImageList.Create(AOwner: TComponent); +begin + inherited; + FCheckedImagesChangeLink := TChangeLink.Create; + FCheckedImagesChangeLink.OnChange := ImageListChanged; + FDisabledImagesChangeLink := TChangeLink.Create; + FDisabledImagesChangeLink.OnChange := ImageListChanged; + FHotImagesChangeLink := TChangeLink.Create; + FHotImagesChangeLink.OnChange := ImageListChanged; + FImagesBitmap := TBitmap.Create; + FImagesBitmap.OnChange := ImagesBitmapChanged; + FImagesBitmapMaskColor := clFuchsia; +end; + +destructor TTBCustomImageList.Destroy; +begin + FreeAndNil(FImagesBitmap); + FreeAndNil(FHotImagesChangeLink); + FreeAndNil(FDisabledImagesChangeLink); + FreeAndNil(FCheckedImagesChangeLink); + inherited; +end; + +procedure TTBCustomImageList.ImagesBitmapChanged(Sender: TObject); +begin + if not ImagesBitmap.Empty then begin + Clear; + AddMasked(ImagesBitmap, FImagesBitmapMaskColor); + end; +end; + +procedure TTBCustomImageList.ImageListChanged(Sender: TObject); +begin + Change; +end; + +procedure TTBCustomImageList.DefineProperties(Filer: TFiler); +type + TProc = procedure(ASelf: TObject; Filer: TFiler); +begin + if (Filer is TReader) or FImagesBitmap.Empty then + inherited + else + { Bypass TCustomImageList.DefineProperties when we've got an ImageBitmap } + TProc(@TComponentAccess.DefineProperties)(Self, Filer); +end; + +procedure TTBCustomImageList.DrawState(Canvas: TCanvas; X, Y, Index: Integer; + Enabled, Selected, Checked: Boolean); +begin + if not Enabled and Assigned(DisabledImages) then + DisabledImages.Draw(Canvas, X, Y, Index) + else if Checked and Assigned(CheckedImages) then + CheckedImages.Draw(Canvas, X, Y, Index, Enabled) + else if Selected and Assigned(HotImages) then + HotImages.Draw(Canvas, X, Y, Index, Enabled) + else + Draw(Canvas, X, Y, Index, Enabled); +end; + +procedure TTBCustomImageList.Notification(AComponent: TComponent; Operation: TOperation); +begin + inherited; + if Operation = opRemove then begin + if AComponent = CheckedImages then CheckedImages := nil; + if AComponent = DisabledImages then DisabledImages := nil; + if AComponent = HotImages then HotImages := nil; + end; +end; + +procedure TTBCustomImageList.ChangeImages(var AImageList: TCustomImageList; + Value: TCustomImageList; AChangeLink: TChangeLink); +begin + if Value = Self then + Value := nil; + if AImageList <> Value then begin + if Assigned(AImageList) then + AImageList.UnregisterChanges(AChangeLink); + AImageList := Value; + if Assigned(Value) then begin + Value.RegisterChanges(AChangeLink); + Value.FreeNotification(Self); + end; + { Don't call Change while loading because it causes the Delphi IDE to + think the form has been modified (?). Also, don't call Change while + destroying since there's no reason to. } + if not(csLoading in ComponentState) and + not(csDestroying in ComponentState) then + Change; + end; +end; + +procedure TTBCustomImageList.SetCheckedImages(Value: TCustomImageList); +begin + ChangeImages(FCheckedImages, Value, FCheckedImagesChangeLink); +end; + +procedure TTBCustomImageList.SetDisabledImages(Value: TCustomImageList); +begin + ChangeImages(FDisabledImages, Value, FDisabledImagesChangeLink); +end; + +procedure TTBCustomImageList.SetHotImages(Value: TCustomImageList); +begin + ChangeImages(FHotImages, Value, FHotImagesChangeLink); +end; + +procedure TTBCustomImageList.SetImagesBitmap(Value: TBitmap); +begin + FImagesBitmap.Assign(Value); +end; + +procedure TTBCustomImageList.SetImagesBitmapMaskColor(Value: TColor); +begin + if FImagesBitmapMaskColor <> Value then begin + FImagesBitmapMaskColor := Value; + ImagesBitmapChanged(nil); + end; +end; + + +{ TTBBaseAccObject } + +{ According to the MSAA docs: + "With Active Accessibility 2.0, servers can return E_NOTIMPL from IDispatch + methods and Active Accessibility will implement the IAccessible interface + for them." + And there was much rejoicing. } + +function TTBBaseAccObject.GetIDsOfNames(const IID: TGUID; Names: Pointer; + NameCount, LocaleID: Integer; DispIDs: Pointer): HResult; +begin + Result := E_NOTIMPL; +end; + +function TTBBaseAccObject.GetTypeInfo(Index, LocaleID: Integer; + out TypeInfo): HResult; +begin + Result := E_NOTIMPL; +end; + +function TTBBaseAccObject.GetTypeInfoCount(out Count: Integer): HResult; +begin + Result := E_NOTIMPL; +end; + +function TTBBaseAccObject.Invoke(DispID: Integer; const IID: TGUID; + LocaleID: Integer; Flags: Word; var Params; VarResult, ExcepInfo, + ArgErr: Pointer): HResult; +begin + Result := E_NOTIMPL; +end; + + +{ Initialization & finalization } + +procedure TBInitToolbarSystemFont; +var + NonClientMetrics: TNonClientMetrics; +begin + NonClientMetrics.cbSize := SizeOf(NonClientMetrics); + if SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, @NonClientMetrics, 0) then + ToolbarFont.Handle := CreateFontIndirect(NonClientMetrics.lfMenuFont); +end; + +initialization + ToolbarFont := TFont.Create; + TBInitToolbarSystemFont; +finalization + DestroyClickWnd; + FreeAndNil(ToolbarFont); +end. diff --git a/official/2.1.6+2.1.beta1/Source/TB2Item.pas.orig b/official/2.1.6+2.1.beta1/Source/TB2Item.pas.orig new file mode 100644 index 0000000..fb3f179 --- /dev/null +++ b/official/2.1.6+2.1.beta1/Source/TB2Item.pas.orig @@ -0,0 +1,6813 @@ +unit TB2Item; + +{ + Toolbar2000 + Copyright (C) 1998-2005 by Jordan Russell + All rights reserved. + + The contents of this file are subject to the "Toolbar2000 License"; you may + not use or distribute this file except in compliance with the + "Toolbar2000 License". A copy of the "Toolbar2000 License" may be found in + TB2k-LICENSE.txt or at: + http://www.jrsoftware.org/files/tb2k/TB2k-LICENSE.txt + + Alternatively, the contents of this file may be used under the terms of the + GNU General Public License (the "GPL"), in which case the provisions of the + GPL are applicable instead of those in the "Toolbar2000 License". A copy of + the GPL may be found in GPL-LICENSE.txt or at: + http://www.jrsoftware.org/files/tb2k/GPL-LICENSE.txt + If you wish to allow use of your version of this file only under the terms of + the GPL and not to allow others to use your version of this file under the + "Toolbar2000 License", indicate your decision by deleting the provisions + above and replace them with the notice and other provisions required by the + GPL. If you do not delete the provisions above, a recipient may use your + version of this file under either the "Toolbar2000 License" or the GPL. + + $jrsoftware: tb2k/Source/TB2Item.pas,v 1.277 2005/06/23 21:55:44 jr Exp $ +} + +interface + +{$I TB2Ver.inc} +{x$DEFINE TB2K_NO_ANIMATION} + { Enabling the above define disables all menu animation. For debugging + purpose only. } +{x$DEFINE TB2K_USE_STRICT_O2K_MENU_STYLE} + { Enabling the above define forces it to use clBtnFace for the menu color + instead of clMenu, and disables the use of flat menu borders on Windows + XP with themes enabled. } + +uses + Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, + StdCtrls, CommCtrl, Menus, ActnList, ImgList, TB2Anim; + +type + TTBCustomItem = class; + TTBCustomItemClass = class of TTBCustomItem; + TTBCustomItemActionLink = class; + TTBCustomItemActionLinkClass = class of TTBCustomItemActionLink; + TTBItemViewer = class; + TTBItemViewerClass = class of TTBItemViewer; + TTBPopupWindow = class; + TTBPopupWindowClass = class of TTBPopupWindow; + TTBView = class; + + TTBDoneAction = (tbdaNone, tbdaCancel, tbdaClickItem, tbdaOpenSystemMenu, + tbdaHelpContext); + PTBDoneActionData = ^TTBDoneActionData; + TTBDoneActionData = record + DoneAction: TTBDoneAction; + case TTBDoneAction of + tbdaClickItem: (ClickItem: TTBCustomItem; Sound: Boolean); + tbdaOpenSystemMenu: (Wnd: HWND; Key: Cardinal); + tbdaHelpContext: (ContextID: Integer); + end; + TTBInsertItemProc = procedure(AParent: TComponent; AItem: TTBCustomItem) of object; + TTBItemChangedAction = (tbicInserted, tbicDeleting, tbicSubitemsChanged, + tbicSubitemsBeginUpdate, tbicSubitemsEndUpdate, tbicInvalidate, + tbicInvalidateAndResize, tbicRecreateItemViewers, tbicNameChanged, + tbicSubMenuImagesChanged); + TTBItemChangedProc = procedure(Sender: TTBCustomItem; Relayed: Boolean; + Action: TTBItemChangedAction; Index: Integer; Item: TTBCustomItem) of object; + TTBItemData = record + Item: TTBCustomItem; + end; + PTBItemDataArray = ^TTBItemDataArray; + TTBItemDataArray = array[0..$7FFFFFFF div SizeOf(TTBItemData)-1] of TTBItemData; + TTBItemDisplayMode = (nbdmDefault, nbdmTextOnly, nbdmTextOnlyInMenus, nbdmImageAndText); + TTBItemOption = (tboDefault, tboDropdownArrow, tboImageAboveCaption, + tboLongHintInMenuOnly, tboNoAutoHint, tboNoRotation, tboSameWidth, + tboShowHint, tboToolbarStyle, tboToolbarSize); + TTBItemOptions = set of TTBItemOption; + TTBItemStyle = set of (tbisSubmenu, tbisSelectable, tbisSeparator, + tbisEmbeddedGroup, tbisClicksTransparent, tbisCombo, tbisNoAutoOpen, + tbisSubitemsEditable, tbisNoLineBreak, tbisRightAlign, tbisDontSelectFirst, + tbisRedrawOnSelChange, tbisRedrawOnMouseOverChange); + TTBPopupAlignment = (tbpaLeft, tbpaRight, tbpaCenter); + TTBPopupEvent = procedure(Sender: TTBCustomItem; FromLink: Boolean) of object; + TTBSelectEvent = procedure(Sender: TTBCustomItem; Viewer: TTBItemViewer; + Selecting: Boolean) of object; + + ETBItemError = class(Exception); + + TTBImageChangeLink = class(TChangeLink) + private + FLastWidth, FLastHeight: Integer; + end; + {$IFNDEF JR_D5} + TImageIndex = type Integer; + {$ENDIF} + + TTBCustomItem = class(TComponent) + private + FActionLink: TTBCustomItemActionLink; + FAutoCheck: Boolean; + FCaption: String; + FChecked: Boolean; + FDisplayMode: TTBItemDisplayMode; + FEnabled: Boolean; + FEffectiveOptions: TTBItemOptions; + FGroupIndex: Integer; + FHelpContext: THelpContext; + FHint: String; + FImageIndex: TImageIndex; + FImages: TCustomImageList; + FImagesChangeLink: TTBImageChangeLink; + FItems: PTBItemDataArray; + FItemCount: Integer; + FItemStyle: TTBItemStyle; + FLinkParents: TList; + FMaskOptions: TTBItemOptions; + FOptions: TTBItemOptions; + FInheritOptions: Boolean; + FNotifyList: TList; + FOnClick: TNotifyEvent; + FOnPopup: TTBPopupEvent; + FOnSelect: TTBSelectEvent; + FParent: TTBCustomItem; + FParentComponent: TComponent; + FRadioItem: Boolean; + FShortCut: TShortCut; + FSubMenuImages: TCustomImageList; + FSubMenuImagesChangeLink: TTBImageChangeLink; + FLinkSubitems: TTBCustomItem; + FVisible: Boolean; + + procedure DoActionChange(Sender: TObject); + function ChangeImages(var AImages: TCustomImageList; + const Value: TCustomImageList; var AChangeLink: TTBImageChangeLink): Boolean; + class procedure ClickWndProc(var Message: TMessage); + function FindItemWithShortCut(AShortCut: TShortCut; + var ATopmostParent: TTBCustomItem): TTBCustomItem; + function FixOptions(const AOptions: TTBItemOptions): TTBItemOptions; + function GetAction: TBasicAction; + function GetItem(Index: Integer): TTBCustomItem; + procedure ImageListChangeHandler(Sender: TObject); + procedure InternalNotify(Ancestor: TTBCustomItem; NestingLevel: Integer; + Action: TTBItemChangedAction; Index: Integer; Item: TTBCustomItem); + {$IFDEF JR_D6} + function IsAutoCheckStored: Boolean; + {$ENDIF} + function IsCaptionStored: Boolean; + function IsCheckedStored: Boolean; + function IsEnabledStored: Boolean; + function IsHelpContextStored: Boolean; + function IsHintStored: Boolean; + function IsImageIndexStored: Boolean; + function IsOnClickStored: Boolean; + function IsShortCutStored: Boolean; + function IsVisibleStored: Boolean; + procedure Notify(Action: TTBItemChangedAction; Index: Integer; Item: TTBCustomItem); + procedure RefreshOptions; + procedure SetAction(Value: TBasicAction); + procedure SetCaption(Value: String); + procedure SetChecked(Value: Boolean); + procedure SetDisplayMode(Value: TTBItemDisplayMode); + procedure SetEnabled(Value: Boolean); + procedure SetGroupIndex(Value: Integer); + procedure SetImageIndex(Value: TImageIndex); + procedure SetImages(Value: TCustomImageList); + procedure SetInheritOptions(Value: Boolean); + procedure SetLinkSubitems(Value: TTBCustomItem); + procedure SetMaskOptions(Value: TTBItemOptions); + procedure SetOptions(Value: TTBItemOptions); + procedure SetRadioItem(Value: Boolean); + procedure SetSubMenuImages(Value: TCustomImageList); + procedure SetVisible(Value: Boolean); + procedure SubMenuImagesChanged; + procedure TurnSiblingsOff; + protected + procedure ActionChange(Sender: TObject; CheckDefaults: Boolean); dynamic; + procedure Change(NeedResize: Boolean); virtual; + function CreatePopup(const ParentView: TTBView; const ParentViewer: TTBItemViewer; + const PositionAsSubmenu, SelectFirstItem, Customizing: Boolean; + const APopupPoint: TPoint; const Alignment: TTBPopupAlignment): TTBPopupWindow; virtual; + procedure DoPopup(Sender: TTBCustomItem; FromLink: Boolean); virtual; + procedure EnabledChanged; virtual; + function GetActionLinkClass: TTBCustomItemActionLinkClass; dynamic; + function GetChevronParentView: TTBView; virtual; + procedure GetChildren(Proc: TGetChildProc; Root: TComponent); override; + function GetItemViewerClass(AView: TTBView): TTBItemViewerClass; virtual; + function GetPopupWindowClass: TTBPopupWindowClass; virtual; + procedure IndexError; + procedure Loaded; override; + function NeedToRecreateViewer(AViewer: TTBItemViewer): Boolean; virtual; + procedure Notification(AComponent: TComponent; Operation: TOperation); override; + function OpenPopup(const SelectFirstItem, TrackRightButton: Boolean; + const PopupPoint: TPoint; const Alignment: TTBPopupAlignment; + const ReturnClickedItemOnly: Boolean): TTBCustomItem; + procedure RecreateItemViewers; + procedure SetChildOrder(Child: TComponent; Order: Integer); override; + procedure SetName(const NewName: TComponentName); override; + procedure SetParentComponent(Value: TComponent); override; + + property ActionLink: TTBCustomItemActionLink read FActionLink write FActionLink; + property ItemStyle: TTBItemStyle read FItemStyle write FItemStyle; + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + function HasParent: Boolean; override; + function GetParentComponent: TComponent; override; + + procedure Add(AItem: TTBCustomItem); + procedure Clear; + procedure Click; virtual; + function ContainsItem(AItem: TTBCustomItem): Boolean; + procedure Delete(Index: Integer); + function GetShortCutText: String; + function IndexOf(AItem: TTBCustomItem): Integer; + procedure InitiateAction; virtual; + procedure Insert(NewIndex: Integer; AItem: TTBCustomItem); + function IsShortCut(var Message: TWMKey): Boolean; + procedure Move(CurIndex, NewIndex: Integer); + function Popup(X, Y: Integer; TrackRightButton: Boolean; + Alignment: TTBPopupAlignment = tbpaLeft; + ReturnClickedItemOnly: Boolean = False): TTBCustomItem; + procedure PostClick; + procedure RegisterNotification(ANotify: TTBItemChangedProc); + procedure Remove(Item: TTBCustomItem); + procedure UnregisterNotification(ANotify: TTBItemChangedProc); + procedure ViewBeginUpdate; + procedure ViewEndUpdate; + + property Action: TBasicAction read GetAction write SetAction; + property AutoCheck: Boolean read FAutoCheck write FAutoCheck {$IFDEF JR_D6} stored IsAutoCheckStored {$ENDIF} default False; + property Caption: String read FCaption write SetCaption stored IsCaptionStored; + property Count: Integer read FItemCount; + property Checked: Boolean read FChecked write SetChecked stored IsCheckedStored default False; + property DisplayMode: TTBItemDisplayMode read FDisplayMode write SetDisplayMode default nbdmDefault; + property EffectiveOptions: TTBItemOptions read FEffectiveOptions; + property Enabled: Boolean read FEnabled write SetEnabled stored IsEnabledStored default True; + property GroupIndex: Integer read FGroupIndex write SetGroupIndex default 0; + property HelpContext: THelpContext read FHelpContext write FHelpContext stored IsHelpContextStored default 0; + property Hint: String read FHint write FHint stored IsHintStored; + property ImageIndex: TImageIndex read FImageIndex write SetImageIndex stored IsImageIndexStored default -1; + property Images: TCustomImageList read FImages write SetImages; + property InheritOptions: Boolean read FInheritOptions write SetInheritOptions default True; + property Items[Index: Integer]: TTBCustomItem read GetItem; default; + property LinkSubitems: TTBCustomItem read FLinkSubitems write SetLinkSubitems; + property MaskOptions: TTBItemOptions read FMaskOptions write SetMaskOptions default []; + property Options: TTBItemOptions read FOptions write SetOptions default []; + property Parent: TTBCustomItem read FParent; + property ParentComponent: TComponent read FParentComponent write FParentComponent; + property RadioItem: Boolean read FRadioItem write SetRadioItem default False; + property ShortCut: TShortCut read FShortCut write FShortCut stored IsShortCutStored default 0; + property SubMenuImages: TCustomImageList read FSubMenuImages write SetSubMenuImages; + property Visible: Boolean read FVisible write SetVisible stored IsVisibleStored default True; + property OnClick: TNotifyEvent read FOnClick write FOnClick stored IsOnClickStored; + property OnPopup: TTBPopupEvent read FOnPopup write FOnPopup; + property OnSelect: TTBSelectEvent read FOnSelect write FOnSelect; + end; + + TTBCustomItemActionLink = class(TActionLink) + protected + FClient: TTBCustomItem; + procedure AssignClient(AClient: TObject); override; + {$IFDEF JR_D6} + function IsAutoCheckLinked: Boolean; virtual; + {$ENDIF} + function IsCaptionLinked: Boolean; override; + function IsCheckedLinked: Boolean; override; + function IsEnabledLinked: Boolean; override; + function IsHelpContextLinked: Boolean; override; + function IsHintLinked: Boolean; override; + function IsImageIndexLinked: Boolean; override; + function IsShortCutLinked: Boolean; override; + function IsVisibleLinked: Boolean; override; + function IsOnExecuteLinked: Boolean; override; + {$IFDEF JR_D6} + procedure SetAutoCheck(Value: Boolean); override; + {$ENDIF} + procedure SetCaption(const Value: String); override; + procedure SetChecked(Value: Boolean); override; + procedure SetEnabled(Value: Boolean); override; + procedure SetHelpContext(Value: THelpContext); override; + procedure SetHint(const Value: String); override; + procedure SetImageIndex(Value: Integer); override; + procedure SetShortCut(Value: TShortCut); override; + procedure SetVisible(Value: Boolean); override; + procedure SetOnExecute(Value: TNotifyEvent); override; + end; + + TTBBaseAccObject = class(TInterfacedObject, IDispatch) + public + procedure ClientIsDestroying; virtual; abstract; + { IDispatch } + function GetTypeInfoCount(out Count: Integer): HResult; stdcall; + function GetTypeInfo(Index, LocaleID: Integer; out TypeInfo): HResult; stdcall; + function GetIDsOfNames(const IID: TGUID; Names: Pointer; + NameCount, LocaleID: Integer; DispIDs: Pointer): HResult; stdcall; + function Invoke(DispID: Integer; const IID: TGUID; LocaleID: Integer; + Flags: Word; var Params; VarResult, ExcepInfo, ArgErr: Pointer): HResult; stdcall; + end; + + TTBItemViewer = class + private + FBoundsRect: TRect; + FClipped: Boolean; + FGroupLevel: Integer; + FItem: TTBCustomItem; + FOffEdge: Boolean; + FShow: Boolean; + FView: TTBView; + procedure AccSelect(const AExecute: Boolean); + function GetIndex: Integer; + protected + FAccObjectInstance: TTBBaseAccObject; + procedure CalcSize(const Canvas: TCanvas; var AWidth, AHeight: Integer); + virtual; + function CaptionShown: Boolean; dynamic; + function DoExecute: Boolean; virtual; + procedure DrawItemCaption(const Canvas: TCanvas; ARect: TRect; + const ACaption: String; ADrawDisabledShadow: Boolean; AFormat: UINT); virtual; + procedure Entering; virtual; + function GetAccRole: Integer; virtual; + function GetAccValue(var Value: WideString): Boolean; virtual; + function GetCaptionText: String; virtual; + procedure GetCursor(const Pt: TPoint; var ACursor: HCURSOR); virtual; + function GetImageList: TCustomImageList; + function ImageShown: Boolean; + function IsRotated: Boolean; + function IsToolbarSize: Boolean; + function IsPtInButtonPart(X, Y: Integer): Boolean; virtual; + procedure KeyDown(var Key: Word; Shift: TShiftState); virtual; + procedure Leaving; virtual; + procedure LosingCapture; virtual; + procedure MouseDown(Shift: TShiftState; X, Y: Integer; + var MouseDownOnMenu: Boolean); virtual; + procedure MouseMove(X, Y: Integer); virtual; + procedure MouseUp(X, Y: Integer; MouseWasDownOnMenu: Boolean); virtual; + procedure MouseWheel(WheelDelta: Integer; X, Y: Integer); virtual; + procedure Paint(const Canvas: TCanvas; const ClientAreaRect: TRect; + IsSelected, IsPushed, UseDisabledShadow: Boolean); virtual; + procedure PostAccSelect(const AExecute: Boolean); + function UsesSameWidth: Boolean; virtual; + public + State: set of (tbisInvalidated, tbisLineSep); + property BoundsRect: TRect read FBoundsRect; + property Clipped: Boolean read FClipped; + property Index: Integer read GetIndex; + property Item: TTBCustomItem read FItem; + property OffEdge: Boolean read FOffEdge; + property Show: Boolean read FShow; + property View: TTBView read FView; + constructor Create(AView: TTBView; AItem: TTBCustomItem; AGroupLevel: Integer); virtual; + destructor Destroy; override; + procedure Execute(AGivePriority: Boolean); + function GetAccObject: IDispatch; + function GetHintText: String; + function IsAccessible: Boolean; + function IsToolbarStyle: Boolean; + function ScreenToClient(const P: TPoint): TPoint; + end; + PTBItemViewerArray = ^TTBItemViewerArray; + TTBItemViewerArray = array[0..$7FFFFFFF div SizeOf(TTBItemViewer)-1] of TTBItemViewer; + TTBViewOrientation = (tbvoHorizontal, tbvoVertical, tbvoFloating); + TTBEnterToolbarLoopOptions = set of (tbetMouseDown, tbetExecuteSelected, + tbetFromMSAA); + TTBViewState = set of (vsModal, vsMouseInWindow, vsDrawInOrder, vsOppositePopup, + vsIgnoreFirstMouseUp, vsShowAccels, vsDropDownMenus, vsNoAnimation); + TTBViewStyle = set of (vsMenuBar, vsUseHiddenAccels, vsAlwaysShowHints); + TTBViewTimerID = (tiOpen, tiClose, tiScrollUp, tiScrollDown); + + TTBViewClass = class of TTBView; + TTBView = class(TComponent) + private + FActiveTimers: set of TTBViewTimerID; + FBackgroundColor: TColor; + FBaseSize: TPoint; + FCapture: Boolean; + FCaptureWnd: HWND; + FChevronOffset: Integer; + FChevronParentView: TTBView; + FChevronSize: Integer; + FCurParentItem: TTBCustomItem; + FCustomizing: Boolean; + FDoneActionData: TTBDoneActionData; + FInternalViewersAtEnd: Integer; + FInternalViewersAtFront: Integer; + FIsPopup: Boolean; + FIsToolbar: Boolean; + FMaxHeight: Integer; + FMonitorRect: TRect; + FMouseOverSelected: Boolean; + FNewViewersGetHighestPriority: Boolean; + FOpenViewer: TTBItemViewer; + FOpenViewerView: TTBView; + FOpenViewerWindow: TTBPopupWindow; + FParentView: TTBView; + FParentItem: TTBCustomItem; + FPriorityList: TList; + FOrientation: TTBViewOrientation; + FScrollOffset: Integer; + FSelected: TTBItemViewer; + FSelectedViaMouse: Boolean; + FShowDownArrow: Boolean; + FShowUpArrow: Boolean; + FState: TTBViewState; + FStyle: TTBViewStyle; + FUpdating: Integer; + FUsePriorityList: Boolean; + FValidated: Boolean; + FViewerCount: Integer; + FViewers: PTBItemViewerArray; + FWindow: TWinControl; + FWrapOffset: Integer; + + procedure DeletingViewer(Viewer: TTBItemViewer); + procedure DrawItem(Viewer: TTBItemViewer; DrawTo: TCanvas; Offscreen: Boolean); + procedure FreeViewers; + procedure ImagesChanged; + function InsertItemViewers(const NewIndex: Integer; + const AItem: TTBCustomItem; const AGroupLevel: Integer; + const AddToPriorityList, TopOfPriorityList: Boolean): Integer; + procedure ItemNotification(Ancestor: TTBCustomItem; Relayed: Boolean; + Action: TTBItemChangedAction; Index: Integer; Item: TTBCustomItem); + procedure LinkNotification(Ancestor: TTBCustomItem; Relayed: Boolean; + Action: TTBItemChangedAction; Index: Integer; Item: TTBCustomItem); + procedure RecreateItemViewer(const I: Integer); + procedure Scroll(ADown: Boolean); + procedure SetCustomizing(Value: Boolean); + procedure SetSelected(Value: TTBItemViewer); + procedure SetUsePriorityList(Value: Boolean); + procedure StartTimer(const ATimer: TTBViewTimerID; const Interval: Integer); + procedure StopAllTimers; + procedure StopTimer(const ATimer: TTBViewTimerID); + procedure UpdateCurParentItem; + protected + FAccObjectInstance: TTBBaseAccObject; + procedure AutoSize(AWidth, AHeight: Integer); virtual; + function CalculatePositions(const CanMoveControls: Boolean; + const AOrientation: TTBViewOrientation; + AWrapOffset, AChevronOffset, AChevronSize: Integer; + var ABaseSize, TotalSize: TPoint; + var AWrappedLines: Integer): Boolean; + procedure DoUpdatePositions(var ASize: TPoint); virtual; + function GetChevronItem: TTBCustomItem; virtual; + procedure GetMargins(AOrientation: TTBViewOrientation; var Margins: TRect); + virtual; + function GetMDIButtonsItem: TTBCustomItem; virtual; + function GetMDISystemMenuItem: TTBCustomItem; virtual; + function GetParentToolbarView: TTBView; + function GetRootView: TTBView; + function HandleWMGetObject(var Message: TMessage): Boolean; + procedure InitiateActions; + procedure KeyDown(var Key: Word; Shift: TShiftState); virtual; + procedure Notification(AComponent: TComponent; Operation: TOperation); override; + procedure SetAccelsVisibility(AShowAccels: Boolean); + public + constructor CreateView(AOwner: TComponent; AParentView: TTBView; + AParentItem: TTBCustomItem; AWindow: TWinControl; + AIsToolbar, ACustomizing, AUsePriorityList: Boolean); virtual; + destructor Destroy; override; + procedure BeginUpdate; + procedure CancelCapture; + procedure CancelChildPopups; + procedure CancelMode; + procedure CloseChildPopups; + function ContainsView(AView: TTBView): Boolean; + procedure DrawSubitems(ACanvas: TCanvas); + procedure EndModal; + procedure EndModalWithClick(AViewer: TTBItemViewer); + procedure EndModalWithHelp(AContextID: Integer); + procedure EndModalWithSystemMenu(AWnd: HWND; AKey: Cardinal); + procedure EndUpdate; + procedure EnterToolbarLoop(Options: TTBEnterToolbarLoopOptions); + procedure ExecuteSelected(AGivePriority: Boolean); + function Find(Item: TTBCustomItem): TTBItemViewer; + function FirstSelectable: TTBItemViewer; + function GetAccObject: IDispatch; + function GetCaptureWnd: HWND; + function GetFont: TFont; virtual; + procedure GetOffEdgeControlList(const List: TList); + procedure GivePriority(AViewer: TTBItemViewer); + function HighestPriorityViewer: TTBItemViewer; + procedure Invalidate(AViewer: TTBItemViewer); + procedure InvalidatePositions; virtual; + function IndexOf(AViewer: TTBItemViewer): Integer; + function IsModalEnding: Boolean; + function NextSelectable(CurViewer: TTBItemViewer; GoForward: Boolean): TTBItemViewer; + function NextSelectableWithAccel(CurViewer: TTBItemViewer; Key: Char; + RequirePrimaryAccel: Boolean; var IsOnlyItemWithAccel: Boolean): TTBItemViewer; + procedure NotifyFocusEvent; + function OpenChildPopup(const SelectFirstItem: Boolean): Boolean; + procedure RecreateAllViewers; + procedure ScrollSelectedIntoView; + procedure Select(Value: TTBItemViewer; ViaMouse: Boolean); + procedure SetCapture; + procedure TryValidatePositions; + procedure UpdateSelection(const P: PPoint; const AllowNewSelection: Boolean); + function UpdatePositions: TPoint; + procedure ValidatePositions; + function ViewerFromPoint(const P: TPoint): TTBItemViewer; + + property BackgroundColor: TColor read FBackgroundColor write FBackgroundColor; + property BaseSize: TPoint read FBaseSize; + property Capture: Boolean read FCapture; + property ChevronOffset: Integer read FChevronOffset write FChevronOffset; + property ChevronSize: Integer read FChevronSize write FChevronSize; + property Customizing: Boolean read FCustomizing write SetCustomizing; + property IsPopup: Boolean read FIsPopup; + property IsToolbar: Boolean read FIsToolbar; + property MouseOverSelected: Boolean read FMouseOverSelected; + property NewViewersGetHighestPriority: Boolean read FNewViewersGetHighestPriority + write FNewViewersGetHighestPriority; + property ParentView: TTBView read FParentView; + property ParentItem: TTBCustomItem read FParentItem; + property OpenViewer: TTBItemViewer read FOpenViewer; + property OpenViewerView: TTBView read FOpenViewerView; + property Orientation: TTBViewOrientation read FOrientation write FOrientation; + property Selected: TTBItemViewer read FSelected write SetSelected; + property SelectedViaMouse: Boolean read FSelectedViaMouse; + property State: TTBViewState read FState; + property Style: TTBViewStyle read FStyle write FStyle; + property UsePriorityList: Boolean read FUsePriorityList write SetUsePriorityList; + property Viewers: PTBItemViewerArray read FViewers; + property ViewerCount: Integer read FViewerCount; + property Window: TWinControl read FWindow; + property WrapOffset: Integer read FWrapOffset write FWrapOffset; + end; + + TTBRootItemClass = class of TTBRootItem; + TTBRootItem = class(TTBCustomItem); + { same as TTBCustomItem, except there's a property editor for it } + + TTBItem = class(TTBCustomItem) + published + property Action; + property AutoCheck; + property Caption; + property Checked; + property DisplayMode; + property Enabled; + property GroupIndex; + property HelpContext; + property Hint; + property ImageIndex; + property Images; + property InheritOptions; + property MaskOptions; + property Options; + property RadioItem; + property ShortCut; + property Visible; + + property OnClick; + property OnSelect; + end; + + TTBGroupItem = class(TTBCustomItem) + public + constructor Create(AOwner: TComponent); override; + published + property InheritOptions; + property LinkSubitems; + property MaskOptions; + property Options; + end; + + TTBSubmenuItem = class(TTBCustomItem) + private + function GetDropdownCombo: Boolean; + procedure SetDropdownCombo(Value: Boolean); + public + constructor Create(AOwner: TComponent); override; + published + property Action; + property AutoCheck; + property Caption; + property Checked; + //property DisplayAsToolbar; + property DisplayMode; + property DropdownCombo: Boolean read GetDropdownCombo write SetDropdownCombo default False; + property Enabled; + property GroupIndex; + property HelpContext; + property Hint; + property ImageIndex; + property Images; + property InheritOptions; + property LinkSubitems; + property MaskOptions; + property Options; + property RadioItem; + property ShortCut; + property SubMenuImages; + property Visible; + + property OnClick; + property OnPopup; + property OnSelect; + end; + + TTBSeparatorItem = class(TTBCustomItem) + private + FBlank: Boolean; + procedure SetBlank(Value: Boolean); + protected + function GetItemViewerClass(AView: TTBView): TTBItemViewerClass; override; + public + constructor Create(AOwner: TComponent); override; + published + property Blank: Boolean read FBlank write SetBlank default False; + property Hint; + property Visible; + end; + + TTBSeparatorItemViewer = class(TTBItemViewer) + protected + procedure CalcSize(const Canvas: TCanvas; + var AWidth, AHeight: Integer); override; + procedure Paint(const Canvas: TCanvas; const ClientAreaRect: TRect; + IsSelected, IsPushed, UseDisabledShadow: Boolean); override; + function UsesSameWidth: Boolean; override; + end; + + TTBControlItem = class(TTBCustomItem) + private + FControl: TControl; + FDontFreeControl: Boolean; + procedure SetControl(Value: TControl); + protected + procedure Notification(AComponent: TComponent; Operation: TOperation); override; + public + constructor Create(AOwner: TComponent); override; + constructor CreateControlItem(AOwner: TComponent; AControl: TControl); + destructor Destroy; override; + property DontFreeControl: Boolean read FDontFreeControl write FDontFreeControl; + published + property Control: TControl read FControl write SetControl; + end; + + TTBPopupView = class(TTBView) + protected + procedure AutoSize(AWidth, AHeight: Integer); override; + public + function GetFont: TFont; override; + end; + + ITBPopupWindow = interface + ['{E45CBE74-1ECF-44CB-B064-6D45B1924708}'] + end; + + TTBPopupWindow = class(TCustomControl, ITBPopupWindow) + private + FAccelsVisibilitySet: Boolean; + FAnimationDirection: TTBAnimationDirection; + FView: TTBView; + procedure CMHintShow(var Message: TCMHintShow); message CM_HINTSHOW; + procedure CMShowingChanged(var Message: TMessage); message CM_SHOWINGCHANGED; + procedure WMClose(var Message: TWMClose); message WM_CLOSE; + procedure WMEraseBkgnd(var Message: TWMEraseBkgnd); message WM_ERASEBKGND; + procedure WMGetObject(var Message: TMessage); message WM_GETOBJECT; + procedure WMNCCalcSize(var Message: TWMNCCalcSize); message WM_NCCALCSIZE; + procedure WMNCPaint(var Message: TMessage); message WM_NCPAINT; + procedure WMPaint(var Message: TWMPaint); message WM_PAINT; + procedure WMPrint(var Message: TMessage); message WM_PRINT; + procedure WMPrintClient(var Message: TMessage); message WM_PRINTCLIENT; + procedure WMTB2kStepAnimation(var Message: TMessage); message WM_TB2K_STEPANIMATION; + protected + procedure CreateParams(var Params: TCreateParams); override; + procedure CreateWnd; override; + procedure DestroyWindowHandle; override; + function GetViewClass: TTBViewClass; dynamic; + procedure Paint; override; + procedure PaintScrollArrows; virtual; + public + constructor CreatePopupWindow(AOwner: TComponent; const AParentView: TTBView; + const AItem: TTBCustomItem; const ACustomizing: Boolean); virtual; + destructor Destroy; override; + procedure BeforeDestruction; override; + + property View: TTBView read FView; + end; + + ITBItems = interface + ['{A5C0D7CC-3EC4-4090-A0F8-3D03271877EA}'] + function GetItems: TTBCustomItem; + end; + + TTBItemContainer = class(TComponent, ITBItems) + private + FItem: TTBRootItem; + function GetImages: TCustomImageList; + function GetItems: TTBCustomItem; + procedure SetImages(Value: TCustomImageList); + protected + procedure GetChildren(Proc: TGetChildProc; Root: TComponent); override; + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + + property Items: TTBRootItem read FItem; + published + property Images: TCustomImageList read GetImages write SetImages; + end; + + TTBPopupMenu = class(TPopupMenu, ITBItems) + private + FItem: TTBRootItem; + //procedure SetItems(Value: TTBCustomItem); + function GetImages: TCustomImageList; + function GetItems: TTBCustomItem; + function GetLinkSubitems: TTBCustomItem; + function GetOptions: TTBItemOptions; + procedure RootItemClick(Sender: TObject); + procedure SetImages(Value: TCustomImageList); + procedure SetLinkSubitems(Value: TTBCustomItem); + procedure SetOptions(Value: TTBItemOptions); + protected + {$IFNDEF JR_D5} + procedure DoPopup(Sender: TObject); + {$ENDIF} + procedure GetChildren(Proc: TGetChildProc; Root: TComponent); override; + function GetRootItemClass: TTBRootItemClass; dynamic; + procedure SetChildOrder(Child: TComponent; Order: Integer); override; + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + function IsShortCut(var Message: TWMKey): Boolean; override; + procedure Popup(X, Y: Integer); override; + function PopupEx(X, Y: Integer; ReturnClickedItemOnly: Boolean = False): TTBCustomItem; + published + property Images: TCustomImageList read GetImages write SetImages; + property Items: TTBRootItem read FItem; + property LinkSubitems: TTBCustomItem read GetLinkSubitems write SetLinkSubitems; + property Options: TTBItemOptions read GetOptions write SetOptions default []; + end; + + TTBCustomImageList = class(TImageList) + private + FCheckedImages: TCustomImageList; + FCheckedImagesChangeLink: TChangeLink; + FDisabledImages: TCustomImageList; + FDisabledImagesChangeLink: TChangeLink; + FHotImages: TCustomImageList; + FHotImagesChangeLink: TChangeLink; + FImagesBitmap: TBitmap; + FImagesBitmapMaskColor: TColor; + procedure ChangeImages(var AImageList: TCustomImageList; + Value: TCustomImageList; AChangeLink: TChangeLink); + procedure ImageListChanged(Sender: TObject); + procedure ImagesBitmapChanged(Sender: TObject); + procedure SetCheckedImages(Value: TCustomImageList); + procedure SetDisabledImages(Value: TCustomImageList); + procedure SetHotImages(Value: TCustomImageList); + procedure SetImagesBitmap(Value: TBitmap); + procedure SetImagesBitmapMaskColor(Value: TColor); + protected + procedure DefineProperties(Filer: TFiler); override; + procedure Notification(AComponent: TComponent; Operation: TOperation); override; + property CheckedImages: TCustomImageList read FCheckedImages write SetCheckedImages; + property DisabledImages: TCustomImageList read FDisabledImages write SetDisabledImages; + property HotImages: TCustomImageList read FHotImages write SetHotImages; + property ImagesBitmap: TBitmap read FImagesBitmap write SetImagesBitmap; + property ImagesBitmapMaskColor: TColor read FImagesBitmapMaskColor + write SetImagesBitmapMaskColor default clFuchsia; + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + procedure DrawState(Canvas: TCanvas; X, Y, Index: Integer; + Enabled, Selected, Checked: Boolean); virtual; + end; + + TTBImageList = class(TTBCustomImageList) + published + property CheckedImages; + property DisabledImages; + property HotImages; + property ImagesBitmap; + property ImagesBitmapMaskColor; + end; + +const + {$IFNDEF TB2K_USE_STRICT_O2K_MENU_STYLE} + tbMenuBkColor = clMenu; + tbMenuTextColor = clMenuText; + {$ELSE} + tbMenuBkColor = clBtnFace; + tbMenuTextColor = clBtnText; + {$ENDIF} + + tbMenuVerticalMargin = 4; + tbMenuImageTextSpace = 1; + tbMenuLeftTextMargin = 2; + tbMenuRightTextMargin = 3; + + tbMenuSeparatorOffset = 12; + + tbMenuScrollArrowHeight = 19; + + tbDropdownArrowWidth = 8; + tbDropdownArrowMargin = 3; + tbDropdownComboArrowWidth = 11; + tbDropdownComboMargin = 2; + + tbLineSpacing = 6; + tbLineSepOffset = 1; + tbDockedLineSepOffset = 4; + + WM_TB2K_CLICKITEM = WM_USER + $100; + +procedure TBInitToolbarSystemFont; + +var + ToolbarFont: TFont; + + +implementation + +uses + MMSYSTEM, TB2Consts, TB2Common, IMM, TB2Acc; + +var + LastPos: TPoint; + +threadvar + ClickWndRefCount: Integer; + ClickWnd: HWND; + ClickList: TList; + +type + TTBModalHandler = class + private + FCreatedWnd: Boolean; + FInited: Boolean; + FWnd: HWND; + FRootPopup: TTBPopupWindow; + procedure WndProc(var Msg: TMessage); + public + constructor Create(AExistingWnd: HWND); + destructor Destroy; override; + procedure Loop(const RootView: TTBView; const AMouseDown, AExecuteSelected, + AFromMSAA, TrackRightButton: Boolean); + property RootPopup: TTBPopupWindow read FRootPopup write FRootPopup; + property Wnd: HWND read FWnd; + end; + + PItemChangedNotificationData = ^TItemChangedNotificationData; + TItemChangedNotificationData = record + Proc: TTBItemChangedProc; + RefCount: Integer; + end; + + TComponentAccess = class(TComponent); + TControlAccess = class(TControl); + +const + ViewTimerBaseID = 9000; + MaxGroupLevel = 10; + + +{ Misc. } + +procedure DestroyClickWnd; +begin + if ClickWnd <> 0 then begin + {$IFDEF JR_D6}Classes.{$ENDIF} DeallocateHWnd(ClickWnd); + ClickWnd := 0; + end; + FreeAndNil(ClickList); +end; + +procedure ReferenceClickWnd; +begin + Inc(ClickWndRefCount); +end; + +procedure ReleaseClickWnd; +begin + Dec(ClickWndRefCount); + if ClickWndRefCount = 0 then + DestroyClickWnd; +end; + +procedure QueueClick(const AItem: TObject; const AArg: Integer); +{ Adds an item to ClickList and posts a message to handle it. AItem must be + either a TTBCustomItem or TTBItemViewer. } +var + I: Integer; +begin + if ClickWnd = 0 then + ClickWnd := {$IFDEF JR_D6}Classes.{$ENDIF} AllocateHWnd(TTBCustomItem.ClickWndProc); + if ClickList = nil then + ClickList := TList.Create; + + { Add a new item to ClickList or replace an empty one } + I := ClickList.IndexOf(nil); + if I = -1 then + I := ClickList.Add(AItem) + else + ClickList[I] := AItem; + + PostMessage(ClickWnd, WM_TB2K_CLICKITEM, AArg, I); +end; + +procedure RemoveFromClickList(const AItem: TObject); +{ Any class that potentially calls QueueClick needs to call RemoveFromClickList + before an instance is destroyed to ensure that any references to the + instance still in ClickList are removed. } +var + I: Integer; +begin + if Assigned(ClickList) and Assigned(AItem) then + for I := 0 to ClickList.Count-1 do + if ClickList[I] = AItem then + ClickList[I] := Pointer(1); + { ^ The special value of Pointer(1) is assigned to the item instead of + of nil because we want the index to stay reserved until the + WM_TB2K_CLICKITEM message for the index is processed. We don't want + the WM_TB2K_CLICKITEM message that's still in the queue to later + refer to a different item; this would result in queued clicks being + processed in the wrong order in a case like this: + A.PostClick; B.PostClick; A.Free; C.PostClick; + C's click would end up being processed before A's, because C would + get A's index. } +end; + +function ProcessDoneAction(const DoneActionData: TTBDoneActionData; + const ReturnClickedItemOnly: Boolean): TTBCustomItem; +begin + Result := nil; + case DoneActionData.DoneAction of + tbdaNone: ; + tbdaClickItem: begin + if DoneActionData.Sound and NeedToPlaySound('MenuCommand') then + PlaySound('MenuCommand', 0, SND_ALIAS or SND_ASYNC or SND_NODEFAULT or SND_NOSTOP); + Result := DoneActionData.ClickItem; + if not ReturnClickedItemOnly then + Result.PostClick; + end; + tbdaOpenSystemMenu: begin + SendMessage(DoneActionData.Wnd, WM_SYSCOMMAND, SC_KEYMENU, DoneActionData.Key); + end; + tbdaHelpContext: begin + { Based on code in TPopupList.WndProc: } + if Assigned(Screen.ActiveForm) and + (biHelp in Screen.ActiveForm.BorderIcons) then + Application.HelpCommand(HELP_CONTEXTPOPUP, DoneActionData.ContextID) + else + Application.HelpContext(DoneActionData.ContextID); + end; + end; +end; + + +{ TTBItemDataArray routines } + +procedure InsertIntoItemArray(var AItems: PTBItemDataArray; + var AItemCount: Integer; NewIndex: Integer; AItem: TTBCustomItem); +begin + ReallocMem(AItems, (AItemCount+1) * SizeOf(AItems[0])); + if NewIndex < AItemCount then + System.Move(AItems[NewIndex], AItems[NewIndex+1], + (AItemCount-NewIndex) * SizeOf(AItems[0])); + AItems[NewIndex].Item := AItem; + Inc(AItemCount); +end; + +procedure DeleteFromItemArray(var AItems: PTBItemDataArray; + var AItemCount: Integer; Index: Integer); +begin + Dec(AItemCount); + if Index < AItemCount then + System.Move(AItems[Index+1], AItems[Index], + (AItemCount-Index) * SizeOf(AItems[0])); + ReallocMem(AItems, AItemCount * SizeOf(AItems[0])); +end; + +procedure InsertIntoViewerArray(var AItems: PTBItemViewerArray; + var AItemCount: Integer; NewIndex: Integer; AItem: TTBItemViewer); +begin + ReallocMem(AItems, (AItemCount+1) * SizeOf(AItems[0])); + if NewIndex < AItemCount then + System.Move(AItems[NewIndex], AItems[NewIndex+1], + (AItemCount-NewIndex) * SizeOf(AItems[0])); + AItems[NewIndex] := AItem; + Inc(AItemCount); +end; + +procedure DeleteFromViewerArray(var AItems: PTBItemViewerArray; + var AItemCount: Integer; Index: Integer); +begin + Dec(AItemCount); + if Index < AItemCount then + System.Move(AItems[Index+1], AItems[Index], + (AItemCount-Index) * SizeOf(AItems[0])); + ReallocMem(AItems, AItemCount * SizeOf(AItems[0])); +end; + + +{ TTBCustomItemActionLink } + +procedure TTBCustomItemActionLink.AssignClient(AClient: TObject); +begin + FClient := AClient as TTBCustomItem; +end; + +{$IFDEF JR_D6} +function TTBCustomItemActionLink.IsAutoCheckLinked: Boolean; +begin + Result := (FClient.AutoCheck = (Action as TCustomAction).AutoCheck); +end; +{$ENDIF} + +function TTBCustomItemActionLink.IsCaptionLinked: Boolean; +begin + Result := inherited IsCaptionLinked and + (FClient.Caption = (Action as TCustomAction).Caption); +end; + +function TTBCustomItemActionLink.IsCheckedLinked: Boolean; +begin + Result := inherited IsCheckedLinked and + (FClient.Checked = (Action as TCustomAction).Checked); +end; + +function TTBCustomItemActionLink.IsEnabledLinked: Boolean; +begin + Result := inherited IsEnabledLinked and + (FClient.Enabled = (Action as TCustomAction).Enabled); +end; + +function TTBCustomItemActionLink.IsHelpContextLinked: Boolean; +begin + Result := inherited IsHelpContextLinked and + (FClient.HelpContext = (Action as TCustomAction).HelpContext); +end; + +function TTBCustomItemActionLink.IsHintLinked: Boolean; +begin + Result := inherited IsHintLinked and + (FClient.Hint = (Action as TCustomAction).Hint); +end; + +function TTBCustomItemActionLink.IsImageIndexLinked: Boolean; +begin + Result := inherited IsImageIndexLinked and + (FClient.ImageIndex = (Action as TCustomAction).ImageIndex); +end; + +function TTBCustomItemActionLink.IsShortCutLinked: Boolean; +begin + Result := inherited IsShortCutLinked and + (FClient.ShortCut = (Action as TCustomAction).ShortCut); +end; + +function TTBCustomItemActionLink.IsVisibleLinked: Boolean; +begin + Result := inherited IsVisibleLinked and + (FClient.Visible = (Action as TCustomAction).Visible); +end; + +function TTBCustomItemActionLink.IsOnExecuteLinked: Boolean; +begin + Result := inherited IsOnExecuteLinked and + MethodsEqual(TMethod(FClient.OnClick), TMethod(Action.OnExecute)); +end; + +{$IFDEF JR_D6} +procedure TTBCustomItemActionLink.SetAutoCheck(Value: Boolean); +begin + if IsAutoCheckLinked then FClient.AutoCheck := Value; +end; +{$ENDIF} + +procedure TTBCustomItemActionLink.SetCaption(const Value: string); +begin + if IsCaptionLinked then FClient.Caption := Value; +end; + +procedure TTBCustomItemActionLink.SetChecked(Value: Boolean); +begin + if IsCheckedLinked then FClient.Checked := Value; +end; + +procedure TTBCustomItemActionLink.SetEnabled(Value: Boolean); +begin + if IsEnabledLinked then FClient.Enabled := Value; +end; + +procedure TTBCustomItemActionLink.SetHelpContext(Value: THelpContext); +begin + if IsHelpContextLinked then FClient.HelpContext := Value; +end; + +procedure TTBCustomItemActionLink.SetHint(const Value: string); +begin + if IsHintLinked then FClient.Hint := Value; +end; + +procedure TTBCustomItemActionLink.SetImageIndex(Value: Integer); +begin + if IsImageIndexLinked then FClient.ImageIndex := Value; +end; + +procedure TTBCustomItemActionLink.SetShortCut(Value: TShortCut); +begin + if IsShortCutLinked then FClient.ShortCut := Value; +end; + +procedure TTBCustomItemActionLink.SetVisible(Value: Boolean); +begin + if IsVisibleLinked then FClient.Visible := Value; +end; + +procedure TTBCustomItemActionLink.SetOnExecute(Value: TNotifyEvent); +begin + if IsOnExecuteLinked then FClient.OnClick := Value; +end; + + +{ TTBCustomItem } + +{}function ItemContainingItems(const AItem: TTBCustomItem): TTBCustomItem; +begin + if Assigned(AItem) and Assigned(AItem.FLinkSubitems) then + Result := AItem.FLinkSubitems + else + Result := AItem; +end; + +constructor TTBCustomItem.Create(AOwner: TComponent); +begin + inherited; + FEnabled := True; + FImageIndex := -1; + FInheritOptions := True; + FItemStyle := [tbisSelectable, tbisRedrawOnSelChange, tbisRedrawOnMouseOverChange]; + FVisible := True; + ReferenceClickWnd; +end; + +destructor TTBCustomItem.Destroy; +var + I: Integer; +begin + Destroying; + RemoveFromClickList(Self); + { Changed in 0.33. Moved FParent.Remove call *after* the child items are + deleted. } + for I := Count-1 downto 0 do + Items[I].Free; + if Assigned(FParent) then + FParent.Remove(Self); + FreeMem(FItems); + FActionLink.Free; + FActionLink := nil; + FreeAndNil(FSubMenuImagesChangeLink); + FreeAndNil(FImagesChangeLink); + inherited; + if Assigned(FNotifyList) then begin + for I := FNotifyList.Count-1 downto 0 do + Dispose(PItemChangedNotificationData(FNotifyList[I])); + FNotifyList.Free; + end; + FLinkParents.Free; + ReleaseClickWnd; +end; + +{$IFDEF JR_D6} +function TTBCustomItem.IsAutoCheckStored: Boolean; +begin + Result := (ActionLink = nil) or not FActionLink.IsAutoCheckLinked; +end; +{$ENDIF} + +function TTBCustomItem.IsCaptionStored: Boolean; +begin + Result := (ActionLink = nil) or not FActionLink.IsCaptionLinked; +end; + +function TTBCustomItem.IsCheckedStored: Boolean; +begin + Result := (ActionLink = nil) or not FActionLink.IsCheckedLinked; +end; + +function TTBCustomItem.IsEnabledStored: Boolean; +begin + Result := (ActionLink = nil) or not FActionLink.IsEnabledLinked; +end; + +function TTBCustomItem.IsHintStored: Boolean; +begin + Result := (ActionLink = nil) or not FActionLink.IsHintLinked; +end; + +function TTBCustomItem.IsHelpContextStored: Boolean; +begin + Result := (ActionLink = nil) or not FActionLink.IsHelpContextLinked; +end; + +function TTBCustomItem.IsImageIndexStored: Boolean; +begin + Result := (ActionLink = nil) or not FActionLink.IsImageIndexLinked; +end; + +function TTBCustomItem.IsShortCutStored: Boolean; +begin + Result := (ActionLink = nil) or not FActionLink.IsShortCutLinked; +end; + +function TTBCustomItem.IsVisibleStored: Boolean; +begin + Result := (ActionLink = nil) or not FActionLink.IsVisibleLinked; +end; + +function TTBCustomItem.IsOnClickStored: Boolean; +begin + Result := (ActionLink = nil) or not FActionLink.IsOnExecuteLinked; +end; + +function TTBCustomItem.GetAction: TBasicAction; +begin + if FActionLink <> nil then + Result := FActionLink.Action + else + Result := nil; +end; + +function TTBCustomItem.GetActionLinkClass: TTBCustomItemActionLinkClass; +begin + Result := TTBCustomItemActionLink; +end; + +procedure TTBCustomItem.DoActionChange(Sender: TObject); +begin + if Sender = Action then ActionChange(Sender, False); +end; + +procedure TTBCustomItem.ActionChange(Sender: TObject; CheckDefaults: Boolean); +begin + if Action is TCustomAction then + with TCustomAction(Sender) do + begin + {$IFDEF JR_D6} + if not CheckDefaults or (Self.AutoCheck = False) then + Self.AutoCheck := AutoCheck; + {$ENDIF} + if not CheckDefaults or (Self.Caption = '') then + Self.Caption := Caption; + if not CheckDefaults or (Self.Checked = False) then + Self.Checked := Checked; + if not CheckDefaults or (Self.Enabled = True) then + Self.Enabled := Enabled; + if not CheckDefaults or (Self.HelpContext = 0) then + Self.HelpContext := HelpContext; + if not CheckDefaults or (Self.Hint = '') then + Self.Hint := Hint; + if not CheckDefaults or (Self.ImageIndex = -1) then + Self.ImageIndex := ImageIndex; + if not CheckDefaults or (Self.ShortCut = scNone) then + Self.ShortCut := ShortCut; + if not CheckDefaults or (Self.Visible = True) then + Self.Visible := Visible; + if not CheckDefaults or not Assigned(Self.OnClick) then + Self.OnClick := OnExecute; + end; +end; + +procedure TTBCustomItem.SetAction(Value: TBasicAction); +begin + if Value = nil then begin + FActionLink.Free; + FActionLink := nil; + end + else begin + if FActionLink = nil then + FActionLink := GetActionLinkClass.Create(Self); + FActionLink.Action := Value; + FActionLink.OnChange := DoActionChange; + { Note: Delphi's Controls.pas and Menus.pas merely check for + "csLoading in Value.ComponentState" here. But that doesn't help when + the Action property references an action on another form / data module + that has already finished loading. So we check two things: + 1. csLoading in Value.ComponentState + 2. csLoading in ComponentState + In the typical case where the item and action list reside on the same + form, #1 and #2 are both true. + Only #1 is true when Action references an action on another form / data + module that is created *after* the item (e.g. if Form1.TBItem1.Action = + Form2.Action1, and Form1 is created before Form2). + Only #2 is true when Action references an action on another form / data + module that is created *before* the item (e.g. if Form2.TBItem1.Action = + Form1.Action1, and Form1 is created before Form2). } + ActionChange(Value, (csLoading in Value.ComponentState) or + (csLoading in ComponentState)); + Value.FreeNotification(Self); + end; +end; + +procedure TTBCustomItem.InitiateAction; +begin + if FActionLink <> nil then FActionLink.Update; +end; + +procedure TTBCustomItem.Loaded; +begin + inherited; + if Action <> nil then ActionChange(Action, True); +end; + +procedure TTBCustomItem.GetChildren(Proc: TGetChildProc; Root: TComponent); +var + I: Integer; +begin + for I := 0 to FItemCount-1 do + Proc(FItems[I].Item); +end; + +procedure TTBCustomItem.SetChildOrder(Child: TComponent; Order: Integer); +var + I: Integer; +begin + I := IndexOf(Child as TTBCustomItem); + if I <> -1 then + Move(I, Order); +end; + +function TTBCustomItem.HasParent: Boolean; +begin + Result := True; +end; + +function TTBCustomItem.GetParentComponent: TComponent; +begin + if (FParent <> nil) and (FParent.FParentComponent <> nil) then + Result := FParent.FParentComponent + else + Result := FParent; +end; + +procedure TTBCustomItem.SetName(const NewName: TComponentName); +begin + if Name <> NewName then begin + inherited; + if Assigned(FParent) then + FParent.Notify(tbicNameChanged, -1, Self); + end; +end; + +procedure TTBCustomItem.SetParentComponent(Value: TComponent); +var + Intf: ITBItems; +begin + if FParent <> nil then FParent.Remove(Self); + if Value <> nil then begin + if Value is TTBCustomItem then + TTBCustomItem(Value).Add(Self) + else if Value.GetInterface(ITBItems, Intf) then + Intf.GetItems.Add(Self); + end; +end; + +procedure TTBCustomItem.Notification(AComponent: TComponent; + Operation: TOperation); +begin + inherited; + if Operation = opRemove then begin + RemoveFromList(FLinkParents, AComponent); + if AComponent = Action then Action := nil; + if AComponent = Images then Images := nil; + if AComponent = SubMenuImages then SubMenuImages := nil; + if AComponent = LinkSubitems then LinkSubitems := nil; + end; +end; + +procedure TTBCustomItem.IndexError; +begin + raise ETBItemError.Create(STBToolbarIndexOutOfBounds); +end; + +class procedure TTBCustomItem.ClickWndProc(var Message: TMessage); +var + List: TList; + I: Integer; + Item: TObject; +begin + if Message.Msg = WM_TB2K_CLICKITEM then begin + List := ClickList; { optimization... } + if Assigned(List) then begin + I := Message.LParam; + if (I >= 0) and (I < List.Count) then begin + Item := List[I]; + List[I] := nil; + if Item = Pointer(1) then { is it a destroyed item? } + Item := nil; + end + else + Item := nil; + + { Remove trailing nil items from ClickList. This is not *necessary*, but + it will make RemoveFromClickList faster if we clean out items that + aren't used, and may never be used again. } + for I := List.Count-1 downto 0 do begin + if List[I] = nil then + List.Delete(I) + else + Break; + end; + + if Assigned(Item) then begin + try + if Item is TTBCustomItem then + TTBCustomItem(Item).Click + else if Item is TTBItemViewer then + TTBItemViewer(Item).AccSelect(Message.WParam <> 0); + except + Application.HandleException(Item); + end; + end; + end; + end + else + with Message do + Result := DefWindowProc(ClickWnd, Msg, wParam, lParam); +end; + +procedure TTBCustomItem.PostClick; +{ Posts a message to the message queue that causes the item's Click handler to + be executed when control is returned to the message loop. + This should be called instead of Click when a WM_SYSCOMMAND message is + (possibly) currently being handled, because TApplication.WndProc's + CM_APPSYSCOMMAND handler disables the VCL's processing of focus messages + until the Perform(WM_SYSCOMMAND, ...) call returns. (An OnClick handler which + calls TForm.ShowModal needs focus messages to be enabled or else the form + will be shown with no initial focus.) } +begin + QueueClick(Self, 0); +end; + +procedure TTBCustomItem.Click; +begin + if Enabled then begin + { Following code based on D6's TMenuItem.Click } + {$IFDEF JR_D6} + if (not Assigned(ActionLink) and AutoCheck) or + (Assigned(ActionLink) and not ActionLink.IsAutoCheckLinked and AutoCheck) then + {$ELSE} + if AutoCheck then + {$ENDIF} + Checked := not Checked; + { Following code based on D4's TControl.Click } + { Call OnClick if assigned and not equal to associated action's OnExecute. + If associated action's OnExecute assigned then call it, otherwise, call + OnClick. } + if Assigned(FOnClick) and (Action <> nil) and + not MethodsEqual(TMethod(FOnClick), TMethod(Action.OnExecute)) then + FOnClick(Self) + else + if not(csDesigning in ComponentState) and (ActionLink <> nil) then + ActionLink.Execute {$IFDEF JR_D6}(Self){$ENDIF} + else + if Assigned(FOnClick) then + FOnClick(Self); + end; +end; + +function TTBCustomItem.GetItem(Index: Integer): TTBCustomItem; +begin + if (Index < 0) or (Index >= FItemCount) then IndexError; + Result := FItems[Index].Item; +end; + +procedure TTBCustomItem.Add(AItem: TTBCustomItem); +begin + Insert(Count, AItem); +end; + +procedure TTBCustomItem.InternalNotify(Ancestor: TTBCustomItem; + NestingLevel: Integer; Action: TTBItemChangedAction; Index: Integer; + Item: TTBCustomItem); +{ Note: Ancestor is Item's parent, or in the case of a group item relayed + notification, it can also be a group item which *links* to Item's parent + (i.e. ItemContainingItems(Ancestor) = Item.Parent). } + + procedure RelayToParentOf(const AItem: TTBCustomItem); + begin + if NestingLevel > MaxGroupLevel then + Exit; + if (tbisEmbeddedGroup in AItem.ItemStyle) and Assigned(AItem.Parent) then begin + if Ancestor = Self then + AItem.Parent.InternalNotify(AItem, NestingLevel + 1, Action, Index, Item) + else + { Don't alter Ancestor on subsequent relays; only on the first. } + AItem.Parent.InternalNotify(Ancestor, NestingLevel + 1, Action, Index, Item); + end; + end; + +var + I: Integer; + P: TTBCustomItem; + SaveProc: TTBItemChangedProc; +begin + { If Self is a group item, relay the notification to the parent } + RelayToParentOf(Self); + { If any group items are linked to Self, relay the notification to + those items' parents } + if Assigned(FLinkParents) then + for I := 0 to FLinkParents.Count-1 do begin + P := FLinkParents[I]; + if P <> Parent then + RelayToParentOf(P); + end; + if Assigned(FNotifyList) then begin + I := 0; + while I < FNotifyList.Count do begin + with PItemChangedNotificationData(FNotifyList[I])^ do begin + SaveProc := Proc; + Proc(Ancestor, Ancestor <> Self, Action, Index, Item); + end; + { Is I now out of bounds? } + if I >= FNotifyList.Count then + Break; + { Only proceed to the next index if the list didn't change } + if MethodsEqual(TMethod(PItemChangedNotificationData(FNotifyList[I])^.Proc), + TMethod(SaveProc)) then + Inc(I); + end; + end; +end; + +procedure TTBCustomItem.Notify(Action: TTBItemChangedAction; Index: Integer; + Item: TTBCustomItem); +begin + InternalNotify(Self, 0, Action, Index, Item); +end; + +procedure TTBCustomItem.ViewBeginUpdate; +begin + Notify(tbicSubitemsBeginUpdate, -1, nil); +end; + +procedure TTBCustomItem.ViewEndUpdate; +begin + Notify(tbicSubitemsEndUpdate, -1, nil); +end; + +procedure TTBCustomItem.Insert(NewIndex: Integer; AItem: TTBCustomItem); +begin + if Assigned(AItem.FParent) then + raise ETBItemError.Create(STBToolbarItemReinserted); + if (NewIndex < 0) or (NewIndex > FItemCount) then IndexError; + InsertIntoItemArray(FItems, FItemCount, NewIndex, AItem); + AItem.FParent := Self; + ViewBeginUpdate; + try + Notify(tbicInserted, NewIndex, AItem); + AItem.RefreshOptions; + finally + ViewEndUpdate; + end; +end; + +procedure TTBCustomItem.Delete(Index: Integer); +begin + if (Index < 0) or (Index >= FItemCount) then IndexError; + Notify(tbicDeleting, Index, FItems[Index].Item); + FItems[Index].Item.FParent := nil; + DeleteFromItemArray(FItems, FItemCount, Index); +end; + +function TTBCustomItem.IndexOf(AItem: TTBCustomItem): Integer; +var + I: Integer; +begin + for I := 0 to FItemCount-1 do + if FItems[I].Item = AItem then begin + Result := I; + Exit; + end; + Result := -1; +end; + +procedure TTBCustomItem.Remove(Item: TTBCustomItem); +var + I: Integer; +begin + I := IndexOf(Item); + //if I = -1 then raise ETBItemError.Create(STBToolbarItemNotFound); + if I <> -1 then + Delete(I); +end; + +procedure TTBCustomItem.Clear; +var + I: Integer; +begin + for I := Count-1 downto 0 do + Items[I].Free; +end; + +procedure TTBCustomItem.Move(CurIndex, NewIndex: Integer); +var + Item: TTBCustomItem; +begin + if CurIndex <> NewIndex then begin + if (NewIndex < 0) or (NewIndex >= FItemCount) then IndexError; + Item := Items[CurIndex]; + ViewBeginUpdate; + try + Delete(CurIndex); + Insert(NewIndex, Item); + finally + ViewEndUpdate; + end; + end; +end; + +function TTBCustomItem.ContainsItem(AItem: TTBCustomItem): Boolean; +begin + while Assigned(AItem) and (AItem <> Self) do + AItem := AItem.Parent; + Result := Assigned(AItem); +end; + +procedure TTBCustomItem.RegisterNotification(ANotify: TTBItemChangedProc); +var + I: Integer; + Data: PItemChangedNotificationData; +begin + if FNotifyList = nil then FNotifyList := TList.Create; + for I := 0 to FNotifyList.Count-1 do + with PItemChangedNotificationData(FNotifyList[I])^ do + if MethodsEqual(TMethod(ANotify), TMethod(Proc)) then begin + Inc(RefCount); + Exit; + end; + FNotifyList.Expand; + New(Data); + Data.Proc := ANotify; + Data.RefCount := 1; + FNotifyList.Add(Data); +end; + +procedure TTBCustomItem.UnregisterNotification(ANotify: TTBItemChangedProc); +var + I: Integer; + Data: PItemChangedNotificationData; +begin + if Assigned(FNotifyList) then + for I := 0 to FNotifyList.Count-1 do begin + Data := FNotifyList[I]; + if MethodsEqual(TMethod(Data.Proc), TMethod(ANotify)) then begin + Dec(Data.RefCount); + if Data.RefCount = 0 then begin + FNotifyList.Delete(I); + Dispose(Data); + if FNotifyList.Count = 0 then begin + FNotifyList.Free; + FNotifyList := nil; + end; + end; + Break; + end; + end; +end; + +function TTBCustomItem.GetPopupWindowClass: TTBPopupWindowClass; +begin + Result := TTBPopupWindow; +end; + +procedure TTBCustomItem.DoPopup(Sender: TTBCustomItem; FromLink: Boolean); +begin + if Assigned(FOnPopup) then + FOnPopup(Sender, FromLink); + if not(tbisCombo in ItemStyle) then + Click; +end; + +var + PlayedSound: Boolean = False; + +function TTBCustomItem.CreatePopup(const ParentView: TTBView; + const ParentViewer: TTBItemViewer; const PositionAsSubmenu, SelectFirstItem, + Customizing: Boolean; const APopupPoint: TPoint; + const Alignment: TTBPopupAlignment): TTBPopupWindow; + + function CountObscured(X, Y, W, H: Integer): Integer; + var + I: Integer; + P: TPoint; + V: TTBItemViewer; + begin + Result := 0; + if ParentView = nil then + Exit; + P := ParentView.FWindow.ClientToScreen(Point(0, 0)); + Dec(X, P.X); + Dec(Y, P.Y); + Inc(W, X); + Inc(H, Y); + for I := 0 to ParentView.FViewerCount-1 do begin + V := ParentView.FViewers[I]; + if V.Show and (V.BoundsRect.Left >= X) and (V.BoundsRect.Right <= W) and + (V.BoundsRect.Top >= Y) and (V.BoundsRect.Bottom <= H) then + Inc(Result); + end; + end; + +var + EventItem, ParentItem: TTBCustomItem; + Opposite: Boolean; + ChevronParentView: TTBView; + X, X2, Y, Y2, W, H: Integer; + P: TPoint; + RepeatCalcX: Boolean; + ParentItemRect: TRect; + MonitorRect: TRect; + AnimDir: TTBAnimationDirection; +begin + EventItem := ItemContainingItems(Self); + if EventItem <> Self then + EventItem.DoPopup(Self, True); + DoPopup(Self, False); + + ChevronParentView := GetChevronParentView; + if ChevronParentView = nil then + ParentItem := Self + else + ParentItem := ChevronParentView.FParentItem; + + Opposite := Assigned(ParentView) and (vsOppositePopup in ParentView.FState); + Result := GetPopupWindowClass.CreatePopupWindow(nil, ParentView, ParentItem, + Customizing); + try + if Assigned(ChevronParentView) then begin + ChevronParentView.FreeNotification(Result.View); + Result.View.FChevronParentView := ChevronParentView; + Result.View.FIsToolbar := True; + Result.View.Style := Result.View.Style + + (ChevronParentView.Style * [vsAlwaysShowHints]); + Result.Color := clBtnFace; + end; + + { Calculate ParentItemRect, and MonitorRect (the rectangle of the monitor + that the popup window will be confined to) } + if Assigned(ParentView) then begin + ParentView.ValidatePositions; + ParentItemRect := ParentViewer.BoundsRect; + P := ParentView.FWindow.ClientToScreen(Point(0, 0)); + OffsetRect(ParentItemRect, P.X, P.Y); + if not IsRectEmpty(ParentView.FMonitorRect) then + MonitorRect := ParentView.FMonitorRect + else + MonitorRect := GetRectOfMonitorContainingRect(ParentItemRect, False); + end + else begin + ParentItemRect.TopLeft := APopupPoint; + ParentItemRect.BottomRight := APopupPoint; + MonitorRect := GetRectOfMonitorContainingPoint(APopupPoint, False); + end; + Result.View.FMonitorRect := MonitorRect; + + { Initialize item positions and size of the popup window } + if ChevronParentView = nil then + Result.View.FMaxHeight := (MonitorRect.Bottom - MonitorRect.Top) - + (PopupMenuWindowNCSize * 2) + else + Result.View.WrapOffset := (MonitorRect.Right - MonitorRect.Left) - + (PopupMenuWindowNCSize * 2); + if SelectFirstItem then + Result.View.Selected := Result.View.FirstSelectable; + Result.View.UpdatePositions; + W := Result.Width; + H := Result.Height; + + { Calculate initial X,Y position of the popup window } + if Assigned(ParentView) then begin + if not PositionAsSubmenu then begin + if ChevronParentView = nil then begin + if (ParentView = nil) or (ParentView.FOrientation <> tbvoVertical) then begin + if GetSystemMetrics(SM_MENUDROPALIGNMENT) = 0 then + X := ParentItemRect.Left + else + X := ParentItemRect.Right - W; + Y := ParentItemRect.Bottom; + end + else begin + X := ParentItemRect.Left - W; + Y := ParentItemRect.Top; + end; + end + else begin + if ChevronParentView.FOrientation <> tbvoVertical then begin + X := ParentItemRect.Right - W; + Y := ParentItemRect.Bottom; + end + else begin + X := ParentItemRect.Left - W; + Y := ParentItemRect.Top; + end; + end; + end + else begin + X := ParentItemRect.Right - PopupMenuWindowNCSize; + Y := ParentItemRect.Top - PopupMenuWindowNCSize; + end; + end + else begin + X := APopupPoint.X; + Y := APopupPoint.Y; + case Alignment of + tbpaRight: Dec(X, W); + tbpaCenter: Dec(X, W div 2); + end; + end; + + { Adjust the Y position of the popup window } + { If the window is going off the bottom of the monitor, try placing it + above the parent item } + if (Y + H > MonitorRect.Bottom) and + ((ParentView = nil) or (ParentView.FOrientation <> tbvoVertical)) then begin + if not PositionAsSubmenu then + Y2 := ParentItemRect.Top + else + Y2 := ParentItemRect.Bottom + PopupMenuWindowNCSize; + Dec(Y2, H); + { Only place it above the parent item if it isn't going to go off the + top of the monitor } + if Y2 >= MonitorRect.Top then + Y := Y2; + end; + { If it's still going off the bottom (which can be possible if a menu bar + was off the screen to begin with), clip it to the bottom of the monitor } + if Y + H > MonitorRect.Bottom then + Y := MonitorRect.Bottom - H; + if Y < MonitorRect.Top then + Y := MonitorRect.Top; + + { Other adjustments to the position of the popup window } + if not PositionAsSubmenu then begin + if (ParentView = nil) and (Alignment = tbpaRight) and (X < MonitorRect.Left) then + Inc(X, W); + if X + W > MonitorRect.Right then begin + if Assigned(ParentView) or (Alignment <> tbpaLeft) then + X := MonitorRect.Right; + Dec(X, W); + end; + if X < MonitorRect.Left then + X := MonitorRect.Left; + if (ParentView = nil) or (ParentView.FOrientation <> tbvoVertical) then begin + Y2 := ParentItemRect.Top - H; + if Y2 >= MonitorRect.Top then begin + { Would the popup window obscure less items if it popped out to the + top instead? } + if (CountObscured(X, Y2, W, H) < CountObscured(X, Y, W, H)) or + ((Y < ParentItemRect.Bottom) and (Y + H > ParentItemRect.Top) and + (X < ParentItemRect.Right) and (X + W > ParentItemRect.Left)) then + Y := Y2; + end; + { Make sure a tall popup window doesn't overlap the parent item } + if (Y < ParentItemRect.Bottom) and (Y + H > ParentItemRect.Top) and + (X < ParentItemRect.Right) and (X + W > ParentItemRect.Left) then begin + if ParentItemRect.Right + W <= MonitorRect.Right then + X := ParentItemRect.Right + else + X := ParentItemRect.Left - W; + if X < MonitorRect.Top then + X := MonitorRect.Top; + end; + end + else begin + X2 := ParentItemRect.Right; + if X2 + W <= MonitorRect.Right then begin + { Would the popup window obscure less items if it popped out to the + right instead? } + if (CountObscured(X2, Y, W, H) < CountObscured(X, Y, W, H)) or + ((Y < ParentItemRect.Bottom) and (Y + H > ParentItemRect.Top) and + (X < ParentItemRect.Right) and (X + W > ParentItemRect.Left)) then + X := X2; + end; + { Make sure a wide popup window doesn't overlap the parent item } + if (Y < ParentItemRect.Bottom) and (Y + H > ParentItemRect.Top) and + (X < ParentItemRect.Right) and (X + W > ParentItemRect.Left) then begin + if ParentItemRect.Bottom + H <= MonitorRect.Bottom then + Y := ParentItemRect.Bottom + else + Y := ParentItemRect.Top - H; + if Y < MonitorRect.Top then + Y := MonitorRect.Top; + end; + end; + end + else begin + { Make nested submenus go from left to right on the screen. Each it + runs out of space on the screen, switch directions } + repeat + RepeatCalcX := False; + X2 := X; + if Opposite or (X2 + W > MonitorRect.Right) then begin + if Assigned(ParentView) then + X2 := ParentItemRect.Left + PopupMenuWindowNCSize; + Dec(X2, W); + if not Opposite then + Include(Result.View.FState, vsOppositePopup) + else begin + if X2 < MonitorRect.Left then begin + Opposite := False; + RepeatCalcX := True; + end + else + Include(Result.View.FState, vsOppositePopup); + end; + end; + until not RepeatCalcX; + X := X2; + if X < MonitorRect.Left then + X := MonitorRect.Left; + end; + + { Determine animation direction } + AnimDir := []; + if not PositionAsSubmenu then begin + if Y >= ParentItemRect.Bottom then + Include(AnimDir, tbadDown) + else if Y + H <= ParentItemRect.Top then + Include(AnimDir, tbadUp); + if X >= ParentItemRect.Right then + Include(AnimDir, tbadRight) + else if X + W <= ParentItemRect.Left then + Include(AnimDir, tbadLeft); + end + else begin + if X + W div 2 >= ParentItemRect.Left + (ParentItemRect.Right - ParentItemRect.Left) div 2 then + Include(AnimDir, tbadRight) + else + Include(AnimDir, tbadLeft); + end; + Result.FAnimationDirection := AnimDir; + + Result.SetBounds(X, Y, W, H); + if Assigned(ParentView) then begin + Result.FreeNotification(ParentView); + ParentView.FOpenViewerWindow := Result; + ParentView.FOpenViewerView := Result.View; + ParentView.FOpenViewer := ParentViewer; + if ParentView.FIsToolbar then begin + Include(ParentView.FState, vsDropDownMenus); + ParentView.Invalidate(ParentViewer); + ParentView.FWindow.Update; + end; + end; + Include(Result.View.FState, vsDrawInOrder); + if not NeedToPlaySound('MenuPopup') then begin + { Don't call PlaySound if we don't have to } + Result.Visible := True; + end + else begin + if not PlayedSound then begin + { Work around Windows 2000 "bug" where there's a 1/3 second delay upon the + first call to PlaySound (or sndPlaySound) by painting the window + completely first. This way the delay isn't very noticable. } + PlayedSound := True; + Result.Visible := True; + Result.Update; + PlaySound('MenuPopup', 0, SND_ALIAS or SND_ASYNC or SND_NODEFAULT or SND_NOSTOP); + end + else begin + PlaySound('MenuPopup', 0, SND_ALIAS or SND_ASYNC or SND_NODEFAULT or SND_NOSTOP); + Result.Visible := True; + end; + end; + CallNotifyWinEvent(EVENT_SYSTEM_MENUPOPUPSTART, Result.View.FWindow.Handle, + OBJID_CLIENT, CHILDID_SELF); + { Call NotifyFocusEvent now that the window is visible } + if Assigned(Result.View.Selected) then + Result.View.NotifyFocusEvent; + except + Result.Free; + raise; + end; +end; + +function TTBCustomItem.OpenPopup(const SelectFirstItem, TrackRightButton: Boolean; + const PopupPoint: TPoint; const Alignment: TTBPopupAlignment; + const ReturnClickedItemOnly: Boolean): TTBCustomItem; +var + ModalHandler: TTBModalHandler; + Popup: TTBPopupWindow; + DoneActionData: TTBDoneActionData; +begin + ModalHandler := TTBModalHandler.Create(0); + try + Popup := CreatePopup(nil, nil, False, SelectFirstItem, False, PopupPoint, + Alignment); + try + Include(Popup.View.FState, vsIgnoreFirstMouseUp); + ModalHandler.RootPopup := Popup; + ModalHandler.Loop(Popup.View, False, False, False, TrackRightButton); + DoneActionData := Popup.View.FDoneActionData; + finally + ModalHandler.RootPopup := nil; + { Remove vsModal state from the root view before any TTBView.Destroy + methods get called, so that NotifyFocusEvent becomes a no-op } + Exclude(Popup.View.FState, vsModal); + Popup.Free; + end; + finally + ModalHandler.Free; + end; + Result := ProcessDoneAction(DoneActionData, ReturnClickedItemOnly); +end; + +function TTBCustomItem.Popup(X, Y: Integer; TrackRightButton: Boolean; + Alignment: TTBPopupAlignment = tbpaLeft; + ReturnClickedItemOnly: Boolean = False): TTBCustomItem; +var + P: TPoint; +begin + P.X := X; + P.Y := Y; + Result := OpenPopup(False, TrackRightButton, P, Alignment, + ReturnClickedItemOnly); +end; + +function TTBCustomItem.FindItemWithShortCut(AShortCut: TShortCut; + var ATopmostParent: TTBCustomItem): TTBCustomItem; + + function DoItem(AParentItem: TTBCustomItem; LinkDepth: Integer): TTBCustomItem; + var + I: Integer; + NewParentItem, Item: TTBCustomItem; + begin + Result := nil; + NewParentItem := AParentItem; + if Assigned(NewParentItem.LinkSubitems) then begin + NewParentItem := NewParentItem.LinkSubitems; + Inc(LinkDepth); + if LinkDepth > 25 then + Exit; { prevent infinite link recursion } + end; + for I := 0 to NewParentItem.Count-1 do begin + Item := NewParentItem.Items[I]; + if Item.ShortCut = AShortCut then begin + Result := Item; + Exit; + end; + Result := DoItem(Item, LinkDepth); + if Assigned(Result) then begin + ATopmostParent := Item; + Exit; + end; + end; + end; + +begin + ATopmostParent := nil; + Result := DoItem(Self, 0); +end; + +function TTBCustomItem.IsShortCut(var Message: TWMKey): Boolean; +var + ShortCut: TShortCut; + ShiftState: TShiftState; + ShortCutItem, TopmostItem, Item, EventItem: TTBCustomItem; + I: Integer; +label 1; +begin + Result := False; + ShiftState := KeyDataToShiftState(Message.KeyData); + ShortCut := Menus.ShortCut(Message.CharCode, ShiftState); +1:ShortCutItem := FindItemWithShortCut(ShortCut, TopmostItem); + if Assigned(ShortCutItem) then begin + { Send OnPopup/OnClick events to ShortCutItem's parents so that they can + update the Enabled state of ShortCutItem if needed } + Item := Self; + repeat + if not Item.Enabled then + Exit; + EventItem := ItemContainingItems(Item); + if not(csDesigning in ComponentState) then begin + for I := 0 to EventItem.Count-1 do + EventItem.Items[I].InitiateAction; + end; + if not(tbisEmbeddedGroup in Item.ItemStyle) then begin + if EventItem <> Item then begin + try + EventItem.DoPopup(Item, True); + except + Application.HandleException(Self); + end; + end; + try + Item.DoPopup(Item, False); + except + Application.HandleException(Self); + end; + end; + ShortCutItem := Item.FindItemWithShortCut(ShortCut, TopmostItem); + if ShortCutItem = nil then + { Can no longer find the shortcut inside TopmostItem. Start over + because the shortcut might have moved. } + goto 1; + Item := TopmostItem; + until Item = nil; + if ShortCutItem.Enabled then begin + try + ShortCutItem.Click; + except + Application.HandleException(Self); + end; + Result := True; + end; + end; +end; + +function TTBCustomItem.GetChevronParentView: TTBView; +begin + Result := nil; +end; + +function TTBCustomItem.GetItemViewerClass(AView: TTBView): TTBItemViewerClass; +begin + Result := TTBItemViewer; +end; + +function TTBCustomItem.NeedToRecreateViewer(AViewer: TTBItemViewer): Boolean; +begin + Result := False; +end; + +function TTBCustomItem.GetShortCutText: String; +var + P: Integer; +begin + P := Pos(#9, Caption); + if P = 0 then begin + if ShortCut <> 0 then + Result := ShortCutToText(ShortCut) + else + Result := ''; + end + else + Result := Copy(Caption, P+1, Maxint); +end; + +procedure TTBCustomItem.Change(NeedResize: Boolean); +const + ItemChangedActions: array[Boolean] of TTBItemChangedAction = + (tbicInvalidate, tbicInvalidateAndResize); +begin + if Assigned(FParent) then + FParent.Notify(ItemChangedActions[NeedResize], -1, Self); +end; + +procedure TTBCustomItem.RecreateItemViewers; +begin + if Assigned(FParent) then + FParent.Notify(tbicRecreateItemViewers, -1, Self); +end; + +procedure TTBCustomItem.ImageListChangeHandler(Sender: TObject); +var + Resize: Boolean; +begin + if Sender = FSubMenuImages then begin + FSubMenuImagesChangeLink.FLastWidth := FSubMenuImages.Width; + FSubMenuImagesChangeLink.FLastHeight := FSubMenuImages.Height; + SubMenuImagesChanged; + end + else begin + { Sender is FImages } + Resize := False; + if (FImagesChangeLink.FLastWidth <> FImages.Width) or + (FImagesChangeLink.FLastHeight <> FImages.Height) then begin + FImagesChangeLink.FLastWidth := FImages.Width; + FImagesChangeLink.FLastHeight := FImages.Height; + Resize := True; + end; + Change(Resize); + end; +end; + +procedure TTBCustomItem.SubMenuImagesChanged; +begin + Notify(tbicSubMenuImagesChanged, -1, nil); +end; + +procedure TTBCustomItem.TurnSiblingsOff; +var + I: Integer; + Item: TTBCustomItem; +begin + if (GroupIndex <> 0) and Assigned(FParent) then begin + for I := 0 to FParent.Count-1 do begin + Item := FParent[I]; + if (Item <> Self) and (Item.GroupIndex = GroupIndex) then + Item.Checked := False; + end; + end; +end; + +procedure TTBCustomItem.SetCaption(Value: String); +begin + if FCaption <> Value then begin + FCaption := Value; + Change(True); + end; +end; + +procedure TTBCustomItem.SetChecked(Value: Boolean); +begin + if FChecked <> Value then begin + FChecked := Value; + Change(False); + if Value then + TurnSiblingsOff; + end; +end; + +procedure TTBCustomItem.SetDisplayMode(Value: TTBItemDisplayMode); +begin + if FDisplayMode <> Value then begin + FDisplayMode := Value; + Change(True); + end; +end; + +procedure TTBCustomItem.EnabledChanged; +begin + Change(False); +end; + +procedure TTBCustomItem.SetEnabled(Value: Boolean); +begin + if FEnabled <> Value then begin + FEnabled := Value; + EnabledChanged; + end; +end; + +procedure TTBCustomItem.SetGroupIndex(Value: Integer); +begin + if FGroupIndex <> Value then begin + FGroupIndex := Value; + if Checked then + TurnSiblingsOff; + end; +end; + +procedure TTBCustomItem.SetImageIndex(Value: TImageIndex); +var + HadNoImage: Boolean; +begin + if FImageIndex <> Value then begin + HadNoImage := FImageIndex = -1; + FImageIndex := Value; + Change(HadNoImage xor (Value = -1)); + end; +end; + +function TTBCustomItem.ChangeImages(var AImages: TCustomImageList; + const Value: TCustomImageList; var AChangeLink: TTBImageChangeLink): Boolean; +{ Returns True if image list was resized } +var + LastWidth, LastHeight: Integer; +begin + Result := False; + LastWidth := -1; + LastHeight := -1; + if Assigned(AImages) then begin + LastWidth := AImages.Width; + LastHeight := AImages.Height; + AImages.UnregisterChanges(AChangeLink); + if Value = nil then begin + AChangeLink.Free; + AChangeLink := nil; + Result := True; + end; + end; + AImages := Value; + if Assigned(Value) then begin + Result := (Value.Width <> LastWidth) or (Value.Height <> LastHeight); + if AChangeLink = nil then begin + AChangeLink := TTBImageChangeLink.Create; + AChangeLink.FLastWidth := Value.Width; + AChangeLink.FLastHeight := Value.Height; + AChangeLink.OnChange := ImageListChangeHandler; + end; + Value.RegisterChanges(AChangeLink); + Value.FreeNotification(Self); + end; +end; + +procedure TTBCustomItem.SetImages(Value: TCustomImageList); +begin + if FImages <> Value then + Change(ChangeImages(FImages, Value, FImagesChangeLink)); +end; + +procedure TTBCustomItem.SetSubMenuImages(Value: TCustomImageList); +begin + if FSubMenuImages <> Value then begin + ChangeImages(FSubMenuImages, Value, FSubMenuImagesChangeLink); + SubMenuImagesChanged; + end; +end; + +procedure TTBCustomItem.SetInheritOptions(Value: Boolean); +begin + if FInheritOptions <> Value then begin + FInheritOptions := Value; + RefreshOptions; + end; +end; + +procedure TTBCustomItem.SetLinkSubitems(Value: TTBCustomItem); +begin + if Value = Self then + Value := nil; + if FLinkSubitems <> Value then begin + if Assigned(FLinkSubitems) then + RemoveFromList(FLinkSubitems.FLinkParents, Self); + FLinkSubitems := Value; + if Assigned(Value) then begin + Value.FreeNotification(Self); + AddToList(Value.FLinkParents, Self); + end; + Notify(tbicSubitemsChanged, -1, nil); + end; +end; + +function TTBCustomItem.FixOptions(const AOptions: TTBItemOptions): TTBItemOptions; +begin + Result := AOptions; + if not(tboToolbarStyle in Result) then + Exclude(Result, tboToolbarSize); +end; + +procedure TTBCustomItem.RefreshOptions; +const + NonInheritedOptions = [tboDefault]; + ChangeOptions = [tboDefault, tboDropdownArrow, tboImageAboveCaption, + tboNoRotation, tboSameWidth, tboToolbarStyle, tboToolbarSize]; +var + OldOptions, NewOptions: TTBItemOptions; + I: Integer; + Item: TTBCustomItem; +begin + OldOptions := FEffectiveOptions; + if FInheritOptions and Assigned(FParent) then + NewOptions := FParent.FEffectiveOptions - NonInheritedOptions + else + NewOptions := []; + NewOptions := FixOptions(NewOptions - FMaskOptions + FOptions); + if FEffectiveOptions <> NewOptions then begin + FEffectiveOptions := NewOptions; + if (OldOptions * ChangeOptions) <> (NewOptions * ChangeOptions) then + Change(True); + for I := 0 to FItemCount-1 do begin + Item := FItems[I].Item; + if Item.FInheritOptions then + Item.RefreshOptions; + end; + end; +end; + +procedure TTBCustomItem.SetMaskOptions(Value: TTBItemOptions); +begin + if FMaskOptions <> Value then begin + FMaskOptions := Value; + RefreshOptions; + end; +end; + +procedure TTBCustomItem.SetOptions(Value: TTBItemOptions); +begin + Value := FixOptions(Value); + if FOptions <> Value then begin + FOptions := Value; + RefreshOptions; + end; +end; + +procedure TTBCustomItem.SetRadioItem(Value: Boolean); +begin + if FRadioItem <> Value then begin + FRadioItem := Value; + Change(False); + end; +end; + +procedure TTBCustomItem.SetVisible(Value: Boolean); +begin + if FVisible <> Value then begin + FVisible := Value; + Change(True); + end; +end; + + +{ TTBGroupItem } + +constructor TTBGroupItem.Create(AOwner: TComponent); +begin + inherited; + ItemStyle := ItemStyle + [tbisEmbeddedGroup, tbisSubitemsEditable]; +end; + + +{ TTBSubmenuItem } + +constructor TTBSubmenuItem.Create(AOwner: TComponent); +begin + inherited; + ItemStyle := ItemStyle + [tbisSubMenu, tbisSubitemsEditable]; +end; + +function TTBSubmenuItem.GetDropdownCombo: Boolean; +begin + Result := tbisCombo in ItemStyle; +end; + +procedure TTBSubmenuItem.SetDropdownCombo(Value: Boolean); +begin + if (tbisCombo in ItemStyle) <> Value then begin + if Value then + ItemStyle := ItemStyle + [tbisCombo] + else + ItemStyle := ItemStyle - [tbisCombo]; + Change(True); + end; +end; + + +{ TTBSeparatorItem } + +constructor TTBSeparatorItem.Create(AOwner: TComponent); +begin + inherited; + ItemStyle := ItemStyle - [tbisSelectable, tbisRedrawOnSelChange, + tbisRedrawOnMouseOverChange] + [tbisSeparator, tbisClicksTransparent]; +end; + +function TTBSeparatorItem.GetItemViewerClass(AView: TTBView): TTBItemViewerClass; +begin + Result := TTBSeparatorItemViewer; +end; + +procedure TTBSeparatorItem.SetBlank(Value: Boolean); +begin + if FBlank <> Value then begin + FBlank := Value; + Change(False); + end; +end; + + +{ TTBSeparatorItemViewer } + +procedure TTBSeparatorItemViewer.CalcSize(const Canvas: TCanvas; + var AWidth, AHeight: Integer); +begin + if not IsToolbarStyle then + Inc(AHeight, DivRoundUp(GetTextHeight(Canvas.Handle) * 2, 3)) + else begin + AWidth := 6; + AHeight := 6; + end; +end; + +procedure TTBSeparatorItemViewer.Paint(const Canvas: TCanvas; + const ClientAreaRect: TRect; IsSelected, IsPushed, UseDisabledShadow: Boolean); +var + DC: HDC; + R: TRect; + ToolbarStyle, Horiz, LineSep: Boolean; +begin + DC := Canvas.Handle; + if TTBSeparatorItem(Item).FBlank then + Exit; + + R := ClientAreaRect; + ToolbarStyle := IsToolbarStyle; + Horiz := not ToolbarStyle or (View.FOrientation = tbvoVertical); + LineSep := tbisLineSep in State; + if LineSep then + Horiz := not Horiz; + if Horiz then begin + R.Top := R.Bottom div 2 - 1; + if not ToolbarStyle then + InflateRect(R, -tbMenuSeparatorOffset, 0) + else if LineSep then begin + if View.FOrientation = tbvoFloating then + InflateRect(R, -tbLineSepOffset, 0) + else + InflateRect(R, -tbDockedLineSepOffset, 0); + end; + DrawEdge(DC, R, EDGE_ETCHED, BF_TOP); + end + else begin + R.Left := R.Right div 2 - 1; + if LineSep then + InflateRect(R, 0, -tbDockedLineSepOffset); + DrawEdge(DC, R, EDGE_ETCHED, BF_LEFT); + end; +end; + +function TTBSeparatorItemViewer.UsesSameWidth: Boolean; +begin + Result := False; +end; + + +{ TTBControlItem } + +constructor TTBControlItem.Create(AOwner: TComponent); +begin + inherited; + ItemStyle := ItemStyle - [tbisSelectable] + [tbisClicksTransparent]; +end; + +constructor TTBControlItem.CreateControlItem(AOwner: TComponent; + AControl: TControl); +begin + FControl := AControl; + AControl.FreeNotification(Self); + Create(AOwner); +end; + +destructor TTBControlItem.Destroy; +begin + inherited; + { Free the associated control *after* the item is completely destroyed } + if not FDontFreeControl and Assigned(FControl) and + not(csAncestor in FControl.ComponentState) then + FControl.Free; +end; + +procedure TTBControlItem.Notification(AComponent: TComponent; + Operation: TOperation); +begin + inherited; + if (Operation = opRemove) and (AComponent = FControl) then + Control := nil; +end; + +procedure TTBControlItem.SetControl(Value: TControl); +begin + if FControl <> Value then begin + FControl := Value; + if Assigned(Value) then + Value.FreeNotification(Self); + Change(True); + end; +end; + + +{ TTBItemViewer } + +constructor TTBItemViewer.Create(AView: TTBView; AItem: TTBCustomItem; + AGroupLevel: Integer); +begin + FItem := AItem; + FView := AView; + FGroupLevel := AGroupLevel; + ReferenceClickWnd; +end; + +destructor TTBItemViewer.Destroy; +begin + RemoveFromClickList(Self); + if Assigned(FAccObjectInstance) then begin + FAccObjectInstance.ClientIsDestroying; + FAccObjectInstance := nil; + end; + inherited; + ReleaseClickWnd; +end; + +function TTBItemViewer.GetAccObject: IDispatch; +begin + if FAccObjectInstance = nil then begin + if not InitializeOleAcc then begin + Result := nil; + Exit; + end; + FAccObjectInstance := TTBItemViewerAccObject.Create(Self); + end; + Result := FAccObjectInstance; +end; + +procedure TTBItemViewer.AccSelect(const AExecute: Boolean); +{ Called by ClickWndProc when an item of type TTBItemViewer is in ClickList } +var + Obj: IDispatch; +begin + { Ensure FAccObjectInstance is created by calling GetAccObject } + Obj := GetAccObject; + if Assigned(Obj) then + (FAccObjectInstance as TTBItemViewerAccObject).HandleAccSelect(AExecute); +end; + +procedure TTBItemViewer.PostAccSelect(const AExecute: Boolean); +{ Internally called by TTBItemViewerAccObject. Don't call directly. } +begin + QueueClick(Self, Ord(AExecute)); +end; + +function TTBItemViewer.IsAccessible: Boolean; +{ Returns True if MSAA clients should know about the viewer, specifically + if it's either shown, off-edge, or clipped (in other words, not completely + invisible/inaccessible). } +begin + { Note: Can't simply check Item.Visible because the chevron item's Visible + property is always True } + Result := Show or OffEdge or Clipped; +end; + +function TTBItemViewer.GetCaptionText: String; +var + P: Integer; +begin + Result := Item.Caption; + P := Pos(#9, Result); + if P <> 0 then + SetLength(Result, P-1); +end; + +function TTBItemViewer.GetHintText: String; +begin + Result := GetShortHint(Item.Hint); + { If there is no short hint, use the caption for the hint. Like Office, + strip any trailing colon or ellipsis. } + if (Result = '') and not(tboNoAutoHint in Item.EffectiveOptions) and + (not(tbisSubmenu in Item.ItemStyle) or (tbisCombo in Item.ItemStyle) or + not CaptionShown) then + Result := StripAccelChars(StripTrailingPunctuation(GetCaptionText)); + { Call associated action's OnHint event handler to post-process the hint } + if Assigned(Item.ActionLink) and + (Item.ActionLink.Action is TCustomAction) then begin + if not TCustomAction(Item.ActionLink.Action).DoHint(Result) then + Result := ''; + { Note: TControlActionLink.DoShowHint actually misinterprets the result + of DoHint, but we get it right... } + end; + { Add shortcut text } + if (Result <> '') and Application.HintShortCuts and + (Item.ShortCut <> scNone) then + Result := Format('%s (%s)', [Result, ShortCutToText(Item.ShortCut)]); +end; + +function TTBItemViewer.CaptionShown: Boolean; +begin + Result := (GetCaptionText <> '') and (not IsToolbarSize or + (Item.ImageIndex < 0) or (Item.DisplayMode in [nbdmTextOnly, nbdmImageAndText])) or + (tboImageAboveCaption in Item.EffectiveOptions); +end; + +function TTBItemViewer.ImageShown: Boolean; +begin + {}{should also return false if Images=nil (use UsedImageList?)} + ImageShown := (Item.ImageIndex >= 0) and + ((Item.DisplayMode in [nbdmDefault, nbdmImageAndText]) or + (IsToolbarStyle and (Item.DisplayMode = nbdmTextOnlyInMenus))); +end; + +function TTBItemViewer.GetImageList: TCustomImageList; +var + V: TTBView; +begin + Result := Item.Images; + if Assigned(Result) then + Exit; + V := View; + repeat + if Assigned(V.FCurParentItem) then begin + Result := V.FCurParentItem.SubMenuImages; + if Assigned(Result) then + Break; + end; + if Assigned(V.FParentItem) then begin + Result := V.FParentItem.SubMenuImages; + if Assigned(Result) then + Break; + end; + V := V.FParentView; + until V = nil; +end; + +function TTBItemViewer.IsRotated: Boolean; +{ Returns True if the caption should be drawn with rotated (vertical) text, + underneath the image } +begin + Result := (View.Orientation = tbvoVertical) and + not (tboNoRotation in Item.EffectiveOptions) and + not (tboImageAboveCaption in Item.EffectiveOptions); +end; + +procedure TTBItemViewer.CalcSize(const Canvas: TCanvas; + var AWidth, AHeight: Integer); +var + ToolbarStyle: Boolean; + DC: HDC; + TextMetrics: TTextMetric; + H, LeftMargin: Integer; + ImgList: TCustomImageList; + S: String; + RotatedFont, SaveFont: HFONT; +begin + ToolbarStyle := IsToolbarStyle; + DC := Canvas.Handle; + ImgList := GetImageList; + if ToolbarStyle then begin + AWidth := 6; + AHeight := 6; + end + else begin + AWidth := 0; + AHeight := 0; + end; + if not ToolbarStyle or CaptionShown then begin + if not IsRotated then begin + GetTextMetrics(DC, TextMetrics); + Inc(AHeight, TextMetrics.tmHeight); + Inc(AWidth, GetTextWidth(DC, GetCaptionText, True)); + if ToolbarStyle then + Inc(AWidth, 6); + end + else begin + { Vertical text isn't always the same size as horizontal text, so we have + to select the rotated font into the DC to get an accurate size } + RotatedFont := CreateRotatedFont(DC); + SaveFont := SelectObject(DC, RotatedFont); + GetTextMetrics(DC, TextMetrics); + Inc(AWidth, TextMetrics.tmHeight); + Inc(AHeight, GetTextWidth(DC, GetCaptionText, True)); + if ToolbarStyle then + Inc(AHeight, 6); + SelectObject(DC, SaveFont); + DeleteObject(RotatedFont); + end; + end; + if ToolbarStyle and ImageShown and Assigned(ImgList) then begin + if not IsRotated and not(tboImageAboveCaption in Item.EffectiveOptions) then begin + Inc(AWidth, ImgList.Width + 1); + if AHeight < ImgList.Height + 6 then + AHeight := ImgList.Height + 6; + end + else begin + Inc(AHeight, ImgList.Height); + if AWidth < ImgList.Width + 7 then + AWidth := ImgList.Width + 7; + end; + end; + if ToolbarStyle and (tbisSubmenu in Item.ItemStyle) then begin + if tbisCombo in Item.ItemStyle then + Inc(AWidth, tbDropdownComboArrowWidth) + else + if tboDropdownArrow in Item.EffectiveOptions then begin + if View.Orientation <> tbvoVertical then + Inc(AWidth, tbDropdownArrowWidth) + else + Inc(AHeight, tbDropdownArrowWidth); + end; + end; + if not ToolbarStyle then begin + Inc(AHeight, TextMetrics.tmExternalLeading + tbMenuVerticalMargin); + if Assigned(ImgList) then begin + H := ImgList.Height + 3; + if H > AHeight then + AHeight := H; + LeftMargin := MulDiv(ImgList.Width + 3, AHeight, H); + end + else + LeftMargin := AHeight; + Inc(AWidth, LeftMargin + tbMenuImageTextSpace + tbMenuLeftTextMargin + + tbMenuRightTextMargin); + S := Item.GetShortCutText; + if S <> '' then + Inc(AWidth, (AHeight - 6) + GetTextWidth(DC, S, True)); + Inc(AWidth, AHeight); + end; +end; + +procedure TTBItemViewer.DrawItemCaption(const Canvas: TCanvas; ARect: TRect; + const ACaption: String; ADrawDisabledShadow: Boolean; AFormat: UINT); +var + DC: HDC; + + procedure Draw; + begin + if not IsRotated then + DrawText(DC, PChar(ACaption), Length(ACaption), ARect, AFormat) + else + DrawRotatedText(DC, ACaption, ARect, AFormat); + end; + +var + ShadowColor, HighlightColor, SaveTextColor: DWORD; +begin + DC := Canvas.Handle; + if not ADrawDisabledShadow then + Draw + else begin + ShadowColor := GetSysColor(COLOR_BTNSHADOW); + HighlightColor := GetSysColor(COLOR_BTNHIGHLIGHT); + OffsetRect(ARect, 1, 1); + SaveTextColor := SetTextColor(DC, HighlightColor); + Draw; + OffsetRect(ARect, -1, -1); + SetTextColor(DC, ShadowColor); + Draw; + SetTextColor(DC, SaveTextColor); + end; +end; + +procedure TTBItemViewer.Paint(const Canvas: TCanvas; + const ClientAreaRect: TRect; IsSelected, IsPushed, UseDisabledShadow: Boolean); +var + ShowEnabled, HasArrow: Boolean; + MenuCheckWidth, MenuCheckHeight: Integer; + + function GetDrawTextFlags: UINT; + begin + Result := 0; + if not AreKeyboardCuesEnabled and (vsUseHiddenAccels in View.FStyle) and + not(vsShowAccels in View.FState) then + Result := DT_HIDEPREFIX; + end; + + procedure DrawSubmenuArrow; + var + BR: TRect; + Bmp: TBitmap; + + procedure DrawWithColor(AColor: TColor); + const + ROP_DSPDxax = $00E20746; + var + DC: HDC; + SaveTextColor, SaveBkColor: TColorRef; + begin + Canvas.Brush.Color := AColor; + DC := Canvas.Handle; + SaveTextColor := SetTextColor(DC, clWhite); + SaveBkColor := SetBkColor(DC, clBlack); + BitBlt(DC, BR.Left, BR.Top, MenuCheckWidth, MenuCheckHeight, + Bmp.Canvas.Handle, 0, 0, ROP_DSPDxax); + SetBkColor(DC, SaveBkColor); + SetTextColor(DC, SaveTextColor); + Canvas.Brush.Style := bsClear; + end; + + begin + Bmp := TBitmap.Create; + try + Bmp.Monochrome := True; + Bmp.Width := MenuCheckWidth; + Bmp.Height := MenuCheckHeight; + BR := Rect(0, 0, MenuCheckWidth, MenuCheckHeight); + DrawFrameControl(Bmp.Canvas.Handle, BR, DFC_MENU, DFCS_MENUARROW); + OffsetRect(BR, ClientAreaRect.Right - MenuCheckWidth, + ClientAreaRect.Top + ((ClientAreaRect.Bottom - ClientAreaRect.Top) - MenuCheckHeight) div 2); + if not UseDisabledShadow then begin + if ShowEnabled and (tbisCombo in Item.ItemStyle) and IsSelected then begin + OffsetRect(BR, 1, 1); + DrawWithColor(clBtnText); + end + else + DrawWithColor(Canvas.Font.Color); + end + else begin + OffsetRect(BR, 1, 1); + DrawWithColor(clBtnHighlight); + OffsetRect(BR, -1, -1); + DrawWithColor(clBtnShadow); + end; + finally + Bmp.Free; + end; + end; + + procedure DrawDropdownArrow(R: TRect; Rotated: Boolean); + + procedure DrawWithColor(AColor: TColor); + var + X, Y: Integer; + P: array[0..2] of TPoint; + begin + X := (R.Left + R.Right) div 2; + Y := (R.Top + R.Bottom) div 2; + if not Rotated then begin + Dec(Y); + P[0].X := X-2; + P[0].Y := Y; + P[1].X := X+2; + P[1].Y := Y; + P[2].X := X; + P[2].Y := Y+2; + end + else begin + Dec(X); + P[0].X := X; + P[0].Y := Y+2; + P[1].X := X; + P[1].Y := Y-2; + P[2].X := X-2; + P[2].Y := Y; + end; + Canvas.Pen.Color := AColor; + Canvas.Brush.Color := AColor; + Canvas.Polygon(P); + end; + + begin + if not UseDisabledShadow then + DrawWithColor(Canvas.Font.Color) + else begin + OffsetRect(R, 1, 1); + DrawWithColor(clBtnHighlight); + OffsetRect(R, -1, -1); + DrawWithColor(clBtnShadow); + end; + end; + + function GetDitherBitmap: TBitmap; + begin + Result := AllocPatternBitmap(clBtnFace, clBtnHighlight); + Result.HandleType := bmDDB; { needed for Win95, or else brush is solid white } + end; + +const + EdgeStyles: array[Boolean] of UINT = (BDR_RAISEDINNER, BDR_SUNKENOUTER); + CheckMarkPoints: array[0..11] of TPoint = ( + { Black } + (X: -2; Y: -2), (X: 0; Y: 0), (X: 4; Y: -4), + (X: 4; Y: -3), (X: 0; Y: 1), (X: -2; Y: -1), + (X: -2; Y: -2), + { White } + (X: -3; Y: -2), (X: -3; Y: -1), (X: 0; Y: 2), + (X: 5; Y: -3), (X: 5; Y: -5)); +var + ToolbarStyle, ImageIsShown: Boolean; + R, RC, RD: TRect; + S: String; + ImgList: TCustomImageList; + I, X, Y: Integer; + Points: array[0..11] of TPoint; + DrawTextFlags: UINT; + LeftMargin: Integer; + TextMetrics: TTextMetric; +begin + ToolbarStyle := IsToolbarStyle; + ShowEnabled := Item.Enabled or View.Customizing; + HasArrow := (tbisSubmenu in Item.ItemStyle) and + ((tbisCombo in Item.ItemStyle) or (tboDropdownArrow in Item.EffectiveOptions)); + MenuCheckWidth := GetSystemMetrics(SM_CXMENUCHECK); + MenuCheckHeight := GetSystemMetrics(SM_CYMENUCHECK); + ImgList := GetImageList; + ImageIsShown := ImageShown and Assigned(ImgList); + LeftMargin := 0; + if not ToolbarStyle then begin + if Assigned(ImgList) then + LeftMargin := MulDiv(ImgList.Width + 3, ClientAreaRect.Bottom, ImgList.Height + 3) + else + LeftMargin := ClientAreaRect.Bottom; + end; + + { Border } + RC := ClientAreaRect; + if ToolbarStyle then begin + if HasArrow then begin + if tbisCombo in Item.ItemStyle then begin + Dec(RC.Right, tbDropdownComboMargin); + RD := RC; + Dec(RC.Right, tbDropdownComboArrowWidth - tbDropdownComboMargin); + RD.Left := RC.Right; + end + else begin + if View.Orientation <> tbvoVertical then + RD := Rect(RC.Right - tbDropdownArrowWidth - tbDropdownArrowMargin, 0, + RC.Right - tbDropdownArrowMargin, RC.Bottom) + else + RD := Rect(0, RC.Bottom - tbDropdownArrowWidth - tbDropdownArrowMargin, + RC.Right, RC.Bottom - tbDropdownArrowMargin); + end; + end + else + SetRectEmpty(RD); + if (IsSelected and ShowEnabled) or Item.Checked or + (csDesigning in Item.ComponentState) then begin + if not(tbisCombo in Item.ItemStyle) then + DrawEdge(Canvas.Handle, RC, EdgeStyles[IsPushed or Item.Checked], BF_RECT) + else begin + DrawEdge(Canvas.Handle, RC, EdgeStyles[(IsPushed and View.FCapture) or Item.Checked], BF_RECT); + if (IsSelected and ShowEnabled) or + (csDesigning in Item.ComponentState) then + DrawEdge(Canvas.Handle, RD, EdgeStyles[IsPushed and not View.FCapture], BF_RECT); + end; + end; + if HasArrow then begin + if not(tbisCombo in Item.ItemStyle) and IsPushed then + OffsetRect(RD, 1, 1); + DrawDropdownArrow(RD, not(tbisCombo in Item.ItemStyle) and + (View.Orientation = tbvoVertical)); + end; + InflateRect(RC, -1, -1); + if Item.Checked and not (IsSelected and ShowEnabled) then begin + Canvas.Brush.Bitmap := GetDitherBitmap; + Canvas.FillRect(RC); + Canvas.Brush.Style := bsClear; + end; + InflateRect(RC, -1, -1); + if Item.Checked or + ((IsSelected and IsPushed) and + (not(tbisCombo in Item.ItemStyle) or View.FCapture)) then + OffsetRect(RC, 1, 1); + if HasArrow and not(tbisCombo in Item.ItemStyle) then begin + if View.Orientation <> tbvoVertical then + Dec(RC.Right, tbDropdownArrowWidth) + else + Dec(RC.Bottom, tbDropdownArrowWidth); + end; + end + else begin + { On selected menu items, fill the background with the selected color. + Note: This assumes the brush color was not changed from the initial + value. } + if IsSelected then begin + R := RC; + if ImageIsShown or Item.Checked then + Inc(R.Left, LeftMargin + tbMenuImageTextSpace); + if (tbisCombo in Item.ItemStyle) and IsSelected and ShowEnabled then + Dec(R.Right, MenuCheckWidth); + Canvas.FillRect(R); + end; + end; + + { Adjust brush & font } + Canvas.Brush.Style := bsClear; + if tboDefault in Item.EffectiveOptions then + with Canvas.Font do Style := Style + [fsBold]; + GetTextMetrics(Canvas.Handle, TextMetrics); + + { Caption } + if CaptionShown then begin + S := GetCaptionText; + R := RC; + DrawTextFlags := GetDrawTextFlags; + if ToolbarStyle then begin + if ImageIsShown then begin + if not IsRotated and not(tboImageAboveCaption in Item.EffectiveOptions) then + Inc(R.Left, ImgList.Width + 1) + else + Inc(R.Top, ImgList.Height + 1); + end; + DrawItemCaption(Canvas, R, S, UseDisabledShadow, + DT_SINGLELINE or DT_CENTER or DT_VCENTER or DrawTextFlags) + end + else begin + Inc(R.Left, LeftMargin + tbMenuImageTextSpace + tbMenuLeftTextMargin); + { Like standard menus, shift the text up one pixel if the text height + is 4 pixels less than the total item height. This is done so underlined + characters aren't displayed too low. } + if (R.Bottom - R.Top) - (TextMetrics.tmHeight + TextMetrics.tmExternalLeading) = tbMenuVerticalMargin then + Dec(R.Bottom); + Inc(R.Top, TextMetrics.tmExternalLeading); + DrawItemCaption(Canvas, R, S, UseDisabledShadow, + DT_SINGLELINE or DT_LEFT or DT_VCENTER or DrawTextFlags); + end; + end; + + { Shortcut and/or submenu arrow (menus only) } + if not ToolbarStyle then begin + S := Item.GetShortCutText; + if S <> '' then begin + R := RC; + R.Left := R.Right - (R.Bottom - R.Top) - GetTextWidth(Canvas.Handle, S, True); + { Like standard menus, shift the text up one pixel if the text height + is 4 pixels less than the total item height. This is done so underlined + characters aren't displayed too low. } + if (R.Bottom - R.Top) - (TextMetrics.tmHeight + TextMetrics.tmExternalLeading) = tbMenuVerticalMargin then + Dec(R.Bottom); + Inc(R.Top, TextMetrics.tmExternalLeading); + DrawItemCaption(Canvas, R, S, UseDisabledShadow, + DT_SINGLELINE or DT_LEFT or DT_VCENTER or DT_NOPREFIX); + end; + if tbisSubmenu in Item.ItemStyle then begin + if tbisCombo in Item.ItemStyle then begin + R := RC; + R.Left := R.Right - MenuCheckWidth; + if IsSelected and ShowEnabled then + DrawEdge(Canvas.Handle, R, BDR_SUNKENOUTER, BF_RECT or BF_MIDDLE) + else begin + Dec(R.Left); + if not IsSelected then + DrawEdge(Canvas.Handle, R, EDGE_ETCHED, BF_LEFT) + else + DrawEdge(Canvas.Handle, R, BDR_SUNKENOUTER, BF_LEFT); + end; + end; + DrawSubmenuArrow; + end; + end; + + { Image, or check box } + if ImageIsShown or (not ToolbarStyle and Item.Checked) then begin + R := RC; + if ToolbarStyle then begin + if not IsRotated and not(tboImageAboveCaption in Item.EffectiveOptions) then + R.Right := R.Left + ImgList.Width + 2 + else + R.Bottom := R.Top + ImgList.Height + 2; + end + else begin + R.Right := R.Left + LeftMargin; + if (IsSelected and ShowEnabled) or Item.Checked then + DrawEdge(Canvas.Handle, R, EdgeStyles[Item.Checked], BF_RECT or BF_MIDDLE); + if Item.Checked and not IsSelected then begin + InflateRect(R, -1, -1); + Canvas.Brush.Bitmap := GetDitherBitmap; + Canvas.FillRect(R); + Canvas.Brush.Style := bsClear; + InflateRect(R, 1, 1); + end; + if Item.Checked then + OffsetRect(R, 1, 1); + end; + if ImageIsShown then begin + X := R.Left + ((R.Right - R.Left) - ImgList.Width) div 2; + Y := R.Top + ((R.Bottom - R.Top) - ImgList.Height) div 2; + if ImgList is TTBCustomImageList then + TTBCustomImageList(ImgList).DrawState(Canvas, X, Y, Item.ImageIndex, + ShowEnabled, IsSelected, Item.Checked) + else + ImgList.Draw(Canvas, X, Y, Item.ImageIndex, ShowEnabled); + end + else + if not ToolbarStyle and Item.Checked then begin + { Draw default check mark or radio button image when user hasn't + specified their own } + X := (R.Left + R.Right) div 2; + Y := (R.Top + R.Bottom) div 2; + if Item.RadioItem then begin + Canvas.Pen.Color := clBtnText; + Canvas.Brush.Color := clBtnText; + Canvas.RoundRect(X-3, Y-3, X+2, Y+2, 2, 2); + Canvas.Pen.Color := clBtnHighlight; + Canvas.Brush.Style := bsClear; + Canvas.RoundRect(X-4, Y-4, X+3, Y+3, 6, 6); + end + else begin + Dec(X, 2); + Inc(Y); + System.Move(CheckMarkPoints, Points, 12 * SizeOf(TPoint)); + for I := Low(Points) to High(Points) do begin + Inc(Points[I].X, X); + Inc(Points[I].Y, Y); + end; + Canvas.Pen.Color := clBtnText; + Polyline(Canvas.Handle, Points[0], 7); + Canvas.Pen.Color := clBtnHighlight; + Polyline(Canvas.Handle, Points[7], 5); + end; + end; + end; +end; + +procedure TTBItemViewer.GetCursor(const Pt: TPoint; var ACursor: HCURSOR); +begin +end; + +function TTBItemViewer.GetIndex: Integer; +begin + Result := View.IndexOf(Self); +end; + +function TTBItemViewer.IsToolbarSize: Boolean; +begin + Result := View.FIsToolbar or (tboToolbarSize in Item.FEffectiveOptions); +end; + +function TTBItemViewer.IsToolbarStyle: Boolean; +begin + Result := View.FIsToolbar or (tboToolbarStyle in Item.FEffectiveOptions); +end; + +function TTBItemViewer.IsPtInButtonPart(X, Y: Integer): Boolean; +var + W: Integer; +begin + Result := not(tbisSubmenu in Item.ItemStyle); + if tbisCombo in Item.ItemStyle then begin + if IsToolbarStyle then + W := tbDropdownComboArrowWidth + else + W := GetSystemMetrics(SM_CXMENUCHECK); + Result := X < (BoundsRect.Right - BoundsRect.Left) - W; + end; +end; + +procedure TTBItemViewer.MouseDown(Shift: TShiftState; X, Y: Integer; + var MouseDownOnMenu: Boolean); + + procedure HandleDefaultDoubleClick(const View: TTBView); + { Looks for a tboDefault item in View and ends the modal loop if it finds + one. } + var + I: Integer; + Viewer: TTBItemViewer; + Item: TTBCustomItem; + begin + for I := 0 to View.FViewerCount-1 do begin + Viewer := View.FViewers[I]; + Item := Viewer.Item; + if (Viewer.Show or Viewer.Clipped) and (tboDefault in Item.EffectiveOptions) and + (tbisSelectable in Item.ItemStyle) and Item.Enabled and Item.Visible then begin + Viewer.Execute(True); + Break; + end; + end; + end; + +var + WasAlreadyOpen: Boolean; +begin + if not Item.Enabled then begin + if (View.FParentView = nil) and not View.FIsPopup then + View.EndModal; + Exit; + end; + if IsPtInButtonPart(X, Y) then begin + if IsToolbarStyle then begin + View.CancelChildPopups; + View.SetCapture; + View.Invalidate(Self); + end; + end + else begin + WasAlreadyOpen := (View.FOpenViewer = Self); + if View.OpenChildPopup(False) then begin + if WasAlreadyOpen and ((View.FParentView = nil) and not View.FIsPopup) then + MouseDownOnMenu := True; + if (ssDouble in Shift) and not(tbisCombo in Item.ItemStyle) then + HandleDefaultDoubleClick(View.FOpenViewerView); + end; + end; +end; + +procedure TTBItemViewer.MouseMove(X, Y: Integer); +begin +end; + +procedure TTBItemViewer.MouseUp(X, Y: Integer; MouseWasDownOnMenu: Boolean); +var + HadCapture, IsToolbarItem: Boolean; +begin + HadCapture := View.FCapture; + View.CancelCapture; + IsToolbarItem := (View.FParentView = nil) and not View.FIsPopup; + if not View.FMouseOverSelected or not Item.Enabled or + (tbisClicksTransparent in Item.ItemStyle) then begin + if IsToolbarItem then + View.EndModal; + Exit; + end; + if (tbisSubmenu in Item.ItemStyle) and not IsPtInButtonPart(X, Y) then begin + if IsToolbarItem and MouseWasDownOnMenu then + View.EndModal; + end + else begin + { it's a 'normal' item } + if not IsToolbarStyle or HadCapture then + Execute(True); + end; +end; + +procedure TTBItemViewer.MouseWheel(WheelDelta, X, Y: Integer); +begin +end; + +procedure TTBItemViewer.LosingCapture; +begin + View.Invalidate(Self); +end; + +procedure TTBItemViewer.Entering; +begin + if Assigned(Item.FOnSelect) then + Item.FOnSelect(Item, Self, True); +end; + +procedure TTBItemViewer.Leaving; +begin + if Assigned(Item.FOnSelect) then + Item.FOnSelect(Item, Self, False); +end; + +procedure TTBItemViewer.KeyDown(var Key: Word; Shift: TShiftState); +begin +end; + +function TTBItemViewer.ScreenToClient(const P: TPoint): TPoint; +begin + Result := View.FWindow.ScreenToClient(P); + Dec(Result.X, BoundsRect.Left); + Dec(Result.Y, BoundsRect.Top); +end; + +function TTBItemViewer.UsesSameWidth: Boolean; +{ If UsesSameWidth returns True, the item viewer's width will be expanded to + match the widest item viewer on the same view whose UsesSameWidth method + also returns True. } +begin + Result := (tboImageAboveCaption in Item.FEffectiveOptions) and + (tboSameWidth in Item.FEffectiveOptions) and IsToolbarSize; +end; + +function TTBItemViewer.DoExecute: Boolean; +{ Low-level 'execute' handler. Returns True if the caller should call + GivePriority on the viewer (normally, if the 'execute' operation was a + success and the modal loop is ending). } +begin + View.EndModalWithClick(Self); + Result := True; +end; + +procedure TTBItemViewer.Execute(AGivePriority: Boolean); +{ Calls DoExecute and, if applicable, View.GivePriority. Note that it is up to + the caller to check the viewer's visibility and enabled state. } +begin + if DoExecute and AGivePriority then + View.GivePriority(Self); +end; + +function TTBItemViewer.GetAccRole: Integer; +{ Returns the MSAA "role" of the viewer. } +const + { Constants from OleAcc.h } + ROLE_SYSTEM_CLIENT = $a; + ROLE_SYSTEM_MENUITEM = $c; + ROLE_SYSTEM_SEPARATOR = $15; + ROLE_SYSTEM_PUSHBUTTON = $2b; + ROLE_SYSTEM_BUTTONMENU = $39; +begin + if Item is TTBControlItem then + Result := ROLE_SYSTEM_CLIENT + else if tbisSeparator in Item.ItemStyle then + Result := ROLE_SYSTEM_SEPARATOR + else if View.IsPopup or (vsMenuBar in View.Style) then + Result := ROLE_SYSTEM_MENUITEM + else if tbisSubmenu in Item.ItemStyle then + Result := ROLE_SYSTEM_BUTTONMENU + else + Result := ROLE_SYSTEM_PUSHBUTTON; +end; + +function TTBItemViewer.GetAccValue(var Value: WideString): Boolean; +{ Gets the MSAA "value" text of the viewer. Returns True if something was + assigned to Value, or False if the viewer does not possess a "value". } +begin + Result := False; +end; + + +{ TTBView } + +constructor TTBView.CreateView(AOwner: TComponent; AParentView: TTBView; + AParentItem: TTBCustomItem; AWindow: TWinControl; + AIsToolbar, ACustomizing, AUsePriorityList: Boolean); +begin + Create(AOwner); + FBackgroundColor := clDefault; + FCustomizing := ACustomizing; + FIsPopup := not AIsToolbar; + FIsToolbar := AIsToolbar; + FNewViewersGetHighestPriority := True; + FParentView := AParentView; + FParentItem := AParentItem; + if Assigned(FParentItem) then begin + //FIsToolbar := FIsToolbar or FParentItem.FDisplayAsToolbar; + FParentItem.RegisterNotification(LinkNotification); + FParentItem.FreeNotification(Self); + end; + FUsePriorityList := AUsePriorityList; + FWindow := AWindow; + UpdateCurParentItem; +end; + +destructor TTBView.Destroy; +begin + CloseChildPopups; + if Assigned(FAccObjectInstance) then begin + FAccObjectInstance.ClientIsDestroying; + { Get rid of our own reference to FAccObjectInstance. Normally the + reference count will be now be zero and FAccObjectInstance will be + freed, unless MSAA still holds a reference. } + FAccObjectInstance._Release; + FAccObjectInstance := nil; + end; + { If parent view is a toolbar, invalidate the open item so that it's + redrawn back in the "up" position } + if Assigned(ParentView) and ParentView.FIsToolbar then begin + Include(ParentView.FState, vsNoAnimation); + if Assigned(ParentView.FOpenViewer) then + ParentView.Invalidate(ParentView.FOpenViewer); + end; + if Assigned(FCurParentItem) then + FCurParentItem.UnregisterNotification(ItemNotification); + if Assigned(FParentItem) then + FParentItem.UnregisterNotification(LinkNotification); + inherited; + FPriorityList.Free; + FreeViewers; + { Now that we're destroyed, "focus" the parent view } + if Assigned(FParentView) then + FParentView.NotifyFocusEvent; +end; + +function TTBView.GetAccObject: IDispatch; +begin + if FAccObjectInstance = nil then begin + if not InitializeOleAcc then begin + Result := nil; + Exit; + end; + FAccObjectInstance := TTBViewAccObject.Create(Self); + { Strictly as an optimization, take a reference for ourself and keep it + for the lifetime of the view. (Destroy calls _Release.) } + FAccObjectInstance._AddRef; + end; + Result := FAccObjectInstance; +end; + +function TTBView.HandleWMGetObject(var Message: TMessage): Boolean; +begin + if (Message.LParam = Integer(OBJID_CLIENT)) and InitializeOleAcc then begin + Message.Result := LresultFromObjectFunc(ITBAccessible, Message.WParam, GetAccObject); + Result := True; + end + else + Result := False; +end; + +procedure TTBView.UpdateCurParentItem; +var + Value: TTBCustomItem; +begin + Value := ItemContainingItems(FParentItem); + if FCurParentItem <> Value then begin + CloseChildPopups; + if Assigned(FCurParentItem) then + FCurParentItem.UnregisterNotification(ItemNotification); + FCurParentItem := Value; + if Assigned(Value) then + Value.RegisterNotification(ItemNotification); + RecreateAllViewers; + if Assigned(Value) and not(csDesigning in Value.ComponentState) then + InitiateActions; + end; +end; + +procedure TTBView.InitiateActions; +var + I: Integer; +begin + { Use a 'while' instead of a 'for' since an InitiateAction implementation + may add/delete items } + I := 0; + while I < FViewerCount do begin + FViewers[I].Item.InitiateAction; + Inc(I); + end; +end; + +procedure TTBView.Notification(AComponent: TComponent; Operation: TOperation); +begin + inherited; + if Operation = opRemove then begin + if AComponent = FParentItem then begin + FParentItem := nil; + UpdateCurParentItem; + if Assigned(FParentView) then + FParentView.CloseChildPopups; + end + else if AComponent = FOpenViewerWindow then begin + FOpenViewerWindow := nil; + FOpenViewerView := nil; + FOpenViewer := nil; + end + else if AComponent = FChevronParentView then + FChevronParentView := nil; + end +end; + +function TTBView.ContainsView(AView: TTBView): Boolean; +begin + while Assigned(AView) and (AView <> Self) do + AView := AView.FParentView; + Result := Assigned(AView); +end; + +function TTBView.GetRootView: TTBView; +begin + Result := Self; + while Assigned(Result.FParentView) do + Result := Result.FParentView; +end; + +function TTBView.GetParentToolbarView: TTBView; +begin + Result := Self; + while Assigned(Result) and not Result.FIsToolbar do + Result := Result.FParentView; +end; + +procedure TTBView.FreeViewers; +var + VI: PTBItemViewerArray; + I, C: Integer; +begin + if Assigned(FViewers) then begin + VI := FViewers; + C := FViewerCount; + FViewers := nil; + FViewerCount := 0; + for I := C-1 downto 0 do + FreeAndNil(VI[I]); + FreeMem(VI); + end; +end; + +procedure TTBView.InvalidatePositions; +begin + if FValidated then begin + FValidated := False; + if Assigned(FWindow) and FWindow.HandleAllocated then + InvalidateRect(FWindow.Handle, nil, True); + end; +end; + +procedure TTBView.ValidatePositions; +begin + if not FValidated then + UpdatePositions; +end; + +procedure TTBView.TryValidatePositions; +begin + if (FUpdating = 0) and + (not Assigned(FParentItem) or not(csLoading in FParentItem.ComponentState)) and + (not Assigned(FParentItem.Owner) or not(csLoading in FParentItem.Owner.ComponentState)) then + ValidatePositions; +end; + +(*procedure TTBView.TryRevalidatePositions; +begin + if FValidated then begin + if FUpdating = 0 then begin + FreePositions; + UpdatePositions; + end + else + InvalidatePositions; + end; +end;*) + +function TTBView.Find(Item: TTBCustomItem): TTBItemViewer; +var + I: Integer; +begin + for I := 0 to FViewerCount-1 do + if FViewers[I].Item = Item then begin + Result := FViewers[I]; + Exit; + end; + raise ETBItemError.Create(STBViewerNotFound); +end; + +function TTBView.IndexOf(AViewer: TTBItemViewer): Integer; +var + I: Integer; +begin + if Assigned(AViewer) then + for I := 0 to FViewerCount-1 do + if FViewers[I] = AViewer then begin + Result := I; + Exit; + end; + Result := -1; +end; + + +procedure TTBView.DeletingViewer(Viewer: TTBItemViewer); +begin + if FSelected = Viewer then + FSelected := nil; + if FOpenViewer = Viewer then + CloseChildPopups; +end; + +procedure TTBView.RecreateItemViewer(const I: Integer); +var + OldViewer, NewViewer: TTBItemViewer; + J: Integer; +begin + OldViewer := FViewers[I]; + DeletingViewer(OldViewer); + NewViewer := OldViewer.Item.GetItemViewerClass(Self).Create(Self, + OldViewer.Item, OldViewer.FGroupLevel); + FViewers[I] := NewViewer; + if Assigned(FPriorityList) then begin + J := FPriorityList.IndexOf(OldViewer); + if J <> -1 then + FPriorityList[J] := NewViewer; + end; + OldViewer.Free; +end; + +function TTBView.InsertItemViewers(const NewIndex: Integer; + const AItem: TTBCustomItem; const AGroupLevel: Integer; + const AddToPriorityList, TopOfPriorityList: Boolean): Integer; +var + NewViewer: TTBItemViewer; + LinkItem: TTBCustomItem; + I: Integer; +begin + if AGroupLevel > MaxGroupLevel then begin + Result := 0; + Exit; + end; + + NewViewer := AItem.GetItemViewerClass(Self).Create(Self, AItem, + AGroupLevel); + InsertIntoViewerArray(FViewers, FViewerCount, NewIndex, + NewViewer); + if AddToPriorityList and FUsePriorityList then begin + if not TopOfPriorityList then + AddToList(FPriorityList, NewViewer) + else + { When new items are inserted programmatically at run-time, place + them at the top of FPriorityList } + AddToFrontOfList(FPriorityList, NewViewer); + end; + Result := 1; + + { If a new group item is being inserted, insert all its child items too } + if not FCustomizing and (tbisEmbeddedGroup in AItem.ItemStyle) then begin + LinkItem := ItemContainingItems(AItem); + for I := 0 to LinkItem.Count-1 do begin + Inc(Result, InsertItemViewers(NewIndex + Result, LinkItem.FItems[I].Item, + AGroupLevel + 1, AddToPriorityList, TopOfPriorityList)); + end; + end; +end; + +procedure TTBView.ItemNotification(Ancestor: TTBCustomItem; Relayed: Boolean; + Action: TTBItemChangedAction; Index: Integer; Item: TTBCustomItem); + + procedure ItemInserted; + var + NewLevel, Start, InsertPoint, Last: Integer; + GroupItem, NextItem: TTBCustomItem; + Found, SearchAgain: Boolean; + begin + InvalidatePositions; + NewLevel := 0; + Start := 0; + if Ancestor = FCurParentItem then + InsertPoint := FViewerCount + else begin + { Ancestor <> FCurParentItem, so apparently an item has been inserted + inside a group item } + repeat + Found := False; + while Start < FViewerCount do begin + GroupItem := FViewers[Start].Item; + if (tbisEmbeddedGroup in GroupItem.ItemStyle) and (GroupItem = Ancestor) then begin + NewLevel := FViewers[Start].FGroupLevel + 1; + Inc(Start); + Found := True; + Break; + end; + Inc(Start); + end; + if not Found then + { Couldn't find Ancestor; it shouldn't get here } + Exit; + InsertPoint := Start; + SearchAgain := False; + while (InsertPoint < FViewerCount) and + (FViewers[InsertPoint].FGroupLevel >= NewLevel) do begin + if (FViewers[InsertPoint].Item = Item) and + (FViewers[InsertPoint].FGroupLevel = NewLevel) then begin + { If the item we were going to insert already exists, then there + must be multiple instances of the same group item. This can + happen when are two group items on the same toolbar each + linking to the same submenu item, with the submenu item + containing a group item of its own, and an item is inserted + inside that. } + SearchAgain := True; + Break; + end; + Inc(InsertPoint); + end; + until not SearchAgain; + end; + if InsertPoint = FViewerCount then begin + { Don't add items after the chevron or MDI buttons item } + Dec(InsertPoint, FInternalViewersAtEnd); + if InsertPoint < 0 then + InsertPoint := 0; { just in case? } + end; + { If the new item wasn't placed at the end, adjust InsertPoint accordingly } + if Index < Item.Parent.Count-1 then begin + Last := InsertPoint; + InsertPoint := Start; + NextItem := Item.Parent.FItems[Index+1].Item; + while (InsertPoint < Last) and + ((FViewers[InsertPoint].Item <> NextItem) or + (FViewers[InsertPoint].FGroupLevel <> NewLevel)) do + Inc(InsertPoint); + end; + InsertItemViewers(InsertPoint, Item, NewLevel, True, + not(csLoading in Item.ComponentState) and FNewViewersGetHighestPriority); + end; + + procedure ItemDeleting; + + procedure DeleteItem(DeleteIndex: Integer); + var + Viewer: TTBItemViewer; + begin + Viewer := FViewers[DeleteIndex]; + DeletingViewer(Viewer); + RemoveFromList(FPriorityList, Viewer); + FreeAndNil(Viewer); + DeleteFromViewerArray(FViewers, FViewerCount, DeleteIndex); + end; + + var + I: Integer; + DeleteLevel: Integer; + begin + InvalidatePositions; + I := 0; + DeleteLevel := 0; + while I < FViewerCount do begin + if DeleteLevel > 0 then begin + if FViewers[I].FGroupLevel >= DeleteLevel then begin + DeleteItem(I); + Continue; + end + else + DeleteLevel := 0; + end; + if FViewers[I].Item = Item then begin + { Delete the item, and any group item children afterward } + DeleteLevel := FViewers[I].FGroupLevel + 1; + DeleteItem(I); + Continue; + end; + Inc(I); + end; + end; + +var + I: Integer; +begin + case Action of + tbicInserted: ItemInserted; + tbicDeleting: ItemDeleting; + tbicSubitemsChanged: begin + { If Relayed=True, LinkSubitems must have changed on a child group + item. Currently there isn't any optimized way of handling this + situation; just recreate all viewers. } + if Relayed then + RecreateAllViewers; + end; + tbicSubitemsBeginUpdate: BeginUpdate; + tbicSubitemsEndUpdate: EndUpdate; + tbicInvalidate: begin + for I := 0 to FViewerCount-1 do + if FViewers[I].Item = Item then + Invalidate(FViewers[I]); + end; + tbicInvalidateAndResize: InvalidatePositions; + tbicRecreateItemViewers: begin + InvalidatePositions; + for I := 0 to FViewerCount-1 do + if FViewers[I].Item = Item then + RecreateItemViewer(I); + end; + tbicSubMenuImagesChanged: ImagesChanged; + else + { Prevent TryValidatePositions from being called below on Actions other than + those listed above. Currently there are no other Actions, but for forward + compatibility, we should ignore unknown Actions completely. } + Exit; + end; + TryValidatePositions; +end; + +procedure TTBView.LinkNotification(Ancestor: TTBCustomItem; Relayed: Boolean; + Action: TTBItemChangedAction; Index: Integer; Item: TTBCustomItem); +{ This notification procedure watches for tbicSubitemsChanged notifications + from FParentItem } +begin + case Action of + tbicSubitemsChanged: begin + { LinkSubitems may have changed on FParentItem, e.g. on the root item + of a toolbar, so see if FCurParentItem needs updating } + UpdateCurParentItem; + end; + tbicSubMenuImagesChanged: begin + { In case the images were inherited from the actual parent instead of + the linked parent... } + if FParentItem <> FCurParentItem then + ImagesChanged; + end; + end; +end; + +procedure TTBView.ImagesChanged; +begin + InvalidatePositions; + TryValidatePositions; + if Assigned(FOpenViewerView) then + FOpenViewerView.ImagesChanged; +end; + +procedure TTBView.GivePriority(AViewer: TTBItemViewer); +{ Move item to top of priority list. Rearranges items if necessary. } +var + I: Integer; +begin + if Assigned(FChevronParentView) then begin + I := AViewer.Index + FChevronParentView.FInternalViewersAtFront; + if I < FChevronParentView.FViewerCount then { range check just in case } + FChevronParentView.GivePriority(FChevronParentView.FViewers[I]); + Exit; + end; + if Assigned(FPriorityList) then begin + I := FPriorityList.IndexOf(AViewer); + if I <> -1 then begin + FPriorityList.Move(I, 0); + if not FValidated or AViewer.OffEdge then + UpdatePositions; + end; + end; + { Call GivePriority on parent view, so that if an item on a submenu is + clicked, the parent item of the submenu gets priority. } + if Assigned(FParentView) and Assigned(FParentView.FOpenViewer) then + FParentView.GivePriority(FParentView.FOpenViewer); +end; + +function TTBView.HighestPriorityViewer: TTBItemViewer; +{ Returns index of first visible, non-separator item at top of priority list, + or -1 if there are no items found } +var + I: Integer; + J: TTBItemViewer; +begin + ValidatePositions; + Result := nil; + if Assigned(FPriorityList) then begin + for I := 0 to FPriorityList.Count-1 do begin + J := FPriorityList[I]; + if J.Show and not(tbisSeparator in J.Item.ItemStyle) then begin + Result := J; + Break; + end; + end; + end + else begin + for I := 0 to FViewerCount-1 do begin + J := FViewers[I]; + if J.Show and not(tbisSeparator in J.Item.ItemStyle) then begin + Result := J; + Break; + end; + end; + end; +end; + +procedure TTBView.StartTimer(const ATimer: TTBViewTimerID; + const Interval: Integer); +{ Starts a timer. Stops any previously set timer of the same ID first. + Note: WM_TIMER messages generated by timers set by the method are handled + in PopupMessageLoop. } +begin + StopTimer(ATimer); + if (FWindow is TTBPopupWindow) and FWindow.HandleAllocated then begin + SetTimer(FWindow.Handle, ViewTimerBaseID + Ord(ATimer), Interval, nil); + Include(FActiveTimers, ATimer); + end; +end; + +procedure TTBView.StopAllTimers; +var + I: TTBViewTimerID; +begin + for I := Low(I) to High(I) do + StopTimer(I); +end; + +procedure TTBView.StopTimer(const ATimer: TTBViewTimerID); +begin + if ATimer in FActiveTimers then begin + if (FWindow is TTBPopupWindow) and FWindow.HandleAllocated then + KillTimer(FWindow.Handle, ViewTimerBaseID + Ord(ATimer)); + Exclude(FActiveTimers, ATimer); + end; +end; + +function TTBView.OpenChildPopup(const SelectFirstItem: Boolean): Boolean; +var + Item: TTBCustomItem; +begin + StopTimer(tiClose); + StopTimer(tiOpen); + if FSelected <> FOpenViewer then begin + CloseChildPopups; + if Assigned(FSelected) then begin + Item := FSelected.Item; + if Item.Enabled and (tbisSubmenu in Item.ItemStyle) then + Item.CreatePopup(Self, FSelected, not FIsToolbar, SelectFirstItem, + False, Point(0, 0), tbpaLeft); + end; + end; + Result := Assigned(FOpenViewer); +end; + +procedure TTBView.CloseChildPopups; +begin + if Assigned(FOpenViewerView) then + FOpenViewerView.CloseChildPopups; + StopTimer(tiClose); + FOpenViewerWindow.Free; + FOpenViewerWindow := nil; + FOpenViewerView := nil; + FOpenViewer := nil; +end; + +procedure TTBView.CancelChildPopups; +begin + if FIsToolbar then + Exclude(FState, vsDropDownMenus); + CloseChildPopups; +end; + +function TTBView.ViewerFromPoint(const P: TPoint): TTBItemViewer; +var + I: Integer; +begin + ValidatePositions; + for I := 0 to FViewerCount-1 do begin + if FViewers[I].Show and + PtInRect(FViewers[I].BoundsRect, P) then begin + Result := FViewers[I]; + Exit; + end; + end; + Result := nil; +end; + +procedure TTBView.NotifyFocusEvent; +{ Notifies Active Accessibility of a change in "focus". Has no effect if the + view or the root view lacks the vsModal state, or if the modal loop is + ending (EndModal* was called). } +var + I, ChildID, J: Integer; +begin + { Note: We don't notify about windows not yet shown (e.g. a popup menu that + is still initializing) because that would probably confuse screen readers. + Also allocating a window handle at this point *might* not be a good idea. } + if (vsModal in FState) and (vsModal in GetRootView.FState) and + not IsModalEnding and + FWindow.HandleAllocated and IsWindowVisible(FWindow.Handle) then begin + if Assigned(FSelected) and FSelected.IsAccessible then + I := IndexOf(FSelected) + else + I := -1; + if (I < 0) and Assigned(FParentView) then begin + { If we have no selected item, report the the selected item on the parent + view as having the "focus". + Note: With standard menus, when you go from having a selection to no + selection on a submenu, it sends two focus events - first with the + client window as having the focus, then with the parent item. I + figure that's probably a bug, so I don't try to emulate that behavior + here. } + FParentView.NotifyFocusEvent; + end + else begin + if I >= 0 then begin + { Convert viewer index into a one-based child index. + (TTBViewAccObject.get_accChild does the inverse.) } + ChildID := 1; + for J := 0 to I-1 do + if FViewers[J].IsAccessible then + Inc(ChildID); + end + else begin + { If there is no (accessible) selection and no parent view, report + the client window itself as being "focused". This is what happens + when a standard context menu has no selection. } + ChildID := CHILDID_SELF; + end; + CallNotifyWinEvent(EVENT_OBJECT_FOCUS, FWindow.Handle, OBJID_CLIENT, ChildID); + end; + end; +end; + +procedure TTBView.SetSelected(Value: TTBItemViewer); +begin + Select(Value, False); +end; + +procedure TTBView.Select(Value: TTBItemViewer; ViaMouse: Boolean); +{ Sets the current selection. + When the selection is changing it will also, if necessary, open/close child + popups. How exactly this works depends on the setting of ViaMouse. If + ViaMouse is True it will delay the opening/closing of popups using timers. } +var + OldSelected: TTBItemViewer; + NewMouseOverSelected: Boolean; + P: TPoint; +begin + OldSelected := FSelected; + if Value <> OldSelected then begin + { If there's a new selection and the parent item on the parent view + isn't currently selected, select it. Also stop any timer running on + the parent view. } + if Assigned(Value) and Assigned(FParentView) and + Assigned(FParentView.FOpenViewer) and + (FParentView.FSelected <> FParentView.FOpenViewer) then begin + FParentView.Selected := FParentView.FOpenViewer; + FParentView.StopTimer(tiClose); + FParentView.StopTimer(tiOpen); + end; + + { Handle automatic closing of child popups } + if vsModal in FState then begin + { If the view is a toolbar, or if the new selection didn't come from + the mouse, close child popups immediately } + if FIsToolbar or not ViaMouse then begin + { Always stop any close timer because CloseChildPopups may not be + called below } + StopTimer(tiClose); + if Value <> FOpenViewer then + { ^ But don't close if selection is returning to the open item. + Needed for the "FParentView.Selected := FParentView.FOpenViewer" + line above to work. } + CloseChildPopups; + end + else begin + { Otherwise, delay-close any child popup } + if Assigned(FOpenViewerView) and not(tiClose in FActiveTimers) then + StartTimer(tiClose, GetMenuShowDelay); + end; + end; + + CancelCapture; + if Assigned(OldSelected) then + OldSelected.Leaving; + FSelected := Value; + FSelectedViaMouse := ViaMouse; + end; + + NewMouseOverSelected := False; + if Assigned(Value) and Assigned(FWindow) then begin + P := SmallPointToPoint(TSmallPoint(GetMessagePos())); + if FindDragTarget(P, True) = FWindow then begin + P := FWindow.ScreenToClient(P); + NewMouseOverSelected := (ViewerFromPoint(P) = Value); + if NewMouseOverSelected and FCapture and + not Value.IsPtInButtonPart(P.X - Value.BoundsRect.Left, + P.Y - Value.BoundsRect.Top) then + NewMouseOverSelected := False; + end; + end; + + if Value <> OldSelected then begin + FMouseOverSelected := NewMouseOverSelected; + if Assigned(OldSelected) and (tbisRedrawOnSelChange in OldSelected.Item.ItemStyle) then + Invalidate(OldSelected); + if Assigned(Value) then begin + if tbisRedrawOnSelChange in Value.Item.ItemStyle then + Invalidate(Value); + Value.Entering; + end; + NotifyFocusEvent; + + { Handle automatic opening of a child popup } + if vsModal in FState then begin + { If the view is a toolbar, immediately open any child popup } + if FIsToolbar then begin + if Assigned(Value) then begin + if ViaMouse and Assigned(FParentView) then begin + { On chevron popups, always drop down menus when mouse passes + over them, like Office 2000 } + Include(FState, vsDropDownMenus); + end; + if (vsDropDownMenus in FState) and + (ViaMouse or not(tbisNoAutoOpen in Value.Item.ItemStyle)) then + OpenChildPopup(not ViaMouse); + end; + end + else begin + { Otherwise, delay-open any child popup if the selection came from + the mouse } + StopTimer(tiOpen); + if ViaMouse and Assigned(Value) and (tbisSubmenu in Value.Item.ItemStyle) then + StartTimer(tiOpen, GetMenuShowDelay); + end; + end; + end + else if FMouseOverSelected <> NewMouseOverSelected then begin + FMouseOverSelected := NewMouseOverSelected; + if Assigned(Value) and FCapture and (tbisRedrawOnMouseOverChange in Value.Item.ItemStyle) then + Invalidate(Value); + end; +end; + +procedure TTBView.UpdateSelection(const P: PPoint; const AllowNewSelection: Boolean); +{ Called in response to a mouse movement, this method updates the current + selection, updates the vsMouseInWindow view state, and enables/disables + scroll timers. } + + function IsPtInScrollArrow(ADownArrow: Boolean): Boolean; + var + P2: TPoint; + R: TRect; + begin + Result := False; + if (vsModal in FState) and (vsMouseInWindow in FState) and + Assigned(P) then begin + P2 := FWindow.ScreenToClient(P^); + R := FWindow.ClientRect; + if PtInRect(R, P2) then begin + if ADownArrow then + Result := FShowDownArrow and (P2.Y >= R.Bottom - tbMenuScrollArrowHeight) + else + Result := FShowUpArrow and (P2.Y < tbMenuScrollArrowHeight); + end; + end; + end; + +var + NewSelected, ViewerAtPoint: TTBItemViewer; + P2: TPoint; + MouseWasInWindow: Boolean; +begin + ValidatePositions; + + { If modal, default to keeping the existing selection } + if vsModal in FState then + NewSelected := FSelected + else + NewSelected := nil; + + { Is the mouse inside the window? } + MouseWasInWindow := vsMouseInWindow in FState; + if Assigned(P) and Assigned(FWindow) and (FindDragTarget(P^, True) = FWindow) then begin + { If we're a popup window and the mouse is inside, default to no selection } + if FIsPopup then + NewSelected := nil; + Include(FState, vsMouseInWindow); + if AllowNewSelection or Assigned(FSelected) then begin + P2 := FWindow.ScreenToClient(P^); + ViewerAtPoint := ViewerFromPoint(P2); + if Assigned(ViewerAtPoint) then + NewSelected := ViewerAtPoint; + end; + end + else + Exclude(FState, vsMouseInWindow); + + { If FCapture is True, don't allow the selection to change } + if FCapture and (NewSelected <> FSelected) then + NewSelected := FSelected; + + { If we're a popup window and there is a selection... } + if FIsPopup and Assigned(NewSelected) then begin + { If the mouse just moved out of the window and no submenu was open, + remove the highlight } + if not FCapture and MouseWasInWindow and not(vsMouseInWindow in FState) and + (not Assigned(FOpenViewerView) or not(tbisSubmenu in NewSelected.Item.ItemStyle)) then + NewSelected := nil; + end; + + { Now we set the new Selected value } + Select(NewSelected, True); + + { Update scroll arrow timers } + if IsPtInScrollArrow(False) then begin + StopTimer(tiScrollDown); + if not(tiScrollUp in FActiveTimers) then + StartTimer(tiScrollUp, 100); + end + else if IsPtInScrollArrow(True) then begin + StopTimer(tiScrollUp); + if not(tiScrollDown in FActiveTimers) then + StartTimer(tiScrollDown, 100); + end + else begin + StopTimer(tiScrollUp); + StopTimer(tiScrollDown); + end; +end; + +procedure TTBView.RecreateAllViewers; +var + Item: TTBCustomItem; + I: Integer; +begin + { Since the FViewers list is being rebuilt, FOpenViewer and FSelected + will no longer be valid, so ensure they're set to nil. } + CloseChildPopups; + Selected := nil; + + InvalidatePositions; + + FreeAndNil(FPriorityList); + FreeViewers; + FInternalViewersAtFront := 0; + FInternalViewersAtEnd := 0; + + { MDI system menu item } + Item := GetMDISystemMenuItem; + if Assigned(Item) then + Inc(FInternalViewersAtFront, InsertItemViewers(FViewerCount, Item, 0, + False, False)); + + { Items } + if Assigned(FCurParentItem) then begin + for I := 0 to FCurParentItem.Count-1 do + InsertItemViewers(FViewerCount, FCurParentItem.FItems[I].Item, 0, + True, False); + end; + + { MDI buttons item } + Item := GetMDIButtonsItem; + if Assigned(Item) then begin + for I := 0 to Item.Count-1 do + Inc(FInternalViewersAtEnd, InsertItemViewers(FViewerCount, + Item.FItems[I].Item, 0, False, False)); + end; + + { Chevron item } + Item := GetChevronItem; + if Assigned(Item) then + Inc(FInternalViewersAtEnd, InsertItemViewers(FViewerCount, Item, 0, + False, False)); +end; + +function TTBView.CalculatePositions(const CanMoveControls: Boolean; + const AOrientation: TTBViewOrientation; + AWrapOffset, AChevronOffset, AChevronSize: Integer; + var ABaseSize, TotalSize: TPoint; + var AWrappedLines: Integer): Boolean; +{ Returns True if the positions have changed } +type + PTempPosition = ^TTempPosition; + TTempPosition = record + BoundsRect: TRect; + Show, OffEdge, LineSep, Clipped, SameWidth: Boolean; + end; + PTempPositionArray = ^TTempPositionArray; + TTempPositionArray = array[0..$7FFFFFFF div SizeOf(TTempPosition)-1] of TTempPosition; +var + DC: HDC; + LeftX, TopY, CurX, CurY, I: Integer; + NewPositions: PTempPositionArray; + GroupSplit, DidWrap: Boolean; + LineStart, HighestHeightOnLine, HighestWidthOnLine: Integer; + + function GetSizeOfGroup(const StartingIndex: Integer): Integer; + var + I: Integer; + begin + Result := 0; + for I := StartingIndex to FViewerCount-1 do begin + if not NewPositions[I].Show then + Continue; + if tbisSeparator in FViewers[I].Item.ItemStyle then + Break; + with NewPositions[I] do begin + if AOrientation <> tbvoVertical then + Inc(Result, BoundsRect.Right) + else + Inc(Result, BoundsRect.Bottom); + end; + end; + end; + + procedure Mirror; + { Reverses the horizontal ordering (i.e. first item becomes last) } + var + I, NewRight: Integer; + begin + for I := 0 to FViewerCount-1 do + with NewPositions[I] do + if Show then begin + NewRight := TotalSize.X - BoundsRect.Left; + BoundsRect.Left := TotalSize.X - BoundsRect.Right; + BoundsRect.Right := NewRight; + end; + end; + + procedure HandleMaxHeight; + { Decreases, if necessary, the height of the view to FMaxHeight, and adjusts + the visibility of the scroll arrows } + var + MaxOffset, I, MaxTop, MaxBottom: Integer; + begin + FShowUpArrow := False; + FShowDownArrow := False; + if (FMaxHeight > 0) and (TotalSize.Y > FMaxHeight) then begin + MaxOffset := TotalSize.Y - FMaxHeight; + if FScrollOffset > MaxOffset then + FScrollOffset := MaxOffset; + if FScrollOffset < 0 then + FScrollOffset := 0; + FShowUpArrow := (FScrollOffset > 0); + FShowDownArrow := (FScrollOffset < MaxOffset); + MaxTop := 0; + if FShowUpArrow then + MaxTop := tbMenuScrollArrowHeight; + MaxBottom := FMaxHeight; + if FShowDownArrow then + Dec(MaxBottom, tbMenuScrollArrowHeight); + for I := 0 to FViewerCount-1 do begin + if not IsRectEmpty(NewPositions[I].BoundsRect) then begin + OffsetRect(NewPositions[I].BoundsRect, 0, -FScrollOffset); + if NewPositions[I].Show and + ((NewPositions[I].BoundsRect.Top < MaxTop) or + (NewPositions[I].BoundsRect.Bottom > MaxBottom)) then begin + NewPositions[I].Show := False; + NewPositions[I].Clipped := True; + end; + end; + end; + TotalSize.Y := FMaxHeight; + end + else + FScrollOffset := 0; + end; + + procedure FinalizeLine(const LineEnd: Integer; const LastLine: Boolean); + var + I, RightAlignStart: Integer; + Item: TTBCustomItem; + IsButton: Boolean; + Pos: PTempPosition; + Z: Integer; + begin + if LineStart <> -1 then begin + if DidWrap and (FChevronParentView = nil) then begin + { When wrapping on a docked toolbar, extend TotalSize.X/Y to + AWrapOffset so that the toolbar always fills the whole row } + if (AOrientation = tbvoHorizontal) and (TotalSize.X < AWrapOffset) then + TotalSize.X := AWrapOffset + else if (AOrientation = tbvoVertical) and (TotalSize.Y < AWrapOffset) then + TotalSize.Y := AWrapOffset; + end; + RightAlignStart := -1; + for I := LineStart to LineEnd do begin + Pos := @NewPositions[I]; + if not Pos.Show then + Continue; + Item := FViewers[I].Item; + if (RightAlignStart < 0) and (tbisRightAlign in Item.ItemStyle) then + RightAlignStart := I; + IsButton := FIsToolbar or (tboToolbarSize in Item.FEffectiveOptions); + if FIsToolbar then begin + if LastLine and not DidWrap and (AOrientation <> tbvoFloating) then begin + { In case the toolbar is docked next to a taller/wider toolbar... } + HighestWidthOnLine := TotalSize.X; + HighestHeightOnLine := TotalSize.Y; + end; + { Make separators on toolbars as tall/wide as the tallest/widest item } + if tbisSeparator in Item.ItemStyle then begin + if AOrientation <> tbvoVertical then + Pos.BoundsRect.Bottom := Pos.BoundsRect.Top + HighestHeightOnLine + else + Pos.BoundsRect.Right := Pos.BoundsRect.Left + HighestWidthOnLine; + end + else begin + { Center the item } + if AOrientation <> tbvoVertical then begin + Z := (HighestHeightOnLine - (Pos.BoundsRect.Bottom - Pos.BoundsRect.Top)) div 2; + Inc(Pos.BoundsRect.Top, Z); + Inc(Pos.BoundsRect.Bottom, Z); + end + else begin + Z := (HighestWidthOnLine - (Pos.BoundsRect.Right - Pos.BoundsRect.Left)) div 2; + Inc(Pos.BoundsRect.Left, Z); + Inc(Pos.BoundsRect.Right, Z); + end; + end; + end + else begin + { Make items in a menu as wide as the widest item } + if not IsButton then begin + with Pos.BoundsRect do Right := Left + HighestWidthOnLine; + end; + end; + end; + if RightAlignStart >= 0 then begin + Z := 0; + for I := LineEnd downto RightAlignStart do begin + Pos := @NewPositions[I]; + if not Pos.Show then + Continue; + if AOrientation <> tbvoVertical then + Z := Min(AWrapOffset, TotalSize.X) - Pos.BoundsRect.Right + else + Z := Min(AWrapOffset, TotalSize.Y) - Pos.BoundsRect.Bottom; + Break; + end; + if Z > 0 then begin + for I := RightAlignStart to LineEnd do begin + Pos := @NewPositions[I]; + if not Pos.Show then + Continue; + if AOrientation <> tbvoVertical then begin + Inc(Pos.BoundsRect.Left, Z); + Inc(Pos.BoundsRect.Right, Z); + end + else begin + Inc(Pos.BoundsRect.Top, Z); + Inc(Pos.BoundsRect.Bottom, Z); + end; + end; + end; + end; + end; + LineStart := -1; + HighestHeightOnLine := 0; + HighestWidthOnLine := 0; + end; + + procedure PositionItem(const CurIndex: Integer; var Pos: TTempPosition); + var + O, X, Y: Integer; + IsLineSep, Vert: Boolean; + begin + if LineStart = -1 then begin + LineStart := CurIndex; + HighestHeightOnLine := 0; + HighestWidthOnLine := 0; + end; + IsLineSep := False; + Vert := (AOrientation = tbvoVertical); + if not Vert then + O := CurX + else + O := CurY; + if (AWrapOffset > 0) and (O > 0) then begin + if not Vert then + Inc(O, Pos.BoundsRect.Right) + else + Inc(O, Pos.BoundsRect.Bottom); + if (tbisSeparator in FViewers[CurIndex].Item.ItemStyle) and + ((GroupSplit and not(tbisNoLineBreak in FViewers[CurIndex].Item.ItemStyle)) + or (O + GetSizeOfGroup(CurIndex+1) > AWrapOffset)) then begin + DidWrap := True; + Inc(AWrappedLines); + if not Vert then begin + CurX := 0; + Inc(CurY, HighestHeightOnLine); + end + else begin + CurY := 0; + Inc(CurX, HighestWidthOnLine); + end; + FinalizeLine(CurIndex-1, False); + LineStart := CurIndex+1; + if not Vert then begin + Pos.BoundsRect.Right := 0; + Pos.BoundsRect.Bottom := tbLineSpacing; + end + else begin + Pos.BoundsRect.Right := tbLineSpacing; + Pos.BoundsRect.Bottom := 0; + end; + Pos.LineSep := True; + IsLineSep := True; + end + else if O > AWrapOffset then begin + { proceed to next row } + DidWrap := True; + Inc(AWrappedLines); + if not Vert then begin + CurX := LeftX; + Inc(CurY, HighestHeightOnLine); + end + else begin + CurY := TopY; + Inc(CurX, HighestWidthOnLine); + end; + GroupSplit := True; + FinalizeLine(CurIndex-1, False); + LineStart := CurIndex; + end; + end; + if Pos.BoundsRect.Bottom > HighestHeightOnLine then + HighestHeightOnLine := Pos.BoundsRect.Bottom; + if Pos.BoundsRect.Right > HighestWidthOnLine then + HighestWidthOnLine := Pos.BoundsRect.Right; + X := CurX; + Y := CurY; + if X < 0 then X := 0; + if Y < 0 then Y := 0; + OffsetRect(Pos.BoundsRect, X, Y); + if IsLineSep then begin + if not Vert then begin + CurX := LeftX; + Inc(CurY, tbLineSpacing); + end + else begin + CurY := TopY; + Inc(CurX, tbLineSpacing); + end; + GroupSplit := False; + end; + end; + +var + SaveOrientation: TTBViewOrientation; + ChevronItem: TTBCustomItem; + CalcCanvas: TCanvas; + LastWasSep, LastWasButton, IsButton, IsControl: Boolean; + Item: TTBCustomItem; + Ctl: TControl; + ChangedBold: Boolean; + HighestSameWidthViewerWidth, Total, J, TotalVisibleItems: Integer; + IsFirst: Boolean; + Viewer: TTBItemViewer; + UseChevron, NonControlsOffEdge, TempViewerCreated: Boolean; + Margins: TRect; +label 1; +begin + SaveOrientation := FOrientation; + AWrappedLines := 1; + ChevronItem := GetChevronItem; + NewPositions := nil; + DC := 0; + CalcCanvas := nil; + try + FOrientation := AOrientation; + + CalcCanvas := TCanvas.Create; + DC := GetDC(0); + CalcCanvas.Handle := DC; + CalcCanvas.Font.Assign(GetFont); + + NewPositions := AllocMem(FViewerCount * SizeOf(TTempPosition)); + + { Figure out which items should be shown } + LastWasSep := True; { set to True initially so it won't show leading seps } + for I := 0 to FViewerCount-1 do begin + Item := FViewers[I].Item; + IsControl := Item is TTBControlItem; + with NewPositions[I] do begin + { Show is initially False since AllocMem initializes to zero } + if Item = ChevronItem then + Continue; + if Assigned(FChevronParentView) then begin + if IsControl then + Continue; + FChevronParentView.ValidatePositions; + J := I + FChevronParentView.FInternalViewersAtFront; + if J < FChevronParentView.FViewerCount then + { range check just in case } + Viewer := FChevronParentView.FViewers[J] + else + Viewer := nil; + if (Viewer = nil) or (not Viewer.OffEdge and not(tbisSeparator in Item.ItemStyle)) then + Continue; + end; + if not IsControl then begin + if not(tbisEmbeddedGroup in Item.ItemStyle) or FCustomizing then begin + Show := Item.Visible; + { Don't display two consecutive separators } + if Show then begin + if (tbisSeparator in Item.ItemStyle) and LastWasSep then + Show := False; + LastWasSep := tbisSeparator in Item.ItemStyle; + end; + end; + end + else begin + { Controls can only be rendered on a single Parent, so only + include the control if its parent is currently equal to + FWindow } + Ctl := TTBControlItem(Item).FControl; + if Assigned(Ctl) and Assigned(FWindow) and (Ctl.Parent = FWindow) and + (Ctl.Visible or (csDesigning in Ctl.ComponentState)) then begin + Show := True; + LastWasSep := False; + end; + end; + end; + end; + + { Hide any trailing separators, so that they aren't included in the + base size } + for I := FViewerCount-1 downto 0 do begin + with NewPositions[I] do + if Show then begin + if not(tbisSeparator in FViewers[I].Item.ItemStyle) then + Break; + Show := False; + end; + end; + + { Calculate sizes of all the items } + HighestSameWidthViewerWidth := 0; + for I := 0 to FViewerCount-1 do begin + Item := FViewers[I].Item; + IsControl := Item is TTBControlItem; + with NewPositions[I] do begin + { BoundsRect is currently empty since AllocMem initializes to zero } + if not Show then + Continue; + if not IsControl then begin + ChangedBold := False; + if tboDefault in Item.EffectiveOptions then + with CalcCanvas.Font do + if not(fsBold in Style) then begin + ChangedBold := True; + Style := Style + [fsBold]; + end; + Viewer := FViewers[I]; + TempViewerCreated := False; + if Item.NeedToRecreateViewer(Viewer) then begin + if CanMoveControls then begin + RecreateItemViewer(I); + Viewer := FViewers[I]; + end + else begin + Viewer := Item.GetItemViewerClass(Self).Create(Self, Item, 0); + TempViewerCreated := True; + end; + end; + try + Viewer.CalcSize(CalcCanvas, BoundsRect.Right, BoundsRect.Bottom); + if Viewer.UsesSameWidth then begin + SameWidth := True; + if (BoundsRect.Right > HighestSameWidthViewerWidth) then + HighestSameWidthViewerWidth := BoundsRect.Right; + end; + finally + if TempViewerCreated then + Viewer.Free; + end; + if ChangedBold then + with CalcCanvas.Font do + Style := Style - [fsBold]; + end + else begin + Ctl := TTBControlItem(Item).FControl; + BoundsRect.Right := Ctl.Width; + BoundsRect.Bottom := Ctl.Height; + end; + end; + end; + + { Increase widths of SameWidth items if necessary. Also calculate + ABaseSize.X (or Y). } + ABaseSize.X := 0; + ABaseSize.Y := 0; + for I := 0 to FViewerCount-1 do begin + with NewPositions[I] do begin + if SameWidth and (BoundsRect.Right < HighestSameWidthViewerWidth) then + BoundsRect.Right := HighestSameWidthViewerWidth; + if AOrientation <> tbvoVertical then + Inc(ABaseSize.X, BoundsRect.Right) + else + Inc(ABaseSize.Y, BoundsRect.Bottom); + end; + end; + + { Hide partially visible items, mark them as 'OffEdge' } + if AOrientation <> tbvoVertical then + Total := ABaseSize.X + else + Total := ABaseSize.Y; + NonControlsOffEdge := False; + UseChevron := Assigned(ChevronItem) and (AChevronOffset > 0) and + (Total > AChevronOffset); + if UseChevron then begin + Dec(AChevronOffset, AChevronSize); + while Total > AChevronOffset do begin + { Count number of items. Stop loop if <= 1 } + TotalVisibleItems := 0; + for I := FViewerCount-1 downto 0 do begin + if NewPositions[I].Show and not(tbisSeparator in FViewers[I].Item.ItemStyle) then + Inc(TotalVisibleItems); + end; + if TotalVisibleItems <= 1 then + Break; + { Hide any trailing separators } + for I := FViewerCount-1 downto 0 do begin + with NewPositions[I] do + if Show then begin + if not(tbisSeparator in FViewers[I].Item.ItemStyle) then + Break; + Show := False; + if AOrientation <> tbvoVertical then + Dec(Total, BoundsRect.Right) + else + Dec(Total, BoundsRect.Bottom); + goto 1; + end; + end; + { Find an item to hide } + if Assigned(FPriorityList) then + I := FPriorityList.Count-1 + else + I := FViewerCount-1; + while I >= 0 do begin + if Assigned(FPriorityList) then begin + Viewer := FPriorityList[I]; + J := Viewer.Index; + end + else begin + Viewer := FViewers[I]; + J := I; + end; + if NewPositions[J].Show and not(tbisSeparator in Viewer.Item.ItemStyle) then begin + NewPositions[J].Show := False; + NewPositions[J].OffEdge := True; + if AOrientation <> tbvoVertical then + Dec(Total, NewPositions[J].BoundsRect.Right) + else + Dec(Total, NewPositions[J].BoundsRect.Bottom); + if not NonControlsOffEdge and not(Viewer.Item is TTBControlItem) then + NonControlsOffEdge := True; + goto 1; + end; + Dec(I); + end; + Break; { prevent endless loop } + 1: + { Don't show two consecutive separators } + LastWasSep := True; { set to True initially so it won't show leading seps } + for J := 0 to FViewerCount-1 do begin + Item := FViewers[J].Item; + with NewPositions[J] do begin + if Show then begin + if (tbisSeparator in Item.ItemStyle) and LastWasSep then begin + Show := False; + if AOrientation <> tbvoVertical then + Dec(Total, BoundsRect.Right) + else + Dec(Total, BoundsRect.Bottom); + end; + LastWasSep := tbisSeparator in Item.ItemStyle; + end; + end; + end; + end; + end; + + { Hide any trailing separators after items were hidden } + for I := FViewerCount-1 downto 0 do begin + with NewPositions[I] do + if Show then begin + if not(tbisSeparator in FViewers[I].Item.ItemStyle) then + Break; + Show := False; + end; + end; + + { Set the ABaseSize.Y (or X) *after* items were hidden } + for I := 0 to FViewerCount-1 do begin + with NewPositions[I] do + if Show then begin + if AOrientation <> tbvoVertical then begin + if BoundsRect.Bottom > ABaseSize.Y then + ABaseSize.Y := BoundsRect.Bottom; + end + else begin + if BoundsRect.Right > ABaseSize.X then + ABaseSize.X := BoundsRect.Right; + end; + end; + end; + + { On menus, set all non-separator items to be as tall as the tallest item } + {if not FIsToolbar then begin + J := 0; + for I := 0 to FViewerCount-1 do begin + Item := FViewers[I].Item; + with NewPositions[I] do + if Show and not(tbisSeparator in Item.ItemStyle) and + not(tboToolbarSize in Item.FEffectiveOptions) and + (BoundsRect.Bottom - BoundsRect.Top > J) then + J := BoundsRect.Bottom - BoundsRect.Top; + end; + for I := 0 to FViewerCount-1 do begin + Item := FViewers[I].Item; + with NewPositions[I] do + if Show and not(tbisSeparator in Item.ItemStyle) and + not(tboToolbarSize in Item.FEffectiveOptions) then + BoundsRect.Bottom := BoundsRect.Top + J; + end; + end;} + + { Calculate the position of the items } + GetMargins(AOrientation, Margins); + LeftX := Margins.Left; + TopY := Margins.Top; + if AWrapOffset > 0 then begin + Dec(AWrapOffset, Margins.Right); + if AWrapOffset < 1 then AWrapOffset := 1; + end; + CurX := LeftX; + CurY := TopY; + GroupSplit := False; + DidWrap := False; + LastWasButton := FIsToolbar; + LineStart := -1; + for I := 0 to FViewerCount-1 do begin + Item := FViewers[I].Item; + with NewPositions[I] do begin + if not Show then + Continue; + IsButton := FIsToolbar or (tboToolbarSize in Item.FEffectiveOptions); + if LastWasButton and not IsButton then begin + { On a menu, if last item was a button and the current item isn't, + proceed to next row } + CurX := LeftX; + CurY := TotalSize.Y; + end; + LastWasButton := IsButton; + PositionItem(I, NewPositions[I]); + if IsButton and (AOrientation <> tbvoVertical) then + Inc(CurX, BoundsRect.Right - BoundsRect.Left) + else + Inc(CurY, BoundsRect.Bottom - BoundsRect.Top); + if BoundsRect.Right > TotalSize.X then + TotalSize.X := BoundsRect.Right; + if BoundsRect.Bottom > TotalSize.Y then + TotalSize.Y := BoundsRect.Bottom; + end; + end; + if FViewerCount <> 0 then + FinalizeLine(FViewerCount-1, True); + Inc(TotalSize.X, Margins.Right); + Inc(TotalSize.Y, Margins.Bottom); + if AOrientation = tbvoVertical then + Mirror; + HandleMaxHeight; + if CanMoveControls then begin + for I := 0 to FViewerCount-1 do begin + Item := FViewers[I].Item; + if Item is TTBControlItem then begin + if NewPositions[I].Show then begin + Ctl := TTBControlItem(Item).FControl; + if not EqualRect(NewPositions[I].BoundsRect, Ctl.BoundsRect) then + Ctl.BoundsRect := NewPositions[I].BoundsRect; + end + else if NewPositions[I].OffEdge or NewPositions[I].Clipped then begin + { Simulate hiding of OddEdge controls by literally moving them + off the edge. Do the same for Clipped controls. } + Ctl := TTBControlItem(Item).FControl; + Ctl.SetBounds(FWindow.ClientWidth, FWindow.ClientHeight, + Ctl.Width, Ctl.Height); + end; + end; + end; + end; + { Set size of line separators } + if FIsToolbar then + for I := 0 to FViewerCount-1 do begin + Item := FViewers[I].Item; + with NewPositions[I] do + if Show and (tbisSeparator in Item.ItemStyle) and + LineSep then begin + if AOrientation <> tbvoVertical then + BoundsRect.Right := TotalSize.X + else + BoundsRect.Bottom := TotalSize.Y; + end; + end; + + { Position the chevron item } + if UseChevron then begin + if CanMoveControls then + ChevronItem.Enabled := NonControlsOffEdge; + NewPositions[FViewerCount-1].Show := True; + I := AChevronOffset; + if AOrientation <> tbvoVertical then begin + if I < TotalSize.X then + I := TotalSize.X; + NewPositions[FViewerCount-1].BoundsRect := Bounds(I, 0, + AChevronSize, TotalSize.Y); + end + else begin + if I < TotalSize.Y then + I := TotalSize.Y; + NewPositions[FViewerCount-1].BoundsRect := Bounds(0, I, + TotalSize.X, AChevronSize); + end; + end; + + { Commit changes } + Result := False; + if CanMoveControls then begin + for I := 0 to FViewerCount-1 do begin + if not Result and + (not EqualRect(FViewers[I].BoundsRect, NewPositions[I].BoundsRect) or + (FViewers[I].Show <> NewPositions[I].Show) or + (tbisLineSep in FViewers[I].State <> NewPositions[I].LineSep)) then + Result := True; + FViewers[I].FBoundsRect := NewPositions[I].BoundsRect; + FViewers[I].FShow := NewPositions[I].Show; + FViewers[I].FOffEdge := NewPositions[I].OffEdge; + FViewers[I].FClipped := NewPositions[I].Clipped; + if NewPositions[I].LineSep then + Include(FViewers[I].State, tbisLineSep) + else + Exclude(FViewers[I].State, tbisLineSep); + end; + end; + finally + FOrientation := SaveOrientation; + if Assigned(CalcCanvas) then + CalcCanvas.Handle := 0; + if DC <> 0 then ReleaseDC(0, DC); + CalcCanvas.Free; + FreeMem(NewPositions); + end; + if (ABaseSize.X = 0) or (ABaseSize.Y = 0) then begin + { If there are no visible items... } + {}{scale this?} + ABaseSize.X := 23; + ABaseSize.Y := 22; + if TotalSize.X < 23 then TotalSize.X := 23; + if TotalSize.Y < 22 then TotalSize.Y := 22; + end; +end; + +procedure TTBView.DoUpdatePositions(var ASize: TPoint); +{ This is called by UpdatePositions } +var + Bmp: TBitmap; + CtlCanvas: TControlCanvas; + WrappedLines: Integer; +begin + { Don't call InvalidatePositions before CalculatePositions so that + endless recursion doesn't happen if an item's CalcSize uses a method that + calls ValidatePositions } + if not CalculatePositions(True, FOrientation, FWrapOffset, FChevronOffset, + FChevronSize, FBaseSize, ASize, WrappedLines) then begin + { If the new positions are identical to the previous ones, continue using + the previous ones, and don't redraw } + FValidated := True; + { Just because the positions are the same doesn't mean the size hasn't + changed. (If a shrunken toolbar moves between docks, the positions of + the non-OffEdge items may be the same on the new dock as on the old + dock.) } + AutoSize(ASize.X, ASize.Y); + end + else begin + if not(csDesigning in ComponentState) then begin + FValidated := True; + { Need to call ValidateRect before AutoSize, otherwise Windows will + erase the client area during a resize } + if FWindow.HandleAllocated then + ValidateRect(FWindow.Handle, nil); + AutoSize(ASize.X, ASize.Y); + if Assigned(FWindow) and FWindow.HandleAllocated and + IsWindowVisible(FWindow.Handle) and + (FWindow.ClientWidth > 0) and (FWindow.ClientHeight > 0) then begin + CtlCanvas := nil; + Bmp := TBitmap.Create; + try + CtlCanvas := TControlCanvas.Create; + CtlCanvas.Control := FWindow; + Bmp.Width := FWindow.ClientWidth; + Bmp.Height := FWindow.ClientHeight; + + SendMessage(FWindow.Handle, WM_ERASEBKGND, WPARAM(Bmp.Canvas.Handle), 0); + SendMessage(FWindow.Handle, WM_PAINT, WPARAM(Bmp.Canvas.Handle), 0); + BitBlt(CtlCanvas.Handle, 0, 0, Bmp.Width, Bmp.Height, + Bmp.Canvas.Handle, 0, 0, SRCCOPY); + ValidateRect(FWindow.Handle, nil); + finally + CtlCanvas.Free; + Bmp.Free; + end; + end; + end + else begin + { Delphi's handling of canvases is different at design time -- child + controls aren't clipped from a parent control's canvas, so the above + offscreen rendering code doesn't work right at design-time } + InvalidatePositions; + FValidated := True; + AutoSize(ASize.X, ASize.Y); + end; + end; +end; + +function TTBView.UpdatePositions: TPoint; +{ Called whenever the size or orientation of a view changes. When items are + added or removed from the view, InvalidatePositions must be called instead, + otherwise the view may not be redrawn properly. } +begin + Result.X := 0; + Result.Y := 0; + DoUpdatePositions(Result); +end; + +procedure TTBView.AutoSize(AWidth, AHeight: Integer); +begin +end; + +function TTBView.GetChevronItem: TTBCustomItem; +begin + Result := nil; +end; + +procedure TTBView.GetMargins(AOrientation: TTBViewOrientation; + var Margins: TRect); +begin + if AOrientation = tbvoFloating then begin + Margins.Left := 4; + Margins.Top := 2; + Margins.Right := 4; + Margins.Bottom := 1; + end + else begin + Margins.Left := 0; + Margins.Top := 0; + Margins.Right := 0; + Margins.Bottom := 0; + end; +end; + +function TTBView.GetMDIButtonsItem: TTBCustomItem; +begin + Result := nil; +end; + +function TTBView.GetMDISystemMenuItem: TTBCustomItem; +begin + Result := nil; +end; + +function TTBView.GetFont: TFont; +begin + if Assigned(ToolbarFont) then + Result := ToolbarFont + else begin + { ToolbarFont is destroyed during unit finalization, but in rare cases + this method may end up being called from ValidatePositions *after* + unit finalization if Application.Run is never called; see the + "EConvertError" newsgroup thread. We can't return nil because that would + cause an exception in the calling function, so just return the window + font. It's not the *right* font, but it shouldn't matter since the app + is exiting anyway. } + Result := TControlAccess(FWindow).Font; + end; +end; + +procedure TTBView.DrawItem(Viewer: TTBItemViewer; DrawTo: TCanvas; + Offscreen: Boolean); +const + COLOR_MENUHILIGHT = 29; + clMenuHighlight = TColor(COLOR_MENUHILIGHT or $80000000); +var + Bmp: TBitmap; + DrawToDC, BmpDC: HDC; + DrawCanvas: TCanvas; + R1, R2, R3: TRect; + IsOpen, IsSelected, IsPushed: Boolean; + ToolbarStyle: Boolean; + UseDisabledShadow: Boolean; + SaveIndex, SaveIndex2: Integer; + BkColor: TColor; +begin + ValidatePositions; + + if tbisInvalidated in Viewer.State then begin + Offscreen := True; + Exclude(Viewer.State, tbisInvalidated); + end; + + R1 := Viewer.BoundsRect; + if not Viewer.Show or IsRectEmpty(R1) or (Viewer.Item is TTBControlItem) then + Exit; + R2 := R1; + OffsetRect(R2, -R2.Left, -R2.Top); + + IsOpen := FOpenViewer = Viewer; + IsSelected := (FSelected = Viewer); + IsPushed := IsSelected and (IsOpen or (FMouseOverSelected and FCapture)); + ToolbarStyle := Viewer.IsToolbarStyle; + + DrawToDC := DrawTo.Handle; + Bmp := nil; + { Must deselect any currently selected handles before calling SaveDC, because + if they are left selected and DeleteObject gets called on them after the + SaveDC call, it will fail on Win9x/Me, and thus leak GDI resources. } + DrawTo.Refresh; + SaveIndex := SaveDC(DrawToDC); + try + IntersectClipRect(DrawToDC, R1.Left, R1.Top, R1.Right, R1.Bottom); + GetClipBox(DrawToDC, R3); + if IsRectEmpty(R3) then + Exit; + + if not Offscreen then begin + MoveWindowOrg(DrawToDC, R1.Left, R1.Top); + { Tweak the brush origin so that the checked background drawn behind + checked items always looks the same regardless of whether the item + is positioned on an even or odd Left or Top coordinate. } + SetBrushOrgEx(DrawToDC, R1.Left and 1, R1.Top and 1, nil); + DrawCanvas := DrawTo; + end + else begin + Bmp := TBitmap.Create; + Bmp.Width := R2.Right; + Bmp.Height := R2.Bottom; + DrawCanvas := Bmp.Canvas; + BmpDC := DrawCanvas.Handle; + SaveIndex2 := SaveDC(BmpDC); + SetWindowOrgEx(BmpDC, R1.Left, R1.Top, nil); + FWindow.Perform(WM_ERASEBKGND, WPARAM(BmpDC), 0); + RestoreDC(BmpDC, SaveIndex2); + end; + + { Initialize brush } + if not ToolbarStyle and IsSelected then begin + {$IFNDEF TB2K_USE_STRICT_O2K_MENU_STYLE} + if AreFlatMenusEnabled then + { Windows XP uses a different fill color for selected menu items when + flat menus are enabled } + DrawCanvas.Brush.Color := clMenuHighlight + else + {$ENDIF} + DrawCanvas.Brush.Color := clHighlight; + end + else + DrawCanvas.Brush.Style := bsClear; + + { Initialize font } + DrawCanvas.Font.Assign(GetFont); + if Viewer.Item.Enabled then begin + if not ToolbarStyle and IsSelected then + DrawCanvas.Font.Color := clHighlightText + else begin + if ToolbarStyle then + DrawCanvas.Font.Color := clBtnText + else + DrawCanvas.Font.Color := tbMenuTextColor; + end; + UseDisabledShadow := False; + end + else begin + DrawCanvas.Font.Color := clGrayText; + { Use the disabled shadow if either: + 1. The item is a toolbar-style item. + 2. The item is not selected, and the background color equals the + button-face color. + 3. The gray-text color is the same as the background color. + Note: Windows actually uses dithered text in this case. } + BkColor := ColorToRGB(TControlAccess(FWindow).Color); + UseDisabledShadow := ToolbarStyle or + (not IsSelected and (BkColor = ColorToRGB(clBtnFace))) or + (ColorToRGB(clGrayText) = BkColor); + end; + + Viewer.Paint(DrawCanvas, R2, IsSelected, IsPushed, UseDisabledShadow); + + if Offscreen then + BitBlt(DrawToDC, R1.Left, R1.Top, Bmp.Width, Bmp.Height, DrawCanvas.Handle, + 0, 0, SRCCOPY); + finally + DrawTo.Refresh; { must do this before a RestoreDC } + RestoreDC(DrawToDC, SaveIndex); + Bmp.Free; + end; +end; + +procedure TTBView.DrawSubitems(ACanvas: TCanvas); +var + I: Integer; +begin + for I := 0 to FViewerCount-1 do begin + if (vsDrawInOrder in FState) or (FViewers[I] <> FSelected) then + DrawItem(FViewers[I], ACanvas, False); + end; + if not(vsDrawInOrder in FState) and Assigned(FSelected) then + DrawItem(FSelected, ACanvas, False); + + Exclude(FState, vsDrawInOrder); +end; + +procedure TTBView.Invalidate(AViewer: TTBItemViewer); +begin + if not FValidated or not Assigned(FWindow) or not FWindow.HandleAllocated then + Exit; + if AViewer.Show and not IsRectEmpty(AViewer.BoundsRect) and + not(AViewer.Item is TTBControlItem) then begin + Include(AViewer.State, tbisInvalidated); + InvalidateRect(FWindow.Handle, @AViewer.BoundsRect, False); + end; +end; + +procedure TTBView.SetAccelsVisibility(AShowAccels: Boolean); +var + I: Integer; + Viewer: TTBItemViewer; +begin + { Always show accels when keyboard cues are enabled } + AShowAccels := AShowAccels or not(vsUseHiddenAccels in FStyle) or + AreKeyboardCuesEnabled; + if AShowAccels <> (vsShowAccels in FState) then begin + if AShowAccels then + Include(FState, vsShowAccels) + else + Exclude(FState, vsShowAccels); + if Assigned(FWindow) and FWindow.HandleAllocated and + IsWindowVisible(FWindow.Handle) then + { ^ the visibility check is just an optimization } + for I := 0 to FViewerCount-1 do begin + Viewer := FViewers[I]; + if Viewer.CaptionShown and + (FindAccelChar(Viewer.GetCaptionText) <> #0) then + Invalidate(Viewer); + end; + end; +end; + +function TTBView.FirstSelectable: TTBItemViewer; +var + FirstViewer: TTBItemViewer; +begin + Result := NextSelectable(nil, True); + if Assigned(Result) then begin + FirstViewer := Result; + while tbisDontSelectFirst in Result.Item.ItemStyle do begin + Result := NextSelectable(Result, True); + if Result = FirstViewer then + { don't loop endlessly if all items have the tbisDontSelectFirst style } + Break; + end; + end; +end; + +function TTBView.NextSelectable(CurViewer: TTBItemViewer; + GoForward: Boolean): TTBItemViewer; +var + I, J: Integer; +begin + ValidatePositions; + Result := nil; + if FViewerCount = 0 then Exit; + J := -1; + I := IndexOf(CurViewer); + while True do begin + if GoForward then begin + Inc(I); + if I >= FViewerCount then I := 0; + end + else begin + Dec(I); + if I < 0 then I := FViewerCount-1; + end; + if J = -1 then + J := I + else + if I = J then + Exit; + if (FViewers[I].Show or FViewers[I].Clipped) and FViewers[I].Item.Visible and + (tbisSelectable in FViewers[I].Item.ItemStyle) then + Break; + end; + Result := FViewers[I]; +end; + +function TTBView.NextSelectableWithAccel(CurViewer: TTBItemViewer; + Key: Char; RequirePrimaryAccel: Boolean; var IsOnlyItemWithAccel: Boolean): TTBItemViewer; + + function IsAccelItem(const Index: Integer; + const Primary, EnabledItems: Boolean): Boolean; + var + S: String; + LastAccel: Char; + Viewer: TTBItemViewer; + Item: TTBCustomItem; + begin + Result := False; + Viewer := FViewers[Index]; + Item := Viewer.Item; + if (Viewer.Show or Viewer.Clipped) and (tbisSelectable in Item.ItemStyle) and + (Item.Enabled = EnabledItems) and + Item.Visible and Viewer.CaptionShown then begin + S := Viewer.GetCaptionText; + if S <> '' then begin + LastAccel := FindAccelChar(S); + if Primary then begin + if LastAccel <> #0 then + Result := AnsiCompareText(LastAccel, Key) = 0; + end + else + if (LastAccel = #0) and (Key <> ' ') then + Result := AnsiCompareText(S[1], Key) = 0; + end; + end; + end; + + function FindAccel(I: Integer; + const Primary, EnabledItems: Boolean): Integer; + var + J: Integer; + begin + Result := -1; + J := -1; + while True do begin + Inc(I); + if I >= FViewerCount then I := 0; + if J = -1 then + J := I + else + if I = J then + Break; + if IsAccelItem(I, Primary, EnabledItems) then begin + Result := I; + Break; + end; + end; + end; + +var + Start, I: Integer; + Primary, EnabledItems: Boolean; +begin + ValidatePositions; + Result := nil; + IsOnlyItemWithAccel := False; + if FViewerCount = 0 then Exit; + + Start := IndexOf(CurViewer); + for Primary := True downto False do + if not RequirePrimaryAccel or Primary then + for EnabledItems := True downto False do begin + I := FindAccel(Start, Primary, EnabledItems); + if I <> -1 then begin + Result := FViewers[I]; + IsOnlyItemWithAccel := not EnabledItems or + (FindAccel(I, Primary, EnabledItems) = I); + Exit; + end; + end; +end; + +procedure TTBView.EnterToolbarLoop(Options: TTBEnterToolbarLoopOptions); +var + ModalHandler: TTBModalHandler; + P: TPoint; +begin + if vsModal in FState then Exit; + ModalHandler := TTBModalHandler.Create(FWindow.Handle); + try + { remove all states except... } + FState := FState * [vsShowAccels]; + try + Include(FState, vsModal); + { Must ensure that DoneAction is reset to tbdaNone *before* calling + NotifyFocusEvent so that the IsModalEnding call it makes won't return + True } + FDoneActionData.DoneAction := tbdaNone; + { Now that the vsModal state has been added, send an MSAA focus event } + if Assigned(Selected) then + NotifyFocusEvent; + ModalHandler.Loop(Self, tbetMouseDown in Options, + tbetExecuteSelected in Options, tbetFromMSAA in Options, False); + finally + { Remove vsModal state from the root view before any TTBView.Destroy + methods get called (as a result of the CloseChildPopups call below), + so that NotifyFocusEvent becomes a no-op } + Exclude(FState, vsModal); + StopAllTimers; + CloseChildPopups; + GetCursorPos(P); + UpdateSelection(@P, True); + end; + finally + ModalHandler.Free; + end; + SetAccelsVisibility(False); + Selected := nil; + // caused flicker: FWindow.Update; + ProcessDoneAction(FDoneActionData, False); +end; + +procedure TTBView.SetCustomizing(Value: Boolean); +begin + if FCustomizing <> Value then begin + FCustomizing := Value; + RecreateAllViewers; + end; +end; + +procedure TTBView.BeginUpdate; +begin + Inc(FUpdating); +end; + +procedure TTBView.EndUpdate; +begin + Dec(FUpdating); + if FUpdating = 0 then + TryValidatePositions; +end; + +procedure TTBView.GetOffEdgeControlList(const List: TList); +var + I: Integer; + Item: TTBCustomItem; +begin + for I := 0 to FViewerCount-1 do begin + Item := FViewers[I].Item; + if (Item is TTBControlItem) and FViewers[I].OffEdge and + (TTBControlItem(Item).FControl is TWinControl) then + List.Add(TTBControlItem(Item).FControl); + end; +end; + +procedure TTBView.SetCapture; +begin + FCapture := True; +end; + +procedure TTBView.CancelCapture; +begin + if FCapture then begin + FCapture := False; + LastPos.X := Low(LastPos.X); + if Assigned(FSelected) then + FSelected.LosingCapture; + end; +end; + +procedure TTBView.KeyDown(var Key: Word; Shift: TShiftState); + + procedure SelNextItem(const ParentView: TTBView; const GoForward: Boolean); + begin + ParentView.Selected := ParentView.NextSelectable(ParentView.FSelected, + GoForward); + ParentView.ScrollSelectedIntoView; + end; + + procedure HelpKey; + var + V: TTBView; + ContextID: Integer; + begin + ContextID := 0; + V := Self; + while Assigned(V) do begin + if Assigned(V.FSelected) then begin + ContextID := V.FSelected.Item.HelpContext; + if ContextID <> 0 then Break; + end; + V := V.FParentView; + end; + if ContextID <> 0 then + EndModalWithHelp(ContextID); + end; + +var + ParentTBView: TTBView; +begin + ParentTBView := GetParentToolbarView; + case Key of + VK_TAB: begin + SelNextItem(Self, GetKeyState(VK_SHIFT) >= 0); + end; + VK_RETURN: begin + ExecuteSelected(True); + end; + VK_MENU, VK_F10: begin + EndModal; + end; + VK_ESCAPE: begin + Key := 0; + if FParentView = nil then + EndModal + else + FParentView.CancelChildPopups; + end; + VK_LEFT, VK_RIGHT: begin + if (Self = ParentTBView) and (Orientation = tbvoVertical) then + OpenChildPopup(True) + else if Key = VK_LEFT then begin + if Assigned(ParentTBView) and (ParentTBView.Orientation <> tbvoVertical) then begin + if (Self = ParentTBView) or + (FParentView = ParentTBView) then + SelNextItem(ParentTBView, False) + else + FParentView.CloseChildPopups; + end + else begin + if Assigned(FParentView) then + FParentView.CancelChildPopups; + end; + end + else begin + if ((Self = ParentTBView) or not OpenChildPopup(True)) and + (Assigned(ParentTBView) and (ParentTBView.Orientation <> tbvoVertical)) then begin + { If we're on ParentTBView, or if the selected item can't display + a submenu, proceed to next item on ParentTBView } + SelNextItem(ParentTBView, True); + end; + end; + end; + VK_UP, VK_DOWN: begin + if (Self = ParentTBView) and (Orientation <> tbvoVertical) then + OpenChildPopup(True) + else + SelNextItem(Self, Key = VK_DOWN); + end; + VK_HOME, VK_END: begin + Selected := NextSelectable(nil, Key = VK_HOME); + ScrollSelectedIntoView; + end; + VK_F1: HelpKey; + else + Exit; { don't set Key to 0 for unprocessed keys } + end; + Key := 0; +end; + +function TTBView.IsModalEnding: Boolean; +begin + Result := (GetRootView.FDoneActionData.DoneAction <> tbdaNone); +end; + +procedure TTBView.EndModal; +var + RootView: TTBView; +begin + RootView := GetRootView; + RootView.FDoneActionData.DoneAction := tbdaCancel; +end; + +procedure TTBView.EndModalWithClick(AViewer: TTBItemViewer); +var + RootView: TTBView; +begin + RootView := GetRootView; + RootView.FDoneActionData.ClickItem := AViewer.Item; + RootView.FDoneActionData.Sound := AViewer.FView.FIsPopup; + RootView.FDoneActionData.DoneAction := tbdaClickItem; +end; + +procedure TTBView.EndModalWithHelp(AContextID: Integer); +var + RootView: TTBView; +begin + RootView := GetRootView; + RootView.FDoneActionData.ContextID := AContextID; + RootView.FDoneActionData.DoneAction := tbdaHelpContext; +end; + +procedure TTBView.EndModalWithSystemMenu(AWnd: HWND; AKey: Cardinal); +var + RootView: TTBView; +begin + RootView := GetRootView; + RootView.FDoneActionData.Wnd := AWnd; + RootView.FDoneActionData.Key := AKey; + RootView.FDoneActionData.DoneAction := tbdaOpenSystemMenu; +end; + +procedure TTBView.ExecuteSelected(AGivePriority: Boolean); +{ Normally called after an Enter or accelerator key press on the view, this + method 'executes' or opens the selected item. It ends the modal loop, except + when a submenu is opened. } +var + Item: TTBCustomItem; +begin + if Assigned(FSelected) and FSelected.Item.Enabled then begin + Item := FSelected.Item; + if (tbisCombo in Item.ItemStyle) or not OpenChildPopup(True) then begin + if tbisSelectable in Item.ItemStyle then + FSelected.Execute(AGivePriority) + else + EndModal; + end + end + else + EndModal; + Exit; asm db 0,'Toolbar2000 (C) 1998-2005 Jordan Russell',0 end; +end; + +procedure TTBView.Scroll(ADown: Boolean); +var + CurPos, NewPos, I: Integer; +begin + ValidatePositions; + if ADown then begin + NewPos := High(NewPos); + CurPos := FMaxHeight - tbMenuScrollArrowHeight; + for I := 0 to FViewerCount-1 do begin + with FViewers[I] do + if Clipped and not(tbisSeparator in Item.ItemStyle) and + (BoundsRect.Bottom < NewPos) and (BoundsRect.Bottom > CurPos) then + NewPos := BoundsRect.Bottom; + end; + if NewPos = High(NewPos) then + Exit; + Dec(NewPos, FMaxHeight - tbMenuScrollArrowHeight); + end + else begin + NewPos := Low(NewPos); + CurPos := tbMenuScrollArrowHeight; + for I := 0 to FViewerCount-1 do begin + with FViewers[I] do + if Clipped and not(tbisSeparator in Item.ItemStyle) and + (BoundsRect.Top > NewPos) and (BoundsRect.Top < CurPos) then + NewPos := BoundsRect.Top; + end; + if NewPos = Low(NewPos) then + Exit; + Dec(NewPos, tbMenuScrollArrowHeight); + end; + Inc(FScrollOffset, NewPos); + UpdatePositions; +end; + +procedure TTBView.ScrollSelectedIntoView; +begin + ValidatePositions; + if (FSelected = nil) or not FSelected.Clipped then + Exit; + + if FSelected.BoundsRect.Top < tbMenuScrollArrowHeight then begin + Dec(FScrollOffset, tbMenuScrollArrowHeight - FSelected.BoundsRect.Top); + UpdatePositions; + end + else if FSelected.BoundsRect.Bottom > FMaxHeight - tbMenuScrollArrowHeight then begin + Dec(FScrollOffset, (FMaxHeight - tbMenuScrollArrowHeight) - + FSelected.BoundsRect.Bottom); + UpdatePositions; + end; +end; + +procedure TTBView.SetUsePriorityList(Value: Boolean); +begin + if FUsePriorityList <> Value then begin + FUsePriorityList := Value; + RecreateAllViewers; + end; +end; + +function TTBView.GetCaptureWnd: HWND; +begin + Result := GetRootView.FCaptureWnd; +end; + +procedure TTBView.CancelMode; +var + View: TTBView; +begin + EndModal; + + { Hide all parent/child popup windows. Can't actually destroy them using + CloseChildPopups because this method may be called while inside + TTBEditItemViewer's message loop, and it could result in the active + TTBEditItemViewer instance being destroyed (leading to an AV). } + View := Self; + while Assigned(View.FOpenViewerView) do + View := View.FOpenViewerView; + repeat + View.StopAllTimers; + if View.FWindow is TTBPopupWindow then + View.FWindow.Visible := False; + View := View.FParentView; + until View = nil; + + { Note: This doesn't remove the selection from a top-level toolbar item. + Unfortunately, we can't do 'Selected := nil' because it would destroy + child popups and that must'nt happen for the reason stated above. } +end; + + +{ TTBModalHandler } + +const + LSFW_LOCK = 1; + LSFW_UNLOCK = 2; + +var + LockSetForegroundWindowInited: BOOL; + LockSetForegroundWindow: function(uLockCode: UINT): BOOL; stdcall; + +constructor TTBModalHandler.Create(AExistingWnd: HWND); +begin + inherited Create; + if not LockSetForegroundWindowInited then begin + LockSetForegroundWindow := GetProcAddress(GetModuleHandle(user32), + 'LockSetForegroundWindow'); + InterlockedExchange(Integer(LockSetForegroundWindowInited), Ord(True)); + end; + LastPos := SmallPointToPoint(TSmallPoint(GetMessagePos())); + if AExistingWnd <> 0 then + FWnd := AExistingWnd + else begin + FWnd := {$IFDEF JR_D6}Classes.{$ENDIF} AllocateHWnd(WndProc); + FCreatedWnd := True; + end; + if Assigned(LockSetForegroundWindow) then begin + { Like standard menus, don't allow other apps to steal the focus during + our modal loop. This also prevents us from losing activation when + "active window tracking" is enabled and the user moves the mouse over + another application's window. } + LockSetForegroundWindow(LSFW_LOCK); + end; + SetCapture(FWnd); + SetCursor(LoadCursor(0, IDC_ARROW)); + CallNotifyWinEvent(EVENT_SYSTEM_MENUSTART, FWnd, OBJID_CLIENT, CHILDID_SELF); + FInited := True; +end; + +destructor TTBModalHandler.Destroy; +begin + if Assigned(LockSetForegroundWindow) then + LockSetForegroundWindow(LSFW_UNLOCK); + if FWnd <> 0 then begin + if GetCapture = FWnd then + ReleaseCapture; + if FInited then + CallNotifyWinEvent(EVENT_SYSTEM_MENUEND, FWnd, OBJID_CLIENT, CHILDID_SELF); + if FCreatedWnd then + {$IFDEF JR_D6}Classes.{$ENDIF} DeallocateHWnd(FWnd); + end; + inherited; +end; + +procedure TTBModalHandler.WndProc(var Msg: TMessage); +begin + Msg.Result := DefWindowProc(FWnd, Msg.Msg, Msg.WParam, Msg.LParam); + if (Msg.Msg = WM_CANCELMODE) and Assigned(FRootPopup) then begin + try + { We can receive a WM_CANCELMODE message during a modal loop if a dialog + pops up. Respond by hiding menus to make it look like the modal loop + has returned, even though it really hasn't yet. + Note: Similar code in TTBCustomToolbar.WMCancelMode. } + FRootPopup.View.CancelMode; + except + Application.HandleException(Self); + end; + end; +end; + +procedure TTBModalHandler.Loop(const RootView: TTBView; + const AMouseDown, AExecuteSelected, AFromMSAA, TrackRightButton: Boolean); +var + OriginalActiveWindow: HWND; + + function GetActiveView: TTBView; + begin + Result := RootView; + while Assigned(Result.FOpenViewerView) do + Result := Result.FOpenViewerView; + end; + + procedure UpdateAllSelections(const P: TPoint; const AllowNewSelection: Boolean); + var + View, CapView: TTBView; + begin + View := GetActiveView; + + CapView := View; + while Assigned(CapView) and not CapView.FCapture do + CapView := CapView.FParentView; + + while Assigned(View) do begin + if (CapView = nil) or (View = CapView) then + View.UpdateSelection(@P, AllowNewSelection); + View := View.FParentView; + end; + end; + + function GetSelectedViewer(var AView: TTBView; var AViewer: TTBItemViewer): Boolean; + { Returns True if AViewer <> nil. } + var + View: TTBView; + begin + AView := nil; + AViewer := nil; + { Look for a capture item first } + View := RootView; + repeat + if View.FCapture then begin + AView := View; + AViewer := View.FSelected; + Break; + end; + View := View.FOpenViewerView; + until View = nil; + if View = nil then begin + View := RootView; + repeat + if Assigned(View.FSelected) and View.FMouseOverSelected then begin + AView := View; + AViewer := View.FSelected; + Break; + end; + if vsMouseInWindow in View.FState then begin + { ...there is no current selection, but the mouse is still in the + window. This can happen if the mouse is over the non-client area + of the toolbar or popup window, or in an area not containing an + item. } + AView := View; + Break; + end; + View := View.FOpenViewerView; + until View = nil; + end; + Result := Assigned(AViewer); + end; + + function ContinueLoop: Boolean; + begin + { Don't continue if the mouse capture is lost, if a (modeless) top-level + window is shown causing the active window to change, or if EndModal* was + called. } + Result := (GetCapture = FWnd) and (GetActiveWindow = OriginalActiveWindow) + and not RootView.IsModalEnding; + end; + + function SendKeyEvent(const View: TTBView; var Key: Word; + const Shift: TShiftState): Boolean; + begin + Result := True; + if Assigned(View.FSelected) then begin + View.FSelected.KeyDown(Key, Shift); + if RootView.IsModalEnding then + Exit; + end; + if Key <> 0 then begin + View.KeyDown(Key, Shift); + if RootView.IsModalEnding then + Exit; + end; + Result := False; + end; + + procedure DoHintMouseMessage(const Ctl: TControl; const P: TPoint); + var + M: TWMMouseMove; + begin + M.Msg := WM_MOUSEMOVE; + M.Keys := 0; + M.Pos := PointToSmallPoint(P); + Application.HintMouseMessage(Ctl, TMessage(M)); + end; + + procedure MouseMoved; + var + View: TTBView; + Cursor: HCURSOR; + Item: TTBCustomItem; + P: TPoint; + R: TRect; + begin + UpdateAllSelections(LastPos, True); + View := GetActiveView; + Cursor := 0; + if Assigned(View.FSelected) and Assigned(View.FWindow) then begin + Item := View.FSelected.Item; + P := View.FWindow.ScreenToClient(LastPos); + if ((vsAlwaysShowHints in View.FStyle) or + (tboShowHint in Item.FEffectiveOptions)) and not View.FCapture then begin + { Display popup hint for the item. Update is called + first to minimize flicker caused by the hiding & + showing of the hint window. } + View.FWindow.Update; + DoHintMouseMessage(View.FWindow, P); + end + else + Application.CancelHint; + R := View.FSelected.BoundsRect; + Dec(P.X, R.Left); + Dec(P.Y, R.Top); + View.FSelected.GetCursor(P, Cursor); + end + else + Application.CancelHint; + if Cursor = 0 then + Cursor := LoadCursor(0, IDC_ARROW); + SetCursor(Cursor); + end; + + procedure UpdateAppHint; + var + View: TTBView; + begin + View := RootView; + while Assigned(View.FOpenViewerView) and Assigned(View.FOpenViewerView.FSelected) do + View := View.FOpenViewerView; + if Assigned(View.FSelected) then + Application.Hint := GetLongHint(View.FSelected.Item.Hint) + else + Application.Hint := ''; + end; + + procedure HandleTimer(const View: TTBView; const ID: TTBViewTimerID); + begin + case ID of + tiOpen: begin + { Similar to standard menus, always close child popups, even if + Selected = OpenViewer. + Note: CloseChildPopups and OpenChildPopup will stop the tiClose + and tiOpen timers respectively. } + View.CloseChildPopups; + View.OpenChildPopup(False); + end; + tiClose: begin + { Note: CloseChildPopups stops the tiClose timer. } + View.CloseChildPopups; + end; + tiScrollUp: begin + if View.FShowUpArrow then + View.Scroll(False) + else + View.StopTimer(tiScrollUp); + end; + tiScrollDown: begin + if View.FShowDownArrow then + View.Scroll(True) + else + View.StopTimer(tiScrollDown); + end; + end; + end; + +var + MouseDownOnMenu: Boolean; + Msg: TMsg; + P: TPoint; + Ctl: TControl; + View: TTBView; + IsOnlyItemWithAccel: Boolean; + MouseIsDown: Boolean; + Key: Word; + Shift: TShiftState; + Viewer: TTBItemViewer; +begin + FillChar(RootView.FDoneActionData, SizeOf(RootView.FDoneActionData), 0); + RootView.ValidatePositions; + try + try + RootView.FCaptureWnd := FWnd; + MouseDownOnMenu := False; + if AMouseDown then begin + P := RootView.FSelected.ScreenToClient(SmallPointToPoint(TSmallPoint(GetMessagePos()))); + RootView.FSelected.MouseDown([], P.X, P.Y, MouseDownOnMenu); + if RootView.IsModalEnding then + Exit; + MouseDownOnMenu := False; { never set MouseDownOnMenu to True on first click } + end + else if AExecuteSelected then begin + RootView.ExecuteSelected(not AFromMSAA); + if RootView.IsModalEnding then + Exit; + end; + OriginalActiveWindow := GetActiveWindow; + while ContinueLoop do begin + { Examine the next message before popping it out of the queue } + if not PeekMessage(Msg, 0, 0, 0, PM_NOREMOVE) then begin + WaitMessage; + Continue; + end; + case Msg.message of + WM_LBUTTONDOWN, WM_RBUTTONDOWN: begin + P := SmallPointToPoint(TSmallPoint(Msg.lParam)); + Windows.ClientToScreen(Msg.hwnd, P); + Ctl := FindDragTarget(P, True); + { Was the mouse not clicked on a popup, or was it clicked on a + popup that is not a child of RootView? + (The latter can happen when in customization mode, for example, + if the user right-clicks a popup menu being customized and + the context menu is displayed.) } + if not(Ctl is TTBPopupWindow) or + not RootView.ContainsView(TTBPopupWindow(Ctl).View) then begin + { If the root view is a popup, or if the root view is a toolbar + and the user clicked outside the toolbar or in its non-client + area (e.g. on its drag handle), exit } + if RootView.FIsPopup or (Ctl <> RootView.FWindow) or + not PtInRect(RootView.FWindow.ClientRect, RootView.FWindow.ScreenToClient(P)) then + Exit + else + if Msg.message = WM_LBUTTONDOWN then begin + { If the user clicked inside a toolbar on anything but an + item, exit } + UpdateAllSelections(P, True); + if (RootView.FSelected = nil) or not RootView.FMouseOverSelected or + (tbisClicksTransparent in RootView.FSelected.Item.ItemStyle) then + Exit; + end; + end; + end; + end; + { Now pop the message out of the queue } + if not PeekMessage(Msg, 0, Msg.message, Msg.message, PM_REMOVE or PM_NOYIELD) then + Continue; + case Msg.message of + $4D: + { This undocumented message is sent to the focused window when + F1 is pressed. Windows handles it by sending a WM_HELP message + to the same window. We don't want this to happen while a menu + is up, so swallow the message. } + ; + WM_CONTEXTMENU: + { Windows still sends WM_CONTEXTMENU messages for "context menu" + keystrokes even if WM_KEYUP messages are never dispatched, + so it must specifically ignore this message } + ; + WM_KEYFIRST..WM_KEYLAST: begin + Application.CancelHint; + MouseIsDown := (GetKeyState(VK_LBUTTON) < 0) or + (TrackRightButton and (GetKeyState(VK_RBUTTON) < 0)); + case Msg.message of + WM_KEYDOWN, WM_SYSKEYDOWN: + begin + if Msg.wParam = VK_PROCESSKEY then + { Don't let IME process the key } + Msg.wParam := ImmGetVirtualKey(Msg.hwnd); + if not MouseIsDown or (Msg.wParam = VK_F1) then begin + Key := Word(Msg.wParam); + if SendKeyEvent(GetActiveView, Key, + KeyDataToShiftState(Msg.lParam)) then + Exit; + { If it's not handled by a KeyDown method, translate + it into a WM_*CHAR message } + if Key <> 0 then + TranslateMessage(Msg); + end; + end; + WM_CHAR, WM_SYSCHAR: + if not MouseIsDown then begin + View := GetActiveView; + Viewer := View.NextSelectableWithAccel(View.FSelected, + Chr(Msg.WParam), False, IsOnlyItemWithAccel); + if Viewer = nil then begin + if (Msg.WParam in [VK_SPACE, Ord('-')]) and + not RootView.FIsPopup and (View = RootView) and + (GetActiveWindow <> 0) then begin + RootView.EndModalWithSystemMenu(GetActiveWindow, + Msg.WParam); + Exit; + end + else + MessageBeep(0); + end + else begin + View.Selected := Viewer; + View.ScrollSelectedIntoView; + if IsOnlyItemWithAccel then + View.ExecuteSelected(True); + end; + end; + end; + end; + WM_TIMER: + begin + Ctl := FindControl(Msg.hwnd); + if Assigned(Ctl) and (Ctl is TTBPopupWindow) and + (Msg.wParam >= ViewTimerBaseID + Ord(Low(TTBViewTimerID))) and + (Msg.wParam <= ViewTimerBaseID + Ord(High(TTBViewTimerID))) then begin + if Assigned(TTBPopupWindow(Ctl).FView) then + HandleTimer(TTBPopupWindow(Ctl).FView, + TTBViewTimerID(WPARAM(Msg.wParam - ViewTimerBaseID))); + end + else + DispatchMessage(Msg); + end; + $118: ; + { ^ Like standard menus, don't dispatch WM_SYSTIMER messages + (the internal Windows message used for things like caret + blink and list box scrolling). } + WM_MOUSEFIRST..WM_MOUSELAST: + case Msg.message of + WM_MOUSEMOVE: begin + if (Msg.pt.X <> LastPos.X) or (Msg.pt.Y <> LastPos.Y) then begin + LastPos := Msg.pt; + MouseMoved; + end; + if GetSelectedViewer(View, Viewer) then begin + P := Viewer.ScreenToClient(Msg.pt); + Viewer.MouseMove(P.X, P.Y); + end; + end; + WM_MOUSEWHEEL: + if GetSelectedViewer(View, Viewer) then begin + P := Viewer.ScreenToClient(Msg.pt); + Viewer.MouseWheel(Smallint(LongRec(Msg.wParam).Hi), P.X, P.Y); + end; + WM_LBUTTONDOWN, WM_LBUTTONDBLCLK, WM_RBUTTONDOWN: + if (Msg.message <> WM_RBUTTONDOWN) or TrackRightButton then begin + Application.CancelHint; + MouseDownOnMenu := False; + Exclude(RootView.FState, vsIgnoreFirstMouseUp); + UpdateAllSelections(Msg.pt, True); + if GetSelectedViewer(View, Viewer) then begin + if Msg.message <> WM_LBUTTONDBLCLK then + Shift := [] + else + Shift := [ssDouble]; + P := Viewer.ScreenToClient(Msg.pt); + Viewer.MouseDown(Shift, P.X, P.Y, MouseDownOnMenu); + LastPos := SmallPointToPoint(TSmallPoint(GetMessagePos())); + end; + end; + WM_LBUTTONUP, WM_RBUTTONUP: + if (Msg.message = WM_LBUTTONUP) or TrackRightButton then begin + UpdateAllSelections(Msg.pt, False); + { ^ False is used so that when a popup menu is + displayed with the cursor currently inside it, the item + under the cursor won't be accidentally selected when the + user releases the button. The user must move the mouse at + at least one pixel (generating a WM_MOUSEMOVE message), + and then release the button. } + if not GetSelectedViewer(View, Viewer) then begin + { Mouse was not released over any item. Cancel out of the + loop if it's outside all views, or is inside unused + space on a topmost toolbar } + if not Assigned(View) or + ((View = RootView) and RootView.FIsToolbar) then begin + if not(vsIgnoreFirstMouseUp in RootView.FState) then + Exit + else + Exclude(RootView.FState, vsIgnoreFirstMouseUp); + end; + end + else begin + P := Viewer.ScreenToClient(Msg.pt); + Viewer.MouseUp(P.X, P.Y, MouseDownOnMenu); + end; + end; + end; + else + DispatchMessage(Msg); + end; + if not ContinueLoop then + Exit; + if LastPos.X = Low(LastPos.X) then begin + LastPos := SmallPointToPoint(TSmallPoint(GetMessagePos())); + MouseMoved; + end; + UpdateAppHint; + end; + finally + RootView.CancelCapture; + end; + finally + RootView.FCaptureWnd := 0; + Application.Hint := ''; + { Make sure there are no outstanding WM_*CHAR messages } + RemoveMessages(WM_CHAR, WM_DEADCHAR); + RemoveMessages(WM_SYSCHAR, WM_SYSDEADCHAR); + { Nor any outstanding 'send WM_HELP' messages caused by an earlier press + of the F1 key } + RemoveMessages($4D, $4D); + end; +end; + + +{ TTBPopupView } + +procedure TTBPopupView.AutoSize(AWidth, AHeight: Integer); +begin + with FWindow do + SetBounds(Left, Top, AWidth + (PopupMenuWindowNCSize * 2), + AHeight + (PopupMenuWindowNCSize * 2)); +end; + +function TTBPopupView.GetFont: TFont; +begin + Result := (Owner as TTBPopupWindow).Font; +end; + + +{ TTBPopupWindow } + +constructor TTBPopupWindow.CreatePopupWindow(AOwner: TComponent; + const AParentView: TTBView; const AItem: TTBCustomItem; + const ACustomizing: Boolean); +begin + inherited Create(AOwner); + Visible := False; + SetBounds(0, 0, 320, 240); + ControlStyle := ControlStyle - [csCaptureMouse]; + ShowHint := True; + Color := tbMenuBkColor; + FView := GetViewClass.CreateView(Self, AParentView, AItem, Self, False, + ACustomizing, False); + Include(FView.FState, vsModal); + + { Inherit the font from the parent view, or use the system menu font if + there is no parent view } + if Assigned(AParentView) then + Font.Assign(AParentView.GetFont) + else + Font.Assign(ToolbarFont); + + { Inherit the accelerator visibility state from the parent view. If there + is no parent view (i.e. it's a standalone popup menu), then default to + hiding accelerator keys, but change this in CreateWnd if the last input + came from the keyboard. } + if Assigned(AParentView) then begin + if vsUseHiddenAccels in AParentView.FStyle then + Include(FView.FStyle, vsUseHiddenAccels); + if vsShowAccels in AParentView.FState then + Include(FView.FState, vsShowAccels); + end + else + Include(FView.FStyle, vsUseHiddenAccels); + + if Application.Handle <> 0 then + { Use Application.Handle if possible so that the taskbar button for the app + doesn't pop up when a TTBEditItem on a popup menu is focused } + ParentWindow := Application.Handle + else + { When Application.Handle is zero, use GetDesktopWindow() as the parent + window, not zero, otherwise UpdateControlState won't show the window } + ParentWindow := GetDesktopWindow; +end; + +destructor TTBPopupWindow.Destroy; +begin + Destroying; + { Ensure window handle is destroyed *before* FView is freed, since + DestroyWindowHandle calls CallNotifyWinEvent which may result in + FView.HandleWMObject being called } + if HandleAllocated then + DestroyWindowHandle; + FreeAndNil(FView); + inherited; +end; + +procedure TTBPopupWindow.BeforeDestruction; +begin + { The inherited BeforeDestruction method hides the form. We need to close + any child popups first, so that pixels behind the popups are properly + restored without generating a WM_PAINT message. } + if Assigned(FView) then + FView.CloseChildPopups; + inherited; +end; + +function TTBPopupWindow.GetViewClass: TTBViewClass; +begin + Result := TTBPopupView; +end; + +procedure TTBPopupWindow.CreateParams(var Params: TCreateParams); +const + CS_DROPSHADOW = $00020000; +begin + inherited; + with Params do begin + Style := (Style and not (WS_CHILD or WS_GROUP or WS_TABSTOP)) or WS_POPUP; + ExStyle := ExStyle or WS_EX_TOPMOST or WS_EX_TOOLWINDOW; + WindowClass.Style := WindowClass.Style or CS_SAVEBITS; + { Enable drop shadow effect on Windows XP and later } + if IsWindowsXP then + WindowClass.Style := WindowClass.Style or CS_DROPSHADOW; + end; +end; + +procedure TTBPopupWindow.CreateWnd; +const + WM_CHANGEUISTATE = $0127; + WM_QUERYUISTATE = $0129; + UIS_INITIALIZE = 3; + UISF_HIDEACCEL = $2; +var + B: Boolean; +begin + inherited; + { On a top-level popup window, send WM_CHANGEUISTATE & WM_QUERYUISTATE + messages to the window to see if the last input came from the keyboard + and if the accelerator keys should be shown } + if (FView.ParentView = nil) and not FAccelsVisibilitySet then begin + FAccelsVisibilitySet := True; + SendMessage(Handle, WM_CHANGEUISTATE, UIS_INITIALIZE, 0); + B := (SendMessage(Handle, WM_QUERYUISTATE, 0, 0) and UISF_HIDEACCEL = 0); + FView.SetAccelsVisibility(B); + end; +end; + +procedure TTBPopupWindow.DestroyWindowHandle; +begin + { Before destroying the window handle, we must stop any animation, otherwise + the animation thread will use an invalid handle } + TBEndAnimation(WindowHandle); + { Cleanly destroy any timers before the window handle is destroyed } + if Assigned(FView) then + FView.StopAllTimers; + CallNotifyWinEvent(EVENT_SYSTEM_MENUPOPUPEND, WindowHandle, OBJID_CLIENT, + CHILDID_SELF); + inherited; +end; + +procedure TTBPopupWindow.WMGetObject(var Message: TMessage); +begin + if not FView.HandleWMGetObject(Message) then + inherited; +end; + +procedure TTBPopupWindow.CMShowingChanged(var Message: TMessage); +const + ShowFlags: array[Boolean] of UINT = ( + SWP_NOSIZE or SWP_NOMOVE or SWP_NOZORDER or SWP_NOACTIVATE or SWP_HIDEWINDOW, + SWP_NOSIZE or SWP_NOMOVE or SWP_NOZORDER or SWP_NOACTIVATE or SWP_SHOWWINDOW); + SPI_GETMENUFADE = $1012; +var + Animate: BOOL; + Blend: Boolean; +begin + { Must override TCustomForm/TForm's CM_SHOWINGCHANGED handler so that the + form doesn't get activated when Visible is set to True. } + + { Handle animation. NOTE: I do not recommend trying to enable animation on + Windows 95 and NT 4.0 because there's a difference in the way the + SetWindowPos works on those versions. See the comment in the + TBStartAnimation function of TB2Anim.pas. } + {$IFNDEF TB2K_NO_ANIMATION} + if ((FView.ParentView = nil) or not(vsNoAnimation in FView.FParentView.FState)) and + Showing and (FView.Selected = nil) and not IsWindowVisible(WindowHandle) and + SystemParametersInfo(SPI_GETMENUANIMATION, 0, @Animate, 0) and Animate then begin + Blend := SystemParametersInfo(SPI_GETMENUFADE, 0, @Animate, 0) and Animate; + if Blend or (FAnimationDirection <> []) then begin + TBStartAnimation(WindowHandle, Blend, FAnimationDirection); + Exit; + end; + end; + {$ENDIF} + + { No animation... } + if not Showing then begin + { Call TBEndAnimation to ensure WS_EX_LAYERED style is removed before + hiding, otherwise windows under the popup window aren't repainted + properly. } + TBEndAnimation(WindowHandle); + end; + SetWindowPos(WindowHandle, 0, 0, 0, 0, 0, ShowFlags[Showing]); +end; + +procedure TTBPopupWindow.WMTB2kStepAnimation(var Message: TMessage); +begin + TBStepAnimation(Message); +end; + +procedure TTBPopupWindow.WMEraseBkgnd(var Message: TWMEraseBkgnd); +begin + { May be necessary in some cases... } + TBEndAnimation(WindowHandle); + inherited; +end; + +procedure TTBPopupWindow.WMPaint(var Message: TWMPaint); +begin + { Must abort animation when a WM_PAINT message is received } + TBEndAnimation(WindowHandle); + inherited; +end; + +procedure TTBPopupWindow.Paint; +begin + FView.DrawSubitems(Canvas); + PaintScrollArrows; +end; + +procedure TTBPopupWindow.PaintScrollArrows; + + procedure DrawArrow(const R: TRect; ADown: Boolean); + var + X, Y: Integer; + P: array[0..2] of TPoint; + begin + X := (R.Left + R.Right) div 2; + Y := (R.Top + R.Bottom) div 2; + Dec(Y); + P[0].X := X-3; + P[0].Y := Y; + P[1].X := X+3; + P[1].Y := Y; + P[2].X := X; + P[2].Y := Y; + if ADown then + Inc(P[2].Y, 3) + else begin + Inc(P[0].Y, 3); + Inc(P[1].Y, 3); + end; + Canvas.Pen.Color := tbMenuTextColor; + Canvas.Brush.Color := tbMenuTextColor; + Canvas.Polygon(P); + end; + +begin + if FView.FShowUpArrow then + DrawArrow(Rect(0, 0, ClientWidth, tbMenuScrollArrowHeight), False); + if FView.FShowDownArrow then + DrawArrow(Bounds(0, ClientHeight - tbMenuScrollArrowHeight, + ClientWidth, tbMenuScrollArrowHeight), True); +end; + +procedure TTBPopupWindow.WMClose(var Message: TWMClose); +begin + { do nothing -- ignore Alt+F4 keypresses } +end; + +procedure TTBPopupWindow.WMNCCalcSize(var Message: TWMNCCalcSize); +begin + InflateRect(Message.CalcSize_Params^.rgrc[0], + -PopupMenuWindowNCSize, -PopupMenuWindowNCSize); + inherited; +end; + +procedure PopupWindowNCPaintProc(Wnd: HWND; DC: HDC; AppData: Longint); +var + R: TRect; + {$IFNDEF TB2K_USE_STRICT_O2K_MENU_STYLE} + Brush: HBRUSH; + {$ENDIF} +begin + GetWindowRect(Wnd, R); OffsetRect(R, -R.Left, -R.Top); + {$IFNDEF TB2K_USE_STRICT_O2K_MENU_STYLE} + if not AreFlatMenusEnabled then begin + {$ENDIF} + DrawEdge(DC, R, EDGE_RAISED, BF_RECT or BF_ADJUST); + FrameRect(DC, R, GetSysColorBrush(COLOR_BTNFACE)); + {$IFNDEF TB2K_USE_STRICT_O2K_MENU_STYLE} + end + else begin + FrameRect(DC, R, GetSysColorBrush(COLOR_BTNSHADOW)); + Brush := CreateSolidBrush(ColorToRGB(TTBPopupWindow(AppData).Color)); + InflateRect(R, -1, -1); + FrameRect(DC, R, Brush); + InflateRect(R, -1, -1); + FrameRect(DC, R, Brush); + DeleteObject(Brush); + end; + {$ENDIF} +end; + +procedure TTBPopupWindow.WMNCPaint(var Message: TMessage); +var + DC: HDC; +begin + DC := GetWindowDC(Handle); + try + SelectNCUpdateRgn(Handle, DC, HRGN(Message.WParam)); + PopupWindowNCPaintProc(Handle, DC, Longint(Self)); + finally + ReleaseDC(Handle, DC); + end; +end; + +procedure TTBPopupWindow.WMPrint(var Message: TMessage); +begin + HandleWMPrint(Handle, Message, PopupWindowNCPaintProc, Longint(Self)); +end; + +procedure TTBPopupWindow.WMPrintClient(var Message: TMessage); +begin + HandleWMPrintClient(Self, Message); +end; + +procedure TTBPopupWindow.CMHintShow(var Message: TCMHintShow); +begin + with Message.HintInfo^ do begin + HintStr := ''; + if Assigned(FView.Selected) then begin + CursorRect := FView.Selected.BoundsRect; + HintStr := FView.FSelected.GetHintText; + end; + end; +end; + + +{ TTBItemContainer } + +constructor TTBItemContainer.Create(AOwner: TComponent); +begin + inherited; + FItem := TTBRootItem.Create(Self); + FItem.ParentComponent := Self; +end; + +destructor TTBItemContainer.Destroy; +begin + FItem.Free; + inherited; +end; + +function TTBItemContainer.GetItems: TTBCustomItem; +begin + Result := FItem; +end; + +procedure TTBItemContainer.GetChildren(Proc: TGetChildProc; Root: TComponent); +begin + FItem.GetChildren(Proc, Root); +end; + +function TTBItemContainer.GetImages: TCustomImageList; +begin + Result := FItem.SubMenuImages; +end; + +procedure TTBItemContainer.SetImages(Value: TCustomImageList); +begin + FItem.SubMenuImages := Value; +end; + + +{ TTBPopupMenu } + +constructor TTBPopupMenu.Create(AOwner: TComponent); +begin + inherited; + FItem := GetRootItemClass.Create(Self); + FItem.ParentComponent := Self; + FItem.OnClick := RootItemClick; +end; + +destructor TTBPopupMenu.Destroy; +begin + FItem.Free; + inherited; +end; + +function TTBPopupMenu.GetItems: TTBCustomItem; +begin + Result := FItem; +end; + +procedure TTBPopupMenu.GetChildren(Proc: TGetChildProc; Root: TComponent); +begin + FItem.GetChildren(Proc, Root); +end; + +procedure TTBPopupMenu.SetChildOrder(Child: TComponent; Order: Integer); +begin + FItem.SetChildOrder(Child, Order); +end; + +function TTBPopupMenu.GetRootItemClass: TTBRootItemClass; +begin + Result := TTBRootItem; +end; + +function TTBPopupMenu.GetImages: TCustomImageList; +begin + Result := FItem.SubMenuImages; +end; + +function TTBPopupMenu.GetLinkSubitems: TTBCustomItem; +begin + Result := FItem.LinkSubitems; +end; + +function TTBPopupMenu.GetOptions: TTBItemOptions; +begin + Result := FItem.Options; +end; + +procedure TTBPopupMenu.SetImages(Value: TCustomImageList); +begin + FItem.SubMenuImages := Value; +end; + +procedure TTBPopupMenu.SetLinkSubitems(Value: TTBCustomItem); +begin + FItem.LinkSubitems := Value; +end; + +procedure TTBPopupMenu.SetOptions(Value: TTBItemOptions); +begin + FItem.Options := Value; +end; + +procedure TTBPopupMenu.RootItemClick(Sender: TObject); +begin + if Sender = FItem then + Sender := Self; + DoPopup(Sender); +end; + +{$IFNDEF JR_D5} +procedure TTBPopupMenu.DoPopup(Sender: TObject); +begin + if Assigned(OnPopup) then OnPopup(Sender); +end; +{$ENDIF} + +procedure TTBPopupMenu.Popup(X, Y: Integer); +begin + PopupEx(X, Y, False); +end; + +function TTBPopupMenu.PopupEx(X, Y: Integer; + ReturnClickedItemOnly: Boolean = False): TTBCustomItem; +begin + {$IFDEF JR_D5} + {$IFDEF JR_D9} + SetPopupPoint(Point(X, Y)); + {$ELSE} + PPoint(@PopupPoint)^ := Point(X, Y); + {$ENDIF} + {$ENDIF} + Result := FItem.Popup(X, Y, TrackButton = tbRightButton, + TTBPopupAlignment(Alignment), ReturnClickedItemOnly); +end; + +function TTBPopupMenu.IsShortCut(var Message: TWMKey): Boolean; +begin + Result := FItem.IsShortCut(Message); +end; + + +{ TTBImageList } + +constructor TTBCustomImageList.Create(AOwner: TComponent); +begin + inherited; + FCheckedImagesChangeLink := TChangeLink.Create; + FCheckedImagesChangeLink.OnChange := ImageListChanged; + FDisabledImagesChangeLink := TChangeLink.Create; + FDisabledImagesChangeLink.OnChange := ImageListChanged; + FHotImagesChangeLink := TChangeLink.Create; + FHotImagesChangeLink.OnChange := ImageListChanged; + FImagesBitmap := TBitmap.Create; + FImagesBitmap.OnChange := ImagesBitmapChanged; + FImagesBitmapMaskColor := clFuchsia; +end; + +destructor TTBCustomImageList.Destroy; +begin + FreeAndNil(FImagesBitmap); + FreeAndNil(FHotImagesChangeLink); + FreeAndNil(FDisabledImagesChangeLink); + FreeAndNil(FCheckedImagesChangeLink); + inherited; +end; + +procedure TTBCustomImageList.ImagesBitmapChanged(Sender: TObject); +begin + if not ImagesBitmap.Empty then begin + Clear; + AddMasked(ImagesBitmap, FImagesBitmapMaskColor); + end; +end; + +procedure TTBCustomImageList.ImageListChanged(Sender: TObject); +begin + Change; +end; + +procedure TTBCustomImageList.DefineProperties(Filer: TFiler); +type + TProc = procedure(ASelf: TObject; Filer: TFiler); +begin + if (Filer is TReader) or FImagesBitmap.Empty then + inherited + else + { Bypass TCustomImageList.DefineProperties when we've got an ImageBitmap } + TProc(@TComponentAccess.DefineProperties)(Self, Filer); +end; + +procedure TTBCustomImageList.DrawState(Canvas: TCanvas; X, Y, Index: Integer; + Enabled, Selected, Checked: Boolean); +begin + if not Enabled and Assigned(DisabledImages) then + DisabledImages.Draw(Canvas, X, Y, Index) + else if Checked and Assigned(CheckedImages) then + CheckedImages.Draw(Canvas, X, Y, Index, Enabled) + else if Selected and Assigned(HotImages) then + HotImages.Draw(Canvas, X, Y, Index, Enabled) + else + Draw(Canvas, X, Y, Index, Enabled); +end; + +procedure TTBCustomImageList.Notification(AComponent: TComponent; Operation: TOperation); +begin + inherited; + if Operation = opRemove then begin + if AComponent = CheckedImages then CheckedImages := nil; + if AComponent = DisabledImages then DisabledImages := nil; + if AComponent = HotImages then HotImages := nil; + end; +end; + +procedure TTBCustomImageList.ChangeImages(var AImageList: TCustomImageList; + Value: TCustomImageList; AChangeLink: TChangeLink); +begin + if Value = Self then + Value := nil; + if AImageList <> Value then begin + if Assigned(AImageList) then + AImageList.UnregisterChanges(AChangeLink); + AImageList := Value; + if Assigned(Value) then begin + Value.RegisterChanges(AChangeLink); + Value.FreeNotification(Self); + end; + { Don't call Change while loading because it causes the Delphi IDE to + think the form has been modified (?). Also, don't call Change while + destroying since there's no reason to. } + if not(csLoading in ComponentState) and + not(csDestroying in ComponentState) then + Change; + end; +end; + +procedure TTBCustomImageList.SetCheckedImages(Value: TCustomImageList); +begin + ChangeImages(FCheckedImages, Value, FCheckedImagesChangeLink); +end; + +procedure TTBCustomImageList.SetDisabledImages(Value: TCustomImageList); +begin + ChangeImages(FDisabledImages, Value, FDisabledImagesChangeLink); +end; + +procedure TTBCustomImageList.SetHotImages(Value: TCustomImageList); +begin + ChangeImages(FHotImages, Value, FHotImagesChangeLink); +end; + +procedure TTBCustomImageList.SetImagesBitmap(Value: TBitmap); +begin + FImagesBitmap.Assign(Value); +end; + +procedure TTBCustomImageList.SetImagesBitmapMaskColor(Value: TColor); +begin + if FImagesBitmapMaskColor <> Value then begin + FImagesBitmapMaskColor := Value; + ImagesBitmapChanged(nil); + end; +end; + + +{ TTBBaseAccObject } + +{ According to the MSAA docs: + "With Active Accessibility 2.0, servers can return E_NOTIMPL from IDispatch + methods and Active Accessibility will implement the IAccessible interface + for them." + And there was much rejoicing. } + +function TTBBaseAccObject.GetIDsOfNames(const IID: TGUID; Names: Pointer; + NameCount, LocaleID: Integer; DispIDs: Pointer): HResult; +begin + Result := E_NOTIMPL; +end; + +function TTBBaseAccObject.GetTypeInfo(Index, LocaleID: Integer; + out TypeInfo): HResult; +begin + Result := E_NOTIMPL; +end; + +function TTBBaseAccObject.GetTypeInfoCount(out Count: Integer): HResult; +begin + Result := E_NOTIMPL; +end; + +function TTBBaseAccObject.Invoke(DispID: Integer; const IID: TGUID; + LocaleID: Integer; Flags: Word; var Params; VarResult, ExcepInfo, + ArgErr: Pointer): HResult; +begin + Result := E_NOTIMPL; +end; + + +{ Initialization & finalization } + +procedure TBInitToolbarSystemFont; +var + NonClientMetrics: TNonClientMetrics; +begin + NonClientMetrics.cbSize := SizeOf(NonClientMetrics); + if SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, @NonClientMetrics, 0) then + ToolbarFont.Handle := CreateFontIndirect(NonClientMetrics.lfMenuFont); +end; + +initialization + ToolbarFont := TFont.Create; + TBInitToolbarSystemFont; +finalization + DestroyClickWnd; + FreeAndNil(ToolbarFont); +end. diff --git a/official/2.1.6+2.1.beta1/Source/TB2MDI.pas b/official/2.1.6+2.1.beta1/Source/TB2MDI.pas new file mode 100644 index 0000000..143e063 --- /dev/null +++ b/official/2.1.6+2.1.beta1/Source/TB2MDI.pas @@ -0,0 +1,682 @@ +unit TB2MDI; + +{ + Toolbar2000 + Copyright (C) 1998-2005 by Jordan Russell + All rights reserved. + + The contents of this file are subject to the "Toolbar2000 License"; you may + not use or distribute this file except in compliance with the + "Toolbar2000 License". A copy of the "Toolbar2000 License" may be found in + TB2k-LICENSE.txt or at: + http://www.jrsoftware.org/files/tb2k/TB2k-LICENSE.txt + + Alternatively, the contents of this file may be used under the terms of the + GNU General Public License (the "GPL"), in which case the provisions of the + GPL are applicable instead of those in the "Toolbar2000 License". A copy of + the GPL may be found in GPL-LICENSE.txt or at: + http://www.jrsoftware.org/files/tb2k/GPL-LICENSE.txt + If you wish to allow use of your version of this file only under the terms of + the GPL and not to allow others to use your version of this file under the + "Toolbar2000 License", indicate your decision by deleting the provisions + above and replace them with the notice and other provisions required by the + GPL. If you do not delete the provisions above, a recipient may use your + version of this file under either the "Toolbar2000 License" or the GPL. + + $jrsoftware: tb2k/Source/TB2MDI.pas,v 1.13 2005/01/06 03:56:50 jr Exp $ +} + +interface + +{$I TB2Ver.inc} + +uses + Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, + Menus, TB2Item, TB2Toolbar; + +type + TTBMDIButtonsItem = class; + TTBMDISystemMenuItem = class; + + TTBMDIHandler = class(TComponent) + private + FButtonsItem: TTBMDIButtonsItem; + FSystemMenuItem: TTBMDISystemMenuItem; + FToolbar: TTBCustomToolbar; + procedure SetToolbar(Value: TTBCustomToolbar); + protected + procedure Notification(AComponent: TComponent; Operation: TOperation); override; + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + published + property Toolbar: TTBCustomToolbar read FToolbar write SetToolbar; + end; + + TTBMDIWindowItem = class(TTBCustomItem) + private + FForm: TForm; + FOnUpdate: TNotifyEvent; + FWindowMenu: TMenuItem; + procedure ItemClick(Sender: TObject); + procedure SetForm(AForm: TForm); + protected + procedure EnabledChanged; override; + procedure GetChildren(Proc: TGetChildProc; Root: TComponent); override; + procedure Notification(AComponent: TComponent; Operation: TOperation); override; + public + constructor Create(AOwner: TComponent); override; + procedure InitiateAction; override; + published + property Enabled; + property OnUpdate: TNotifyEvent read FOnUpdate write FOnUpdate; + end; + + TTBMDISystemMenuItem = class(TTBCustomItem) + private + FImageList: TImageList; + procedure CommandClick(Sender: TObject); + protected + function GetItemViewerClass(AView: TTBView): TTBItemViewerClass; override; + public + constructor Create(AOwner: TComponent); override; + procedure Click; override; + end; + + TTBMDISystemMenuItemViewer = class(TTBItemViewer) + protected + procedure CalcSize(const Canvas: TCanvas; var AWidth, AHeight: Integer); + override; + procedure Paint(const Canvas: TCanvas; const ClientAreaRect: TRect; + IsSelected, IsPushed, UseDisabledShadow: Boolean); override; + end; + + TTBMDIButtonType = (tbmbMinimize, tbmbRestore, tbmbClose); + + TTBMDIButtonItem = class(TTBCustomItem) + private + FButtonType: TTBMDIButtonType; + protected + function GetItemViewerClass(AView: TTBView): TTBItemViewerClass; override; + public + constructor Create(AOwner: TComponent); override; + end; + + TTBMDIButtonItemViewer = class(TTBItemViewer) + protected + procedure CalcSize(const Canvas: TCanvas; var AWidth, AHeight: Integer); + override; + procedure Paint(const Canvas: TCanvas; const ClientAreaRect: TRect; + IsSelected, IsPushed, UseDisabledShadow: Boolean); override; + end; + + TTBMDISepItem = class(TTBSeparatorItem) + protected + function GetItemViewerClass(AView: TTBView): TTBItemViewerClass; override; + end; + + TTBMDISepItemViewer = class(TTBSeparatorItemViewer) + protected + procedure CalcSize(const Canvas: TCanvas; var AWidth, AHeight: Integer); + override; + end; + + TTBMDIButtonsItem = class(TTBCustomItem) + private + FMinimizeItem: TTBMDIButtonItem; + FRestoreItem: TTBMDIButtonItem; + FCloseItem: TTBMDIButtonItem; + FSep1, FSep2: TTBMDISepItem; + procedure InvalidateSystemMenuItem; + procedure ItemClick(Sender: TObject); + procedure UpdateState(W: HWND; Maximized: Boolean); + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + end; + +implementation + +uses + TB2Common, TB2Consts, CommCtrl; + +type + TTBCustomToolbarAccess = class(TTBCustomToolbar); + + +{ TTBMDIHandler } + +constructor TTBMDIHandler.Create(AOwner: TComponent); +begin + inherited; + FSystemMenuItem := TTBMDISystemMenuItem.Create(Self); + FButtonsItem := TTBMDIButtonsItem.Create(Self); +end; + +destructor TTBMDIHandler.Destroy; +begin + Toolbar := nil; + inherited; +end; + +procedure TTBMDIHandler.Notification(AComponent: TComponent; Operation: TOperation); +begin + inherited; + if (AComponent = FToolbar) and (Operation = opRemove) then + Toolbar := nil; +end; + +procedure TTBMDIHandler.SetToolbar(Value: TTBCustomToolbar); +var + Rebuild: Boolean; +begin + if FToolbar <> Value then begin + if Assigned(FToolbar) then begin + Rebuild := False; + if TTBCustomToolbarAccess(FToolbar).FMDIButtonsItem = FButtonsItem then begin + TTBCustomToolbarAccess(FToolbar).FMDIButtonsItem := nil; + Rebuild := True; + end; + if TTBCustomToolbarAccess(FToolbar).FMDISystemMenuItem = FSystemMenuItem then begin + TTBCustomToolbarAccess(FToolbar).FMDISystemMenuItem := nil; + Rebuild := True; + end; + if Rebuild and Assigned(FToolbar.View) then + FToolbar.View.RecreateAllViewers; + end; + FToolbar := Value; + if Assigned(Value) then begin + Value.FreeNotification(Self); + TTBCustomToolbarAccess(Value).FMDIButtonsItem := FButtonsItem; + TTBCustomToolbarAccess(Value).FMDISystemMenuItem := FSystemMenuItem; + Value.View.RecreateAllViewers; + end; + end; +end; + + +{ TTBMDISystemMenuItem } + +constructor TTBMDISystemMenuItem.Create(AOwner: TComponent); +begin + inherited; + ItemStyle := ItemStyle + [tbisSubMenu, tbisDontSelectFirst] - + [tbisRedrawOnSelChange, tbisRedrawOnMouseOverChange]; + Caption := '&-'; + + {$R TB2MDI.res} + FImageList := TImageList.Create(Self); + FImageList.Handle := ImageList_LoadBitmap(HInstance, 'TB2SYSMENUIMAGES', + 16, 0, clSilver); + SubMenuImages := FImageList; +end; + +function TTBMDISystemMenuItem.GetItemViewerClass(AView: TTBView): TTBItemViewerClass; +begin + Result := TTBMDISystemMenuItemViewer; +end; + +procedure TTBMDISystemMenuItem.Click; +var + I: Integer; + Form: TForm; + M: HMENU; + State, ID: UINT; + Item: TTBCustomItem; + Buf: array[0..1023] of Char; +begin + inherited; + Clear; + if Application.MainForm = nil then + Exit; + Form := Application.MainForm.ActiveMDIChild; + if Form = nil then + Exit; + M := GetSystemMenu(Form.Handle, False); + for I := 0 to GetMenuItemCount(M)-1 do begin + State := GetMenuState(M, I, MF_BYPOSITION); + if State and MF_SEPARATOR <> 0 then + Add(TTBSeparatorItem.Create(Self)) + else begin + Item := TTBCustomItem.Create(Self); + if State and MF_GRAYED <> 0 then + Item.Enabled := False; + if GetMenuString(M, I, Buf, SizeOf(Buf), MF_BYPOSITION) = 0 then + Buf[0] := #0; + Item.Caption := Buf; + ID := GetMenuItemID(M, I); + Item.Tag := ID; + case ID and $FFF0 of + SC_RESTORE: Item.ImageIndex := 3; + SC_MINIMIZE: Item.ImageIndex := 2; + SC_MAXIMIZE: Item.ImageIndex := 1; + SC_CLOSE: begin + Item.ImageIndex := 0; + Item.Options := Item.Options + [tboDefault]; + end; + end; + Item.OnClick := CommandClick; + Add(Item); + end; + end; +end; + +procedure TTBMDISystemMenuItem.CommandClick(Sender: TObject); +var + Form: TForm; +begin + if Assigned(Application.MainForm) then begin + Form := Application.MainForm.ActiveMDIChild; + if Assigned(Form) then + SendMessage(Form.Handle, WM_SYSCOMMAND, TTBCustomItem(Sender).Tag, + GetMessagePos); + end; +end; + + +{ TTBMDISystemMenuItemViewer } + +procedure TTBMDISystemMenuItemViewer.CalcSize(const Canvas: TCanvas; + var AWidth, AHeight: Integer); +begin + AWidth := GetSystemMetrics(SM_CXSMICON) + 2; + AHeight := GetSystemMetrics(SM_CYSMICON) + 2; +end; + +procedure TTBMDISystemMenuItemViewer.Paint(const Canvas: TCanvas; + const ClientAreaRect: TRect; IsSelected, IsPushed, UseDisabledShadow: Boolean); + + function GetIconHandle: HICON; + var + Form: TForm; + begin + Result := 0; + if Assigned(Application.MainForm) then begin + Form := Application.MainForm.ActiveMDIChild; + if Assigned(Form) then + Result := Form.Icon.Handle; + end; + if Result = 0 then + Result := Application.Icon.Handle; + if Result = 0 then + Result := LoadIcon(0, IDI_APPLICATION); + end; + +var + R: TRect; + TempIcon: HICON; +begin + R := ClientAreaRect; + InflateRect(R, -1, -1); + TempIcon := CopyImage(GetIconHandle, IMAGE_ICON, R.Right - R.Left, + R.Bottom - R.Top, LR_COPYFROMRESOURCE); + DrawIconEx(Canvas.Handle, R.Left, R.Top, TempIcon, 0, 0, 0, 0, DI_NORMAL); + DestroyIcon(TempIcon); +end; + + +{ TTBMDIButtonItem } + +constructor TTBMDIButtonItem.Create(AOwner: TComponent); +begin + inherited; + ItemStyle := ItemStyle - [tbisSelectable, tbisRedrawOnSelChange] + + [tbisRightAlign]; +end; + +function TTBMDIButtonItem.GetItemViewerClass(AView: TTBView): TTBItemViewerClass; +begin + Result := TTBMDIButtonItemViewer; +end; + + +{ TTBMDIButtonItemViewer } + +procedure TTBMDIButtonItemViewer.CalcSize(const Canvas: TCanvas; + var AWidth, AHeight: Integer); +begin + if NewStyleControls then begin + AWidth := GetSystemMetrics(SM_CXMENUSIZE) - 2; + if AWidth < 0 then AWidth := 0; + AHeight := GetSystemMetrics(SM_CYMENUSIZE) - 4; + if AHeight < 0 then AHeight := 0; + end + else begin + AWidth := 16; + AHeight := 14; + end; +end; + +procedure TTBMDIButtonItemViewer.Paint(const Canvas: TCanvas; + const ClientAreaRect: TRect; IsSelected, IsPushed, UseDisabledShadow: Boolean); +const + ButtonTypeFlags: array[TTBMDIButtonType] of UINT = (DFCS_CAPTIONMIN, + DFCS_CAPTIONRESTORE, DFCS_CAPTIONCLOSE); + PushedFlags: array[Boolean] of UINT = (0, DFCS_PUSHED); + EnabledFlags: array[Boolean] of UINT = (DFCS_INACTIVE, 0); +begin + DrawFrameControl(Canvas.Handle, ClientAreaRect, DFC_CAPTION, + ButtonTypeFlags[TTBMDIButtonItem(Item).FButtonType] or + PushedFlags[IsPushed] or EnabledFlags[Item.Enabled]); +end; + + +{ TTBMDISepItem } + +function TTBMDISepItem.GetItemViewerClass(AView: TTBView): TTBItemViewerClass; +begin + Result := TTBMDISepItemViewer; +end; + + +{ TTBMDISepItemViewer } + +procedure TTBMDISepItemViewer.CalcSize(const Canvas: TCanvas; + var AWidth, AHeight: Integer); +begin + if View.Orientation <> tbvoVertical then begin + AWidth := 2; + AHeight := 6; + end + else begin + AWidth := 6; + AHeight := 2; + end; +end; + + +{ TTBMDIButtonsItem } + +var + CBTHookHandle: HHOOK; + MDIButtonsItems: TList; + +function WindowIsMDIChild(W: HWND): Boolean; +var + I: Integer; + MainForm, ChildForm: TForm; +begin + MainForm := Application.MainForm; + if Assigned(MainForm) then + for I := 0 to MainForm.MDIChildCount-1 do begin + ChildForm := MainForm.MDIChildren[I]; + if ChildForm.HandleAllocated and (ChildForm.Handle = W) then begin + Result := True; + Exit; + end; + end; + Result := False; +end; + +function CBTHook(Code: Integer; WParam: WPARAM; LParam: LPARAM): LRESULT; +stdcall; +var + Maximizing: Boolean; + WindowPlacement: TWindowPlacement; + I: Integer; +begin + case Code of + HCBT_SETFOCUS: begin + if WindowIsMDIChild(HWND(WParam)) and Assigned(MDIButtonsItems) then begin + for I := 0 to MDIButtonsItems.Count-1 do + TTBMDIButtonsItem(MDIButtonsItems[I]).InvalidateSystemMenuItem; + end; + end; + HCBT_MINMAX: begin + if WindowIsMDIChild(HWND(WParam)) and Assigned(MDIButtonsItems) and + (LParam in [SW_SHOWNORMAL, SW_SHOWMAXIMIZED, SW_MINIMIZE, SW_RESTORE]) then begin + Maximizing := (LParam = SW_MAXIMIZE); + if (LParam = SW_RESTORE) and not IsZoomed(HWND(WParam)) then begin + WindowPlacement.length := SizeOf(WindowPlacement); + GetWindowPlacement(HWND(WParam), @WindowPlacement); + Maximizing := (WindowPlacement.flags and WPF_RESTORETOMAXIMIZED <> 0); + end; + for I := 0 to MDIButtonsItems.Count-1 do + TTBMDIButtonsItem(MDIButtonsItems[I]).UpdateState(HWND(WParam), + Maximizing); + end; + end; + HCBT_DESTROYWND: begin + if WindowIsMDIChild(HWND(WParam)) and Assigned(MDIButtonsItems) then begin + for I := 0 to MDIButtonsItems.Count-1 do + TTBMDIButtonsItem(MDIButtonsItems[I]).UpdateState(HWND(WParam), + False); + end; + end; + end; + Result := CallNextHookEx(CBTHookHandle, Code, WParam, LParam); +end; + +constructor TTBMDIButtonsItem.Create(AOwner: TComponent); + + function CreateItem(const AType: TTBMDIButtonType): TTBMDIButtonItem; + begin + Result := TTBMDIButtonItem.Create(Self); + Result.FButtonType := AType; + Result.OnClick := ItemClick; + end; + +begin + inherited; + ItemStyle := ItemStyle + [tbisEmbeddedGroup]; + FMinimizeItem := CreateItem(tbmbMinimize); + FRestoreItem := CreateItem(tbmbRestore); + FCloseItem := CreateItem(tbmbClose); + FSep1 := TTBMDISepItem.Create(Self); + FSep1.Blank := True; + FSep1.ItemStyle := FSep1.ItemStyle + [tbisRightAlign, tbisNoLineBreak]; + FSep2 := TTBMDISepItem.Create(Self); + FSep2.Blank := True; + FSep2.ItemStyle := FSep2.ItemStyle + [tbisRightAlign, tbisNoLineBreak]; + Add(FSep1); + Add(FMinimizeItem); + Add(FRestoreItem); + Add(FSep2); + Add(FCloseItem); + UpdateState(0, False); + AddToList(MDIButtonsItems, Self); + if CBTHookHandle = 0 then + CBTHookHandle := SetWindowsHookEx(WH_CBT, CBTHook, 0, GetCurrentThreadId); +end; + +destructor TTBMDIButtonsItem.Destroy; +begin + RemoveFromList(MDIButtonsItems, Self); + if (MDIButtonsItems = nil) and (CBTHookHandle <> 0) then begin + UnhookWindowsHookEx(CBTHookHandle); + CBTHookHandle := 0; + end; + inherited; +end; + +procedure TTBMDIButtonsItem.UpdateState(W: HWND; Maximized: Boolean); +var + HasMaxChild, VisibilityChanged: Boolean; + + procedure UpdateVisibleEnabled(const Item: TTBCustomItem; + const AEnabled: Boolean); + begin + if (Item.Visible <> HasMaxChild) or (Item.Enabled <> AEnabled) then begin + Item.Visible := HasMaxChild; + Item.Enabled := AEnabled; + VisibilityChanged := True; + end; + end; + +var + MainForm, ActiveMDIChild, ChildForm: TForm; + I: Integer; +begin + HasMaxChild := False; + MainForm := Application.MainForm; + ActiveMDIChild := nil; + if Assigned(MainForm) then begin + for I := 0 to MainForm.MDIChildCount-1 do begin + ChildForm := MainForm.MDIChildren[I]; + if ChildForm.HandleAllocated and + (((ChildForm.Handle = W) and Maximized) or + ((ChildForm.Handle <> W) and IsZoomed(ChildForm.Handle))) then begin + HasMaxChild := True; + Break; + end; + end; + ActiveMDIChild := MainForm.ActiveMDIChild; + end; + + VisibilityChanged := False; + UpdateVisibleEnabled(TTBMDIHandler(Owner).FSystemMenuItem, True); + UpdateVisibleEnabled(FSep1, True); + UpdateVisibleEnabled(FMinimizeItem, (ActiveMDIChild = nil) or + (GetWindowLong(ActiveMDIChild.Handle, GWL_STYLE) and WS_MINIMIZEBOX <> 0)); + UpdateVisibleEnabled(FRestoreItem, True); + UpdateVisibleEnabled(FSep2, True); + UpdateVisibleEnabled(FCloseItem, True); + + if VisibilityChanged and Assigned((Owner as TTBMDIHandler).FToolbar) then begin + TTBMDIHandler(Owner).FToolbar.View.InvalidatePositions; + TTBMDIHandler(Owner).FToolbar.View.TryValidatePositions; + end; +end; + +procedure TTBMDIButtonsItem.ItemClick(Sender: TObject); +var + MainForm, ChildForm: TForm; + Cmd: WPARAM; +begin + MainForm := Application.MainForm; + if Assigned(MainForm) then begin + ChildForm := MainForm.ActiveMDIChild; + if Assigned(ChildForm) then begin + { Send WM_SYSCOMMAND messages so that we get sounds } + if Sender = FRestoreItem then + Cmd := SC_RESTORE + else if Sender = FCloseItem then + Cmd := SC_CLOSE + else + Cmd := SC_MINIMIZE; + SendMessage(ChildForm.Handle, WM_SYSCOMMAND, Cmd, GetMessagePos); + end; + end; +end; + +procedure TTBMDIButtonsItem.InvalidateSystemMenuItem; +var + View: TTBView; +begin + if Assigned((Owner as TTBMDIHandler).FToolbar) then begin + View := TTBMDIHandler(Owner).FToolbar.View; + View.Invalidate(View.Find(TTBMDIHandler(Owner).FSystemMenuItem)); + end; +end; + + +{ TTBMDIWindowItem } + +constructor TTBMDIWindowItem.Create(AOwner: TComponent); +var + Form: TForm; +begin + inherited; + ItemStyle := ItemStyle + [tbisEmbeddedGroup]; + Caption := STBMDIWindowItemDefCaption; + FWindowMenu := TMenuItem.Create(Self); + + if not(csDesigning in ComponentState) then begin + { Need to set WindowMenu before MDI children are created. Otherwise the + list incorrectly shows the first 9 child windows, even if window 10+ is + active. } + Form := Application.MainForm; + if (Form = nil) and (Screen.FormCount > 0) then + Form := Screen.Forms[0]; + SetForm(Form); + end; +end; + +procedure TTBMDIWindowItem.GetChildren(Proc: TGetChildProc; Root: TComponent); +begin +end; + +procedure TTBMDIWindowItem.Notification(AComponent: TComponent; Operation: TOperation); +begin + inherited; + if (Operation = opRemove) and (AComponent = FForm) then + SetForm(nil); +end; + +procedure TTBMDIWindowItem.SetForm(AForm: TForm); +begin + if FForm <> AForm then begin + if Assigned(FForm) and (FForm.WindowMenu = FWindowMenu) then + FForm.WindowMenu := nil; + FForm := AForm; + if Assigned(FForm) then + FForm.FreeNotification(Self); + end; + if Assigned(FForm) then + FForm.WindowMenu := FWindowMenu; +end; + +procedure TTBMDIWindowItem.EnabledChanged; +var + I: Integer; +begin + inherited; + for I := 0 to Count-1 do + Items[I].Enabled := Enabled; +end; + +procedure TTBMDIWindowItem.InitiateAction; +var + MainForm: TForm; + I: Integer; + M: HMENU; + Item: TTBCustomItem; + ItemCount: Integer; + Buf: array[0..1023] of Char; +begin + inherited; + if csDesigning in ComponentState then + Exit; + MainForm := Application.MainForm; + if Assigned(MainForm) then + SetForm(MainForm); + if FForm = nil then + Exit; + if FForm.ClientHandle <> 0 then + { This is needed, otherwise windows selected on the More Windows dialog + don't move back into the list } + SendMessage(FForm.ClientHandle, WM_MDIREFRESHMENU, 0, 0); + M := FWindowMenu.Handle; + ItemCount := GetMenuItemCount(M) - 1; + if ItemCount < 0 then + ItemCount := 0; + while Count < ItemCount do begin + Item := TTBCustomItem.Create(Self); + Item.Enabled := Enabled; + Item.OnClick := ItemClick; + Add(Item); + end; + while Count > ItemCount do + Items[Count-1].Free; + for I := 0 to ItemCount-1 do begin + Item := Items[I]; + Item.Tag := GetMenuItemID(M, I+1); + if GetMenuString(M, I+1, Buf, SizeOf(Buf), MF_BYPOSITION) = 0 then + Buf[0] := #0; + Item.Caption := Buf; + Item.Checked := GetMenuState(M, I+1, MF_BYPOSITION) and MF_CHECKED <> 0; + end; + if Assigned(FOnUpdate) then + FOnUpdate(Self); +end; + +procedure TTBMDIWindowItem.ItemClick(Sender: TObject); +var + Form: TForm; +begin + Form := Application.MainForm; + if Assigned(Form) then + PostMessage(Form.Handle, WM_COMMAND, TTBCustomItem(Sender).Tag, 0); +end; + +end. diff --git a/official/2.1.6+2.1.beta1/Source/TB2MDI.res b/official/2.1.6+2.1.beta1/Source/TB2MDI.res new file mode 100644 index 0000000..4a62035 Binary files /dev/null and b/official/2.1.6+2.1.beta1/Source/TB2MDI.res differ diff --git a/official/2.1.6+2.1.beta1/Source/TB2MRU.pas b/official/2.1.6+2.1.beta1/Source/TB2MRU.pas new file mode 100644 index 0000000..4ee91c0 --- /dev/null +++ b/official/2.1.6+2.1.beta1/Source/TB2MRU.pas @@ -0,0 +1,403 @@ +unit TB2MRU; + +{ + Toolbar2000 + Copyright (C) 1998-2005 by Jordan Russell + All rights reserved. + + The contents of this file are subject to the "Toolbar2000 License"; you may + not use or distribute this file except in compliance with the + "Toolbar2000 License". A copy of the "Toolbar2000 License" may be found in + TB2k-LICENSE.txt or at: + http://www.jrsoftware.org/files/tb2k/TB2k-LICENSE.txt + + Alternatively, the contents of this file may be used under the terms of the + GNU General Public License (the "GPL"), in which case the provisions of the + GPL are applicable instead of those in the "Toolbar2000 License". A copy of + the GPL may be found in GPL-LICENSE.txt or at: + http://www.jrsoftware.org/files/tb2k/GPL-LICENSE.txt + If you wish to allow use of your version of this file only under the terms of + the GPL and not to allow others to use your version of this file under the + "Toolbar2000 License", indicate your decision by deleting the provisions + above and replace them with the notice and other provisions required by the + GPL. If you do not delete the provisions above, a recipient may use your + version of this file under either the "Toolbar2000 License" or the GPL. + + $jrsoftware: tb2k/Source/TB2MRU.pas,v 1.23 2005/01/06 03:56:50 jr Exp $ +} + +interface + +{$I TB2Ver.inc} + +uses + Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, + TB2Item, IniFiles, Registry; + +type + TTBMRUListClickEvent = procedure(Sender: TObject; const Filename: String) of object; + + TTBMRUList = class(TComponent) + private + FAddFullPath: Boolean; + FContainer: TTBCustomItem; + FHidePathExtension: Boolean; + FList: TStrings; + FMaxItems: Integer; + FOnChange: TNotifyEvent; + FOnClick: TTBMRUListClickEvent; + FPrefix: String; + procedure ClickHandler(Sender: TObject); + procedure SetHidePathExtension(Value: Boolean); + procedure SetList(Value: TStrings); + procedure SetMaxItems(Value: Integer); + protected + property Container: TTBCustomItem read FContainer; + function GetFirstKey: Integer; virtual; + function GetItemClass: TTBCustomItemClass; virtual; + procedure SetItemCaptions; virtual; + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + procedure Add(Filename: String); + procedure Remove(const Filename: String); + procedure LoadFromIni(Ini: TCustomIniFile; const Section: String); + procedure LoadFromRegIni(Ini: TRegIniFile; const Section: String); + procedure SaveToIni(Ini: TCustomIniFile; const Section: String); + procedure SaveToRegIni(Ini: TRegIniFile; const Section: String); + published + { MaxItems must be published before Items } + property AddFullPath: Boolean read FAddFullPath write FAddFullPath default True; + property HidePathExtension: Boolean read FHidePathExtension write SetHidePathExtension default True; + property MaxItems: Integer read FMaxItems write SetMaxItems default 4; + property Items: TStrings read FList write SetList; + property OnClick: TTBMRUListClickEvent read FOnClick write FOnClick; + property OnChange: TNotifyEvent read FOnChange write FOnChange; + property Prefix: String read FPrefix write FPrefix; + end; + + TTBMRUListItem = class(TTBCustomItem) + private + FMRUList: TTBMRUList; + procedure SetMRUList(Value: TTBMRUList); + protected + procedure Notification(AComponent: TComponent; Operation: TOperation); override; + public + constructor Create(AOwner: TComponent); override; + published + property MRUList: TTBMRUList read FMRUList write SetMRUList; + //property Caption; + //property LinkSubitems; + end; + +implementation + +uses + TB2Common, TB2Consts, CommDlg; + +type + TTBMRUListStrings = class(TStrings) + private + FInternalList: TStrings; + FMRUList: TTBMRUList; + procedure Changed; + public + constructor Create; + destructor Destroy; override; + procedure Clear; override; + procedure Delete(Index: Integer); override; + function Get(Index: Integer): String; override; + function GetCount: Integer; override; + function IndexOf(const S: String): Integer; override; + procedure Insert(Index: Integer; const S: String); override; + procedure Move(CurIndex, NewIndex: Integer); override; + procedure Put(Index: Integer; const S: String); override; + end; + + +{ TTBMRUListStrings } + +constructor TTBMRUListStrings.Create; +begin + inherited; + FInternalList := TStringList.Create; +end; + +destructor TTBMRUListStrings.Destroy; +begin + inherited; + FInternalList.Free; +end; + +procedure TTBMRUListStrings.Changed; +begin + if Assigned(FMRUList.FOnChange) and + not(csLoading in FMRUList.ComponentState) then + FMRUList.FOnChange(FMRUList); +end; + +procedure TTBMRUListStrings.Clear; +var + I: Integer; +begin + for I := FInternalList.Count-1 downto 0 do + Delete(I); +end; + +procedure TTBMRUListStrings.Delete(Index: Integer); +begin + FMRUList.FContainer[Index].Free; + FInternalList.Delete(Index); + FMRUList.SetItemCaptions; + Changed; +end; + +function TTBMRUListStrings.Get(Index: Integer): String; +begin + Result := FInternalList[Index]; +end; + +function TTBMRUListStrings.GetCount: Integer; +begin + Result := FInternalList.Count; +end; + +function TTBMRUListStrings.IndexOf(const S: String): Integer; +begin + { This is identical to TStrings.IndexOf except we use AnsiCompareFileName. } + for Result := 0 to GetCount - 1 do + if AnsiCompareFileName(Get(Result), S) = 0 then Exit; + Result := -1; +end; + +procedure TTBMRUListStrings.Insert(Index: Integer; const S: String); +var + Item: TTBCustomItem; +begin + Item := FMRUList.GetItemClass.Create(FMRUList.FContainer); + Item.OnClick := FMRUList.ClickHandler; + FMRUList.FContainer.Insert(Index, Item); + FInternalList.Insert(Index, S); + FMRUList.SetItemCaptions; + Changed; +end; + +procedure TTBMRUListStrings.Move(CurIndex, NewIndex: Integer); +begin + FInternalList.Move(CurIndex, NewIndex); + FMRUList.FContainer.Move(CurIndex, NewIndex); + FMRUList.SetItemCaptions; + Changed; +end; + +procedure TTBMRUListStrings.Put(Index: Integer; const S: String); +begin + FInternalList[Index] := S; + FMRUList.SetItemCaptions; + Changed; +end; + + +{ TTBMRUList } + +constructor TTBMRUList.Create(AOwner: TComponent); +begin + inherited; + FAddFullPath := True; + FHidePathExtension := True; + FMaxItems := 4; + FPrefix := 'MRU'; + FList := TTBMRUListStrings.Create; + TTBMRUListStrings(FList).FMRUList := Self; + FContainer := TTBCustomItem.Create(nil); +end; + +destructor TTBMRUList.Destroy; +begin + FContainer.Free; + FList.Free; + inherited; +end; + +procedure TTBMRUList.Add(Filename: String); +var + I: Integer; +begin + if AddFullPath then + Filename := ExpandFileName(Filename); + { If Filename is already in the MRU list, move it to the top } + I := FList.IndexOf(Filename); + if I <> -1 then begin + if I > 0 then + FList.Move(I, 0); + FList[0] := Filename; { ...in case the capitalization changed } + end + else + FList.Insert(0, Filename); +end; + +procedure TTBMRUList.Remove(const Filename: String); +var + I: Integer; +begin + I := FList.IndexOf(Filename); + if I <> -1 then + FList.Delete(I); +end; + +procedure TTBMRUList.LoadFromIni(Ini: TCustomIniFile; const Section: String); +var + I: Integer; + S: String; +begin + FList.Clear; + for I := 1 to FMaxItems do begin + S := Ini.ReadString(Section, FPrefix + IntToStr(I), ''); + if S <> '' then + FList.Add(S); + end; +end; + +procedure TTBMRUList.LoadFromRegIni(Ini: TRegIniFile; const Section: String); +var + I: Integer; + S: String; +begin + FList.Clear; + for I := 1 to FMaxItems do begin + S := Ini.ReadString(Section, FPrefix + IntToStr(I), ''); + if S <> '' then + FList.Add(S); + end; +end; + +procedure TTBMRUList.SaveToIni(Ini: TCustomIniFile; const Section: String); +var + I: Integer; +begin + for I := 1 to FMaxItems do begin + if I <= FList.Count then + Ini.WriteString(Section, FPrefix + IntToStr(I), FList[I-1]) + else + Ini.DeleteKey(Section, FPrefix + IntToStr(I)); + end; +end; + +procedure TTBMRUList.SaveToRegIni(Ini: TRegIniFile; const Section: String); +var + I: Integer; +begin + for I := 1 to FMaxItems do begin + if I <= FList.Count then + Ini.WriteString(Section, FPrefix + IntToStr(I), FList[I-1]) + else + Ini.DeleteKey(Section, FPrefix + IntToStr(I)); + end; +end; + +procedure TTBMRUList.SetItemCaptions; +var + I, J, N: Integer; + Key: Char; + S: String; + Buf: array[0..MAX_PATH-1] of Char; +begin + while FList.Count > FMaxItems do + FList.Delete(FList.Count-1); + N := GetFirstKey; + for I := 0 to FContainer.Count-1 do begin + Key := #0; + if N < 9 then + Key := Chr(Ord('1') + N) + else begin + { No more numbers; try letters } + J := N - 9; + if J < 26 then + Key := Chr(Ord('A') + J); + end; + S := FList[I]; + if HidePathExtension and (GetFileTitle(PChar(S), Buf, SizeOf(Buf)) = 0) then + S := Buf; + S := EscapeAmpersands(S); + if Key <> #0 then + FContainer[I].Caption := Format('&%s %s', [Key, S]) + else + FContainer[I].Caption := S; + Inc(N); + end; +end; + +procedure TTBMRUList.ClickHandler(Sender: TObject); +var + I: Integer; +begin + I := FContainer.IndexOf(TTBCustomItem(Sender)); + if I <> -1 then begin + if I > 0 then + FList.Move(I, 0); + if Assigned(FOnClick) then + FOnClick(Self, FList[0]); + end; +end; + +procedure TTBMRUList.SetHidePathExtension(Value: Boolean); +begin + if FHidePathExtension <> Value then begin + FHidePathExtension := Value; + SetItemCaptions; + end; +end; + +procedure TTBMRUList.SetList(Value: TStrings); +begin + FList.Assign(Value); +end; + +procedure TTBMRUList.SetMaxItems(Value: Integer); +begin + FMaxItems := Value; + SetItemCaptions; +end; + +function TTBMRUList.GetItemClass: TTBCustomItemClass; +begin + Result := TTBCustomItem; +end; + +function TTBMRUList.GetFirstKey: Integer; +begin + Result := 0; +end; + + +{ TTBMRUListItem } + +constructor TTBMRUListItem.Create(AOwner: TComponent); +begin + inherited; + ItemStyle := ItemStyle + [tbisEmbeddedGroup]; + Caption := STBMRUListItemDefCaption; +end; + +procedure TTBMRUListItem.Notification(AComponent: TComponent; + Operation: TOperation); +begin + inherited; + if (AComponent = FMRUList) and (Operation = opRemove) then + SetMRUList(nil); +end; + +procedure TTBMRUListItem.SetMRUList(Value: TTBMRUList); +begin + if FMRUList <> Value then begin + FMRUList := Value; + if Assigned(FMRUList) then begin + Value.FreeNotification(Self); + LinkSubitems := FMRUList.FContainer; + end + else + LinkSubitems := nil; + end; +end; + +end. diff --git a/official/2.1.6+2.1.beta1/Source/TB2MRU.pas.orig b/official/2.1.6+2.1.beta1/Source/TB2MRU.pas.orig new file mode 100644 index 0000000..fa776d9 --- /dev/null +++ b/official/2.1.6+2.1.beta1/Source/TB2MRU.pas.orig @@ -0,0 +1,395 @@ +unit TB2MRU; + +{ + Toolbar2000 + Copyright (C) 1998-2005 by Jordan Russell + All rights reserved. + + The contents of this file are subject to the "Toolbar2000 License"; you may + not use or distribute this file except in compliance with the + "Toolbar2000 License". A copy of the "Toolbar2000 License" may be found in + TB2k-LICENSE.txt or at: + http://www.jrsoftware.org/files/tb2k/TB2k-LICENSE.txt + + Alternatively, the contents of this file may be used under the terms of the + GNU General Public License (the "GPL"), in which case the provisions of the + GPL are applicable instead of those in the "Toolbar2000 License". A copy of + the GPL may be found in GPL-LICENSE.txt or at: + http://www.jrsoftware.org/files/tb2k/GPL-LICENSE.txt + If you wish to allow use of your version of this file only under the terms of + the GPL and not to allow others to use your version of this file under the + "Toolbar2000 License", indicate your decision by deleting the provisions + above and replace them with the notice and other provisions required by the + GPL. If you do not delete the provisions above, a recipient may use your + version of this file under either the "Toolbar2000 License" or the GPL. + + $jrsoftware: tb2k/Source/TB2MRU.pas,v 1.23 2005/01/06 03:56:50 jr Exp $ +} + +interface + +{$I TB2Ver.inc} + +uses + Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, + TB2Item, IniFiles, Registry; + +type + TTBMRUListClickEvent = procedure(Sender: TObject; const Filename: String) of object; + + TTBMRUList = class(TComponent) + private + FAddFullPath: Boolean; + FContainer: TTBCustomItem; + FHidePathExtension: Boolean; + FList: TStrings; + FMaxItems: Integer; + FOnChange: TNotifyEvent; + FOnClick: TTBMRUListClickEvent; + FPrefix: String; + procedure ClickHandler(Sender: TObject); + procedure SetHidePathExtension(Value: Boolean); + procedure SetList(Value: TStrings); + procedure SetMaxItems(Value: Integer); + protected + property Container: TTBCustomItem read FContainer; + function GetItemClass: TTBCustomItemClass; virtual; + procedure SetItemCaptions; virtual; + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + procedure Add(Filename: String); + procedure Remove(const Filename: String); + procedure LoadFromIni(Ini: TCustomIniFile; const Section: String); + procedure LoadFromRegIni(Ini: TRegIniFile; const Section: String); + procedure SaveToIni(Ini: TCustomIniFile; const Section: String); + procedure SaveToRegIni(Ini: TRegIniFile; const Section: String); + published + { MaxItems must be published before Items } + property AddFullPath: Boolean read FAddFullPath write FAddFullPath default True; + property HidePathExtension: Boolean read FHidePathExtension write SetHidePathExtension default True; + property MaxItems: Integer read FMaxItems write SetMaxItems default 4; + property Items: TStrings read FList write SetList; + property OnClick: TTBMRUListClickEvent read FOnClick write FOnClick; + property OnChange: TNotifyEvent read FOnChange write FOnChange; + property Prefix: String read FPrefix write FPrefix; + end; + + TTBMRUListItem = class(TTBCustomItem) + private + FMRUList: TTBMRUList; + procedure SetMRUList(Value: TTBMRUList); + protected + procedure Notification(AComponent: TComponent; Operation: TOperation); override; + public + constructor Create(AOwner: TComponent); override; + published + property MRUList: TTBMRUList read FMRUList write SetMRUList; + //property Caption; + //property LinkSubitems; + end; + +implementation + +uses + TB2Common, TB2Consts, CommDlg; + +type + TTBMRUListStrings = class(TStrings) + private + FInternalList: TStrings; + FMRUList: TTBMRUList; + procedure Changed; + public + constructor Create; + destructor Destroy; override; + procedure Clear; override; + procedure Delete(Index: Integer); override; + function Get(Index: Integer): String; override; + function GetCount: Integer; override; + function IndexOf(const S: String): Integer; override; + procedure Insert(Index: Integer; const S: String); override; + procedure Move(CurIndex, NewIndex: Integer); override; + procedure Put(Index: Integer; const S: String); override; + end; + + +{ TTBMRUListStrings } + +constructor TTBMRUListStrings.Create; +begin + inherited; + FInternalList := TStringList.Create; +end; + +destructor TTBMRUListStrings.Destroy; +begin + inherited; + FInternalList.Free; +end; + +procedure TTBMRUListStrings.Changed; +begin + if Assigned(FMRUList.FOnChange) and + not(csLoading in FMRUList.ComponentState) then + FMRUList.FOnChange(FMRUList); +end; + +procedure TTBMRUListStrings.Clear; +var + I: Integer; +begin + for I := FInternalList.Count-1 downto 0 do + Delete(I); +end; + +procedure TTBMRUListStrings.Delete(Index: Integer); +begin + FMRUList.FContainer[Index].Free; + FInternalList.Delete(Index); + FMRUList.SetItemCaptions; + Changed; +end; + +function TTBMRUListStrings.Get(Index: Integer): String; +begin + Result := FInternalList[Index]; +end; + +function TTBMRUListStrings.GetCount: Integer; +begin + Result := FInternalList.Count; +end; + +function TTBMRUListStrings.IndexOf(const S: String): Integer; +begin + { This is identical to TStrings.IndexOf except we use AnsiCompareFileName. } + for Result := 0 to GetCount - 1 do + if AnsiCompareFileName(Get(Result), S) = 0 then Exit; + Result := -1; +end; + +procedure TTBMRUListStrings.Insert(Index: Integer; const S: String); +var + Item: TTBCustomItem; +begin + Item := FMRUList.GetItemClass.Create(FMRUList.FContainer); + Item.OnClick := FMRUList.ClickHandler; + FMRUList.FContainer.Insert(Index, Item); + FInternalList.Insert(Index, S); + FMRUList.SetItemCaptions; + Changed; +end; + +procedure TTBMRUListStrings.Move(CurIndex, NewIndex: Integer); +begin + FInternalList.Move(CurIndex, NewIndex); + FMRUList.FContainer.Move(CurIndex, NewIndex); + FMRUList.SetItemCaptions; + Changed; +end; + +procedure TTBMRUListStrings.Put(Index: Integer; const S: String); +begin + FInternalList[Index] := S; + FMRUList.SetItemCaptions; + Changed; +end; + + +{ TTBMRUList } + +constructor TTBMRUList.Create(AOwner: TComponent); +begin + inherited; + FAddFullPath := True; + FHidePathExtension := True; + FMaxItems := 4; + FPrefix := 'MRU'; + FList := TTBMRUListStrings.Create; + TTBMRUListStrings(FList).FMRUList := Self; + FContainer := TTBCustomItem.Create(nil); +end; + +destructor TTBMRUList.Destroy; +begin + FContainer.Free; + FList.Free; + inherited; +end; + +procedure TTBMRUList.Add(Filename: String); +var + I: Integer; +begin + if AddFullPath then + Filename := ExpandFileName(Filename); + { If Filename is already in the MRU list, move it to the top } + I := FList.IndexOf(Filename); + if I <> -1 then begin + if I > 0 then + FList.Move(I, 0); + FList[0] := Filename; { ...in case the capitalization changed } + end + else + FList.Insert(0, Filename); +end; + +procedure TTBMRUList.Remove(const Filename: String); +var + I: Integer; +begin + I := FList.IndexOf(Filename); + if I <> -1 then + FList.Delete(I); +end; + +procedure TTBMRUList.LoadFromIni(Ini: TCustomIniFile; const Section: String); +var + I: Integer; + S: String; +begin + FList.Clear; + for I := 1 to FMaxItems do begin + S := Ini.ReadString(Section, FPrefix + IntToStr(I), ''); + if S <> '' then + FList.Add(S); + end; +end; + +procedure TTBMRUList.LoadFromRegIni(Ini: TRegIniFile; const Section: String); +var + I: Integer; + S: String; +begin + FList.Clear; + for I := 1 to FMaxItems do begin + S := Ini.ReadString(Section, FPrefix + IntToStr(I), ''); + if S <> '' then + FList.Add(S); + end; +end; + +procedure TTBMRUList.SaveToIni(Ini: TCustomIniFile; const Section: String); +var + I: Integer; +begin + for I := 1 to FMaxItems do begin + if I <= FList.Count then + Ini.WriteString(Section, FPrefix + IntToStr(I), FList[I-1]) + else + Ini.DeleteKey(Section, FPrefix + IntToStr(I)); + end; +end; + +procedure TTBMRUList.SaveToRegIni(Ini: TRegIniFile; const Section: String); +var + I: Integer; +begin + for I := 1 to FMaxItems do begin + if I <= FList.Count then + Ini.WriteString(Section, FPrefix + IntToStr(I), FList[I-1]) + else + Ini.DeleteKey(Section, FPrefix + IntToStr(I)); + end; +end; + +procedure TTBMRUList.SetItemCaptions; +var + I, J: Integer; + Key: Char; + S: String; + Buf: array[0..MAX_PATH-1] of Char; +begin + while FList.Count > FMaxItems do + FList.Delete(FList.Count-1); + for I := 0 to FContainer.Count-1 do begin + Key := #0; + if I < 9 then + Key := Chr(Ord('1') + I) + else begin + { No more numbers; try letters } + J := I - 9; + if J < 26 then + Key := Chr(Ord('A') + J); + end; + S := FList[I]; + if HidePathExtension and (GetFileTitle(PChar(S), Buf, SizeOf(Buf)) = 0) then + S := Buf; + S := EscapeAmpersands(S); + if Key <> #0 then + FContainer[I].Caption := Format('&%s %s', [Key, S]) + else + FContainer[I].Caption := S; + end; +end; + +procedure TTBMRUList.ClickHandler(Sender: TObject); +var + I: Integer; +begin + I := FContainer.IndexOf(TTBCustomItem(Sender)); + if I <> -1 then begin + if I > 0 then + FList.Move(I, 0); + if Assigned(FOnClick) then + FOnClick(Self, FList[0]); + end; +end; + +procedure TTBMRUList.SetHidePathExtension(Value: Boolean); +begin + if FHidePathExtension <> Value then begin + FHidePathExtension := Value; + SetItemCaptions; + end; +end; + +procedure TTBMRUList.SetList(Value: TStrings); +begin + FList.Assign(Value); +end; + +procedure TTBMRUList.SetMaxItems(Value: Integer); +begin + FMaxItems := Value; + SetItemCaptions; +end; + +function TTBMRUList.GetItemClass: TTBCustomItemClass; +begin + Result := TTBCustomItem; +end; + + +{ TTBMRUListItem } + +constructor TTBMRUListItem.Create(AOwner: TComponent); +begin + inherited; + ItemStyle := ItemStyle + [tbisEmbeddedGroup]; + Caption := STBMRUListItemDefCaption; +end; + +procedure TTBMRUListItem.Notification(AComponent: TComponent; + Operation: TOperation); +begin + inherited; + if (AComponent = FMRUList) and (Operation = opRemove) then + SetMRUList(nil); +end; + +procedure TTBMRUListItem.SetMRUList(Value: TTBMRUList); +begin + if FMRUList <> Value then begin + FMRUList := Value; + if Assigned(FMRUList) then begin + Value.FreeNotification(Self); + LinkSubitems := FMRUList.FContainer; + end + else + LinkSubitems := nil; + end; +end; + +end. diff --git a/official/2.1.6+2.1.beta1/Source/TB2Reg.dcr b/official/2.1.6+2.1.beta1/Source/TB2Reg.dcr new file mode 100644 index 0000000..0ddba52 Binary files /dev/null and b/official/2.1.6+2.1.beta1/Source/TB2Reg.dcr differ diff --git a/official/2.1.6+2.1.beta1/Source/TB2Reg.pas b/official/2.1.6+2.1.beta1/Source/TB2Reg.pas new file mode 100644 index 0000000..1cdd320 --- /dev/null +++ b/official/2.1.6+2.1.beta1/Source/TB2Reg.pas @@ -0,0 +1,257 @@ +unit TB2Reg; + +{ + Toolbar2000 + Copyright (C) 1998-2005 by Jordan Russell + All rights reserved. + + The contents of this file are subject to the "Toolbar2000 License"; you may + not use or distribute this file except in compliance with the + "Toolbar2000 License". A copy of the "Toolbar2000 License" may be found in + TB2k-LICENSE.txt or at: + http://www.jrsoftware.org/files/tb2k/TB2k-LICENSE.txt + + Alternatively, the contents of this file may be used under the terms of the + GNU General Public License (the "GPL"), in which case the provisions of the + GPL are applicable instead of those in the "Toolbar2000 License". A copy of + the GPL may be found in GPL-LICENSE.txt or at: + http://www.jrsoftware.org/files/tb2k/GPL-LICENSE.txt + If you wish to allow use of your version of this file only under the terms of + the GPL and not to allow others to use your version of this file under the + "Toolbar2000 License", indicate your decision by deleting the provisions + above and replace them with the notice and other provisions required by the + GPL. If you do not delete the provisions above, a recipient may use your + version of this file under either the "Toolbar2000 License" or the GPL. + + $jrsoftware: tb2k/Source/TB2Reg.pas,v 1.28 2005/01/06 03:56:50 jr Exp $ +} + +interface + +{$I TB2Ver.inc} + +uses + Windows, SysUtils, Classes, Graphics, Controls, Dialogs, ActnList, ImgList, + {$IFDEF JR_D6} DesignIntf, DesignEditors, VCLEditors, {$ELSE} DsgnIntf, {$ENDIF} + TB2Toolbar, TB2ToolWindow, TB2Dock, TB2Item, TB2ExtItems, TB2MRU, TB2MDI, + TB2DsgnItemEditor; + +{$IFDEF JR_D5} + +{ TTBImageIndexPropertyEditor } + +{ Unfortunately TComponentImageIndexPropertyEditor seems to be gone in + Delphi 6, so we have to use our own image index property editor class } + +type + TTBImageIndexPropertyEditor = class(TIntegerProperty + {$IFDEF JR_D6} , ICustomPropertyListDrawing {$ENDIF}) + public + function GetAttributes: TPropertyAttributes; override; + procedure GetValues(Proc: TGetStrProc); override; + function GetImageListAt(Index: Integer): TCustomImageList; virtual; + + // ICustomPropertyListDrawing + procedure ListMeasureHeight(const Value: string; ACanvas: TCanvas; + var AHeight: Integer); {$IFNDEF JR_D6} override; {$ENDIF} + procedure ListMeasureWidth(const Value: string; ACanvas: TCanvas; + var AWidth: Integer); {$IFNDEF JR_D6} override; {$ENDIF} + procedure ListDrawValue(const Value: string; ACanvas: TCanvas; + const ARect: TRect; ASelected: Boolean); {$IFNDEF JR_D6} override; {$ENDIF} + end; + +{ TTBItemImageIndexPropertyEditor } + +type + TTBItemImageIndexPropertyEditor = class(TTBImageIndexPropertyEditor) + public + function GetImageListAt (Index: Integer): TCustomImageList; override; + end; + +{$ENDIF} + +procedure Register; + +implementation + +uses + ImgEdit; + +{$IFDEF JR_D5} + +function TTBImageIndexPropertyEditor.GetAttributes: TPropertyAttributes; +begin + Result := [paMultiSelect, paValueList, paRevertable]; +end; + +function TTBImageIndexPropertyEditor.GetImageListAt(Index: Integer): TCustomImageList; +begin + Result := nil; +end; + +procedure TTBImageIndexPropertyEditor.GetValues(Proc: TGetStrProc); +var + ImgList: TCustomImageList; + I: Integer; +begin + ImgList := GetImageListAt(0); + if Assigned(ImgList) then + for I := 0 to ImgList.Count-1 do + Proc(IntToStr(I)); +end; + +procedure TTBImageIndexPropertyEditor.ListDrawValue(const Value: string; + ACanvas: TCanvas; const ARect: TRect; ASelected: Boolean); +var + ImgList: TCustomImageList; + X: Integer; +begin + ImgList := GetImageListAt(0); + ACanvas.FillRect(ARect); + X := ARect.Left + 2; + if Assigned(ImgList) then begin + ImgList.Draw(ACanvas, X, ARect.Top + 2, StrToInt(Value)); + Inc(X, ImgList.Width); + end; + ACanvas.TextOut(X + 3, ARect.Top + 1, Value); +end; + +procedure TTBImageIndexPropertyEditor.ListMeasureHeight(const Value: string; + ACanvas: TCanvas; var AHeight: Integer); +var + ImgList: TCustomImageList; +begin + ImgList := GetImageListAt(0); + AHeight := ACanvas.TextHeight(Value) + 2; + if Assigned(ImgList) and (ImgList.Height + 4 > AHeight) then + AHeight := ImgList.Height + 4; +end; + +procedure TTBImageIndexPropertyEditor.ListMeasureWidth(const Value: string; + ACanvas: TCanvas; var AWidth: Integer); +var + ImgList: TCustomImageList; +begin + ImgList := GetImageListAt(0); + AWidth := ACanvas.TextWidth(Value) + 4; + if Assigned(ImgList) then + Inc(AWidth, ImgList.Width); +end; + +{ TTBItemImageIndexPropertyEditor } + +function TTBItemImageIndexPropertyEditor.GetImageListAt(Index: Integer): TCustomImageList; +var + C: TPersistent; + Item: TTBCustomItem; +begin + Result := nil; + { ? I'm guessing that the Index parameter is a component index (one that + would be passed to the GetComponent function). } + C := GetComponent(Index); + if C is TTBCustomItem then begin + Item := TTBCustomItem(C); + repeat + Result := Item.Images; + if Assigned(Result) then + Break; + Item := Item.Parent; + if Item = nil then + Break; + Result := Item.SubMenuImages; + until Assigned(Result); + end; +end; + +{$ENDIF} + +{ TTBCustomImageListEditor } + +type + TTBCustomImageListEditor = class(TComponentEditor) + public + procedure Edit; override; + procedure ExecuteVerb(Index: Integer); override; + function GetVerb(Index: Integer): String; override; + function GetVerbCount: Integer; override; + end; + + TTBCustomImageListAccess = class(TTBCustomImageList); + +procedure TTBCustomImageListEditor.Edit; +var + ImgList: TTBCustomImageList; +begin + ImgList := Component as TTBCustomImageList; + if not TTBCustomImageListAccess(ImgList).ImagesBitmap.Empty then begin + if MessageDlg('The image list''s ImagesBitmap property has ' + + 'a bitmap assigned. Because of this, any changes you make in the ' + + 'Image List Editor will not be preserved when the form is saved.'#13#10#13#10 + + 'Do you want to open the editor anyway?', mtWarning, + [mbYes, mbNo], 0) <> mrYes then + Exit; + end; + EditImageList(ImgList); +end; + +procedure TTBCustomImageListEditor.ExecuteVerb(Index: Integer); +begin + if Index = 0 then + Edit; +end; + +function TTBCustomImageListEditor.GetVerbCount: Integer; +begin + Result := 1; +end; + +function TTBCustomImageListEditor.GetVerb(Index: Integer): String; +begin + if Index = 0 then + Result := 'ImageList Editor...' + else + Result := ''; +end; + + +procedure Register; +begin + RegisterComponents('Toolbar2000', [TTBDock, TTBToolbar, TTBToolWindow, + TTBPopupMenu, TTBImageList, TTBItemContainer, TTBBackground, TTBMRUList, + TTBMDIHandler]); + {$IFDEF JR_D4} + RegisterActions('', [TTBEditAction], nil); + {$ENDIF} + RegisterNoIcon([TTBItem, TTBGroupItem, TTBSubmenuItem, TTBSeparatorItem, + TTBEditItem, TTBMRUListItem, TTBControlItem, TTBMDIWindowItem, + TTBVisibilityToggleItem]); + RegisterClasses([TTBItem, TTBGroupItem, TTBSubmenuItem, TTBSeparatorItem, + TTBEditItem, TTBMRUListItem, TTBControlItem, TTBMDIWindowItem, + TTBVisibilityToggleItem]); + + RegisterComponentEditor(TTBCustomToolbar, TTBItemsEditor); + RegisterComponentEditor(TTBItemContainer, TTBItemsEditor); + RegisterComponentEditor(TTBPopupMenu, TTBItemsEditor); + RegisterComponentEditor(TTBCustomImageList, TTBCustomImageListEditor); + RegisterPropertyEditor(TypeInfo(TTBRootItem), nil, '', TTBItemsPropertyEditor); + {$IFDEF JR_D5} + RegisterPropertyEditor(TypeInfo(TImageIndex), TTBCustomItem, 'ImageIndex', + TTBItemImageIndexPropertyEditor); + {$ENDIF} + {$IFDEF JR_D6} + { TShortCut properties show up like Integer properties in Delphi 6 + without this... } + RegisterPropertyEditor(TypeInfo(TShortCut), TTBCustomItem, '', + TShortCutProperty); + {$ENDIF} + + { Link in images for the toolbar buttons } + {$R TB2DsgnItemEditor.res} + TBRegisterItemClass(TTBEditItem, 'New &Edit', HInstance); + TBRegisterItemClass(TTBGroupItem, 'New &Group Item', HInstance); + TBRegisterItemClass(TTBMRUListItem, 'New &MRU List Item', HInstance); + TBRegisterItemClass(TTBMDIWindowItem, 'New MDI &Windows List', HInstance); + TBRegisterItemClass(TTBVisibilityToggleItem, 'New &Visibility-Toggle Item', HInstance); +end; + +end. diff --git a/official/2.1.6+2.1.beta1/Source/TB2Reg.pas.orig b/official/2.1.6+2.1.beta1/Source/TB2Reg.pas.orig new file mode 100644 index 0000000..950e5e5 --- /dev/null +++ b/official/2.1.6+2.1.beta1/Source/TB2Reg.pas.orig @@ -0,0 +1,251 @@ +unit TB2Reg; + +{ + Toolbar2000 + Copyright (C) 1998-2005 by Jordan Russell + All rights reserved. + + The contents of this file are subject to the "Toolbar2000 License"; you may + not use or distribute this file except in compliance with the + "Toolbar2000 License". A copy of the "Toolbar2000 License" may be found in + TB2k-LICENSE.txt or at: + http://www.jrsoftware.org/files/tb2k/TB2k-LICENSE.txt + + Alternatively, the contents of this file may be used under the terms of the + GNU General Public License (the "GPL"), in which case the provisions of the + GPL are applicable instead of those in the "Toolbar2000 License". A copy of + the GPL may be found in GPL-LICENSE.txt or at: + http://www.jrsoftware.org/files/tb2k/GPL-LICENSE.txt + If you wish to allow use of your version of this file only under the terms of + the GPL and not to allow others to use your version of this file under the + "Toolbar2000 License", indicate your decision by deleting the provisions + above and replace them with the notice and other provisions required by the + GPL. If you do not delete the provisions above, a recipient may use your + version of this file under either the "Toolbar2000 License" or the GPL. + + $jrsoftware: tb2k/Source/TB2Reg.pas,v 1.28 2005/01/06 03:56:50 jr Exp $ +} + +interface + +{$I TB2Ver.inc} + +uses + Windows, SysUtils, Classes, Graphics, Controls, Dialogs, ActnList, ImgList, + {$IFDEF JR_D6} DesignIntf, DesignEditors, VCLEditors, {$ELSE} DsgnIntf, {$ENDIF} + TB2Toolbar, TB2ToolWindow, TB2Dock, TB2Item, TB2ExtItems, TB2MRU, TB2MDI, + TB2DsgnItemEditor; + +procedure Register; + +implementation + +uses + ImgEdit; + +{$IFDEF JR_D5} + +{ TTBImageIndexPropertyEditor } + +{ Unfortunately TComponentImageIndexPropertyEditor seems to be gone in + Delphi 6, so we have to use our own image index property editor class } + +type + TTBImageIndexPropertyEditor = class(TIntegerProperty + {$IFDEF JR_D6} , ICustomPropertyListDrawing {$ENDIF}) + public + function GetAttributes: TPropertyAttributes; override; + procedure GetValues(Proc: TGetStrProc); override; + function GetImageListAt(Index: Integer): TCustomImageList; virtual; + + // ICustomPropertyListDrawing + procedure ListMeasureHeight(const Value: string; ACanvas: TCanvas; + var AHeight: Integer); {$IFNDEF JR_D6} override; {$ENDIF} + procedure ListMeasureWidth(const Value: string; ACanvas: TCanvas; + var AWidth: Integer); {$IFNDEF JR_D6} override; {$ENDIF} + procedure ListDrawValue(const Value: string; ACanvas: TCanvas; + const ARect: TRect; ASelected: Boolean); {$IFNDEF JR_D6} override; {$ENDIF} + end; + +function TTBImageIndexPropertyEditor.GetAttributes: TPropertyAttributes; +begin + Result := [paMultiSelect, paValueList, paRevertable]; +end; + +function TTBImageIndexPropertyEditor.GetImageListAt(Index: Integer): TCustomImageList; +begin + Result := nil; +end; + +procedure TTBImageIndexPropertyEditor.GetValues(Proc: TGetStrProc); +var + ImgList: TCustomImageList; + I: Integer; +begin + ImgList := GetImageListAt(0); + if Assigned(ImgList) then + for I := 0 to ImgList.Count-1 do + Proc(IntToStr(I)); +end; + +procedure TTBImageIndexPropertyEditor.ListDrawValue(const Value: string; + ACanvas: TCanvas; const ARect: TRect; ASelected: Boolean); +var + ImgList: TCustomImageList; + X: Integer; +begin + ImgList := GetImageListAt(0); + ACanvas.FillRect(ARect); + X := ARect.Left + 2; + if Assigned(ImgList) then begin + ImgList.Draw(ACanvas, X, ARect.Top + 2, StrToInt(Value)); + Inc(X, ImgList.Width); + end; + ACanvas.TextOut(X + 3, ARect.Top + 1, Value); +end; + +procedure TTBImageIndexPropertyEditor.ListMeasureHeight(const Value: string; + ACanvas: TCanvas; var AHeight: Integer); +var + ImgList: TCustomImageList; +begin + ImgList := GetImageListAt(0); + AHeight := ACanvas.TextHeight(Value) + 2; + if Assigned(ImgList) and (ImgList.Height + 4 > AHeight) then + AHeight := ImgList.Height + 4; +end; + +procedure TTBImageIndexPropertyEditor.ListMeasureWidth(const Value: string; + ACanvas: TCanvas; var AWidth: Integer); +var + ImgList: TCustomImageList; +begin + ImgList := GetImageListAt(0); + AWidth := ACanvas.TextWidth(Value) + 4; + if Assigned(ImgList) then + Inc(AWidth, ImgList.Width); +end; + +{ TTBItemImageIndexPropertyEditor } + +type + TTBItemImageIndexPropertyEditor = class(TTBImageIndexPropertyEditor) + protected + function GetImageListAt(Index: Integer): TCustomImageList; override; + end; + +function TTBItemImageIndexPropertyEditor.GetImageListAt(Index: Integer): TCustomImageList; +var + C: TPersistent; + Item: TTBCustomItem; +begin + Result := nil; + { ? I'm guessing that the Index parameter is a component index (one that + would be passed to the GetComponent function). } + C := GetComponent(Index); + if C is TTBCustomItem then begin + Item := TTBCustomItem(C); + repeat + Result := Item.Images; + if Assigned(Result) then + Break; + Item := Item.Parent; + if Item = nil then + Break; + Result := Item.SubMenuImages; + until Assigned(Result); + end; +end; + +{$ENDIF} + +{ TTBCustomImageListEditor } + +type + TTBCustomImageListEditor = class(TComponentEditor) + public + procedure Edit; override; + procedure ExecuteVerb(Index: Integer); override; + function GetVerb(Index: Integer): String; override; + function GetVerbCount: Integer; override; + end; + + TTBCustomImageListAccess = class(TTBCustomImageList); + +procedure TTBCustomImageListEditor.Edit; +var + ImgList: TTBCustomImageList; +begin + ImgList := Component as TTBCustomImageList; + if not TTBCustomImageListAccess(ImgList).ImagesBitmap.Empty then begin + if MessageDlg('The image list''s ImagesBitmap property has ' + + 'a bitmap assigned. Because of this, any changes you make in the ' + + 'Image List Editor will not be preserved when the form is saved.'#13#10#13#10 + + 'Do you want to open the editor anyway?', mtWarning, + [mbYes, mbNo], 0) <> mrYes then + Exit; + end; + EditImageList(ImgList); +end; + +procedure TTBCustomImageListEditor.ExecuteVerb(Index: Integer); +begin + if Index = 0 then + Edit; +end; + +function TTBCustomImageListEditor.GetVerbCount: Integer; +begin + Result := 1; +end; + +function TTBCustomImageListEditor.GetVerb(Index: Integer): String; +begin + if Index = 0 then + Result := 'ImageList Editor...' + else + Result := ''; +end; + + +procedure Register; +begin + RegisterComponents('Toolbar2000', [TTBDock, TTBToolbar, TTBToolWindow, + TTBPopupMenu, TTBImageList, TTBItemContainer, TTBBackground, TTBMRUList, + TTBMDIHandler]); + {$IFDEF JR_D4} + RegisterActions('', [TTBEditAction], nil); + {$ENDIF} + RegisterNoIcon([TTBItem, TTBGroupItem, TTBSubmenuItem, TTBSeparatorItem, + TTBEditItem, TTBMRUListItem, TTBControlItem, TTBMDIWindowItem, + TTBVisibilityToggleItem]); + RegisterClasses([TTBItem, TTBGroupItem, TTBSubmenuItem, TTBSeparatorItem, + TTBEditItem, TTBMRUListItem, TTBControlItem, TTBMDIWindowItem, + TTBVisibilityToggleItem]); + + RegisterComponentEditor(TTBCustomToolbar, TTBItemsEditor); + RegisterComponentEditor(TTBItemContainer, TTBItemsEditor); + RegisterComponentEditor(TTBPopupMenu, TTBItemsEditor); + RegisterComponentEditor(TTBCustomImageList, TTBCustomImageListEditor); + RegisterPropertyEditor(TypeInfo(TTBRootItem), nil, '', TTBItemsPropertyEditor); + {$IFDEF JR_D5} + RegisterPropertyEditor(TypeInfo(TImageIndex), TTBCustomItem, 'ImageIndex', + TTBItemImageIndexPropertyEditor); + {$ENDIF} + {$IFDEF JR_D6} + { TShortCut properties show up like Integer properties in Delphi 6 + without this... } + RegisterPropertyEditor(TypeInfo(TShortCut), TTBCustomItem, '', + TShortCutProperty); + {$ENDIF} + + { Link in images for the toolbar buttons } + {$R TB2DsgnItemEditor.res} + TBRegisterItemClass(TTBEditItem, 'New &Edit', HInstance); + TBRegisterItemClass(TTBGroupItem, 'New &Group Item', HInstance); + TBRegisterItemClass(TTBMRUListItem, 'New &MRU List Item', HInstance); + TBRegisterItemClass(TTBMDIWindowItem, 'New MDI &Windows List', HInstance); + TBRegisterItemClass(TTBVisibilityToggleItem, 'New &Visibility-Toggle Item', HInstance); +end; + +end. diff --git a/official/2.1.6+2.1.beta1/Source/TB2ResCursors.res b/official/2.1.6+2.1.beta1/Source/TB2ResCursors.res new file mode 100644 index 0000000..e09ab15 Binary files /dev/null and b/official/2.1.6+2.1.beta1/Source/TB2ResCursors.res differ diff --git a/official/2.1.6+2.1.beta1/Source/TB2ToolWindow.pas b/official/2.1.6+2.1.beta1/Source/TB2ToolWindow.pas new file mode 100644 index 0000000..b6922c1 --- /dev/null +++ b/official/2.1.6+2.1.beta1/Source/TB2ToolWindow.pas @@ -0,0 +1,268 @@ +unit TB2ToolWindow; + +{ + Toolbar2000 + Copyright (C) 1998-2005 by Jordan Russell + All rights reserved. + + The contents of this file are subject to the "Toolbar2000 License"; you may + not use or distribute this file except in compliance with the + "Toolbar2000 License". A copy of the "Toolbar2000 License" may be found in + TB2k-LICENSE.txt or at: + http://www.jrsoftware.org/files/tb2k/TB2k-LICENSE.txt + + Alternatively, the contents of this file may be used under the terms of the + GNU General Public License (the "GPL"), in which case the provisions of the + GPL are applicable instead of those in the "Toolbar2000 License". A copy of + the GPL may be found in GPL-LICENSE.txt or at: + http://www.jrsoftware.org/files/tb2k/GPL-LICENSE.txt + If you wish to allow use of your version of this file only under the terms of + the GPL and not to allow others to use your version of this file under the + "Toolbar2000 License", indicate your decision by deleting the provisions + above and replace them with the notice and other provisions required by the + GPL. If you do not delete the provisions above, a recipient may use your + version of this file under either the "Toolbar2000 License" or the GPL. + + $jrsoftware: tb2k/Source/TB2ToolWindow.pas,v 1.18 2005/01/06 03:56:50 jr Exp $ +} + +interface + +{$I TB2Ver.inc} + +uses + Windows, Classes, Graphics, Controls, TB2Dock; + +type + { TTBToolWindow } + + TTBToolWindow = class(TTBCustomDockableWindow) + private + FMinClientWidth, FMinClientHeight, FMaxClientWidth, FMaxClientHeight: Integer; + FBarHeight, FBarWidth: Integer; + function CalcSize(ADock: TTBDock): TPoint; + function GetClientAreaWidth: Integer; + procedure SetClientAreaWidth(Value: Integer); + function GetClientAreaHeight: Integer; + procedure SetClientAreaHeight(Value: Integer); + procedure SetClientAreaSize(AWidth, AHeight: Integer); + protected + function DoArrange(CanMoveControls: Boolean; PreviousDockType: TTBDockType; + NewFloating: Boolean; NewDock: TTBDock): TPoint; override; + procedure GetBaseSize(var ASize: TPoint); override; + procedure GetMinMaxSize(var AMinClientWidth, AMinClientHeight, + AMaxClientWidth, AMaxClientHeight: Integer); override; + procedure Paint; override; + procedure SizeChanging(const AWidth, AHeight: Integer); override; + public + constructor Create(AOwner: TComponent); override; + + procedure ReadPositionData(const Data: TTBReadPositionData); override; + procedure WritePositionData(const Data: TTBWritePositionData); override; + published + property ActivateParent; + property Align; + property Anchors; + property BorderStyle; + property Caption; + property Color; + property CloseButton; + property CloseButtonWhenDocked; + property ClientAreaHeight: Integer read GetClientAreaHeight write SetClientAreaHeight; + property ClientAreaWidth: Integer read GetClientAreaWidth write SetClientAreaWidth; + property CurrentDock; + property DefaultDock; + property DockableTo; + property DockMode; + property DockPos; + property DockRow; + property DragHandleStyle; + property FloatingMode; + property Font; + property FullSize; + property HideWhenInactive; + property LastDock; + property MaxClientHeight: Integer read FMaxClientHeight write FMaxClientHeight default 0; + property MaxClientWidth: Integer read FMaxClientWidth write FMaxClientWidth default 0; + property MinClientHeight: Integer read FMinClientHeight write FMinClientHeight default 32; + property MinClientWidth: Integer read FMinClientWidth write FMinClientWidth default 32; + property ParentFont; + property ParentShowHint; + property PopupMenu; + property Resizable; + property ShowCaption; + property ShowHint; + property Stretch; + property SmoothDrag; + property TabOrder; + property UseLastDock; + {}{property Version;} + property Visible; + + property OnClose; + property OnCloseQuery; + {$IFDEF JR_D5} + property OnContextPopup; + {$ENDIF} + property OnDragDrop; + property OnDragOver; + property OnDockChanged; + property OnDockChanging; + property OnDockChangingHidden; + property OnMouseDown; + property OnMouseMove; + property OnMouseUp; + property OnMove; + property OnRecreated; + property OnRecreating; + property OnResize; + property OnVisibleChanged; + end; + +implementation + +const + { Constants for TTBToolWindow-specific registry values. Do not localize! } + rvClientWidth = 'ClientWidth'; + rvClientHeight = 'ClientHeight'; + + +{ TTBToolWindow } + +constructor TTBToolWindow.Create(AOwner: TComponent); +begin + inherited; + FMinClientWidth := 32; + FMinClientHeight := 32; + { Initialize the client size to 32x32 } + SetBounds(Left, Top, 32, 32); +end; + +procedure TTBToolWindow.Paint; +var + R: TRect; +begin + { Draw dotted border in design mode } + if csDesigning in ComponentState then + with Canvas do begin + R := ClientRect; + Pen.Style := psDot; + Pen.Color := clBtnShadow; + Brush.Style := bsClear; + Rectangle(R.Left, R.Top, R.Right, R.Bottom); + Pen.Style := psSolid; + end; +end; + +procedure TTBToolWindow.ReadPositionData(const Data: TTBReadPositionData); +begin + inherited; + { Restore ClientAreaWidth/ClientAreaHeight variables } + if Resizable then + with Data do + SetClientAreaSize(ReadIntProc(Name, rvClientWidth, FBarWidth, ExtraData), + ReadIntProc(Name, rvClientHeight, FBarHeight, ExtraData)); +end; + +procedure TTBToolWindow.WritePositionData(const Data: TTBWritePositionData); +begin + inherited; + { Write values of FBarWidth/FBarHeight } + with Data do begin + WriteIntProc(Name, rvClientWidth, FBarWidth, ExtraData); + WriteIntProc(Name, rvClientHeight, FBarHeight, ExtraData); + end; +end; + +procedure TTBToolWindow.GetMinMaxSize(var AMinClientWidth, AMinClientHeight, + AMaxClientWidth, AMaxClientHeight: Integer); +begin + AMinClientWidth := FMinClientWidth; + AMinClientHeight := FMinClientHeight; + AMaxClientWidth := FMaxClientWidth; + AMaxClientHeight := FMaxClientHeight; +end; + +procedure TTBToolWindow.SizeChanging(const AWidth, AHeight: Integer); +begin + FBarWidth := AWidth; + if Parent <> nil then Dec(FBarWidth, Width - ClientWidth); + FBarHeight := AHeight; + if Parent <> nil then Dec(FBarHeight, Height - ClientHeight); +end; + +function TTBToolWindow.CalcSize(ADock: TTBDock): TPoint; +begin + Result.X := FBarWidth; + Result.Y := FBarHeight; + if Assigned(ADock) then + if FullSize then + begin + { If docked and full size, return the size corresponding to docked size } + if not(ADock.Position in [dpLeft, dpRight]) then + Result.X := ADock.ClientWidth - (Width - ClientWidth) + else + Result.Y := ADock.ClientHeight - (Height - ClientHeight); + end + else if Stretch then + begin + { If docked and stretching, return the minimum size so that the toolbar + can shrink below FBarWidth/FBarHeight } + if not(ADock.Position in [dpLeft, dpRight]) then + Result.X := FMinClientWidth + else + Result.Y := FMinClientHeight; + end; +end; + +procedure TTBToolWindow.GetBaseSize(var ASize: TPoint); +begin + ASize := CalcSize(CurrentDock); +end; + +function TTBToolWindow.DoArrange(CanMoveControls: Boolean; + PreviousDockType: TTBDockType; NewFloating: Boolean; NewDock: TTBDock): TPoint; +begin + Result := CalcSize(NewDock); +end; + +function TTBToolWindow.GetClientAreaWidth: Integer; +begin + if Parent = nil then + Result := Width + else + Result := ClientWidth; +end; + +procedure TTBToolWindow.SetClientAreaWidth(Value: Integer); +begin + SetClientAreaSize(Value, ClientAreaHeight); +end; + +function TTBToolWindow.GetClientAreaHeight: Integer; +begin + if Parent = nil then + Result := Height + else + Result := ClientHeight; +end; + +procedure TTBToolWindow.SetClientAreaHeight(Value: Integer); +begin + SetClientAreaSize(ClientAreaWidth, Value); +end; + +procedure TTBToolWindow.SetClientAreaSize(AWidth, AHeight: Integer); +var + Client: TRect; +begin + if Parent = nil then + SetBounds(Left, Top, AWidth, AHeight) + else begin + Client := GetClientRect; + SetBounds(Left, Top, Width - Client.Right + AWidth, + Height - Client.Bottom + AHeight); + end; +end; + +end. diff --git a/official/2.1.6+2.1.beta1/Source/TB2ToolWindow.pas.orig b/official/2.1.6+2.1.beta1/Source/TB2ToolWindow.pas.orig new file mode 100644 index 0000000..90d5592 --- /dev/null +++ b/official/2.1.6+2.1.beta1/Source/TB2ToolWindow.pas.orig @@ -0,0 +1,258 @@ +unit TB2ToolWindow; + +{ + Toolbar2000 + Copyright (C) 1998-2005 by Jordan Russell + All rights reserved. + + The contents of this file are subject to the "Toolbar2000 License"; you may + not use or distribute this file except in compliance with the + "Toolbar2000 License". A copy of the "Toolbar2000 License" may be found in + TB2k-LICENSE.txt or at: + http://www.jrsoftware.org/files/tb2k/TB2k-LICENSE.txt + + Alternatively, the contents of this file may be used under the terms of the + GNU General Public License (the "GPL"), in which case the provisions of the + GPL are applicable instead of those in the "Toolbar2000 License". A copy of + the GPL may be found in GPL-LICENSE.txt or at: + http://www.jrsoftware.org/files/tb2k/GPL-LICENSE.txt + If you wish to allow use of your version of this file only under the terms of + the GPL and not to allow others to use your version of this file under the + "Toolbar2000 License", indicate your decision by deleting the provisions + above and replace them with the notice and other provisions required by the + GPL. If you do not delete the provisions above, a recipient may use your + version of this file under either the "Toolbar2000 License" or the GPL. + + $jrsoftware: tb2k/Source/TB2ToolWindow.pas,v 1.18 2005/01/06 03:56:50 jr Exp $ +} + +interface + +{$I TB2Ver.inc} + +uses + Windows, Classes, Graphics, Controls, TB2Dock; + +type + { TTBToolWindow } + + TTBToolWindow = class(TTBCustomDockableWindow) + private + FMinClientWidth, FMinClientHeight, FMaxClientWidth, FMaxClientHeight: Integer; + FBarHeight, FBarWidth: Integer; + function CalcSize(ADock: TTBDock): TPoint; + function GetClientAreaWidth: Integer; + procedure SetClientAreaWidth(Value: Integer); + function GetClientAreaHeight: Integer; + procedure SetClientAreaHeight(Value: Integer); + procedure SetClientAreaSize(AWidth, AHeight: Integer); + protected + function DoArrange(CanMoveControls: Boolean; PreviousDockType: TTBDockType; + NewFloating: Boolean; NewDock: TTBDock): TPoint; override; + procedure GetBaseSize(var ASize: TPoint); override; + procedure GetMinMaxSize(var AMinClientWidth, AMinClientHeight, + AMaxClientWidth, AMaxClientHeight: Integer); override; + procedure Paint; override; + procedure SizeChanging(const AWidth, AHeight: Integer); override; + public + constructor Create(AOwner: TComponent); override; + + procedure ReadPositionData(const Data: TTBReadPositionData); override; + procedure WritePositionData(const Data: TTBWritePositionData); override; + published + property ActivateParent; + property Align; + property Anchors; + property BorderStyle; + property Caption; + property Color; + property CloseButton; + property CloseButtonWhenDocked; + property ClientAreaHeight: Integer read GetClientAreaHeight write SetClientAreaHeight; + property ClientAreaWidth: Integer read GetClientAreaWidth write SetClientAreaWidth; + property CurrentDock; + property DefaultDock; + property DockableTo; + property DockMode; + property DockPos; + property DockRow; + property DragHandleStyle; + property FloatingMode; + property Font; + property FullSize; + property HideWhenInactive; + property LastDock; + property MaxClientHeight: Integer read FMaxClientHeight write FMaxClientHeight default 0; + property MaxClientWidth: Integer read FMaxClientWidth write FMaxClientWidth default 0; + property MinClientHeight: Integer read FMinClientHeight write FMinClientHeight default 32; + property MinClientWidth: Integer read FMinClientWidth write FMinClientWidth default 32; + property ParentFont; + property ParentShowHint; + property PopupMenu; + property Resizable; + property ShowCaption; + property ShowHint; + property Stretch; + property SmoothDrag; + property TabOrder; + property UseLastDock; + {}{property Version;} + property Visible; + + property OnClose; + property OnCloseQuery; + {$IFDEF JR_D5} + property OnContextPopup; + {$ENDIF} + property OnDragDrop; + property OnDragOver; + property OnDockChanged; + property OnDockChanging; + property OnDockChangingHidden; + property OnMouseDown; + property OnMouseMove; + property OnMouseUp; + property OnMove; + property OnRecreated; + property OnRecreating; + property OnResize; + property OnVisibleChanged; + end; + +implementation + +const + { Constants for TTBToolWindow-specific registry values. Do not localize! } + rvClientWidth = 'ClientWidth'; + rvClientHeight = 'ClientHeight'; + + +{ TTBToolWindow } + +constructor TTBToolWindow.Create(AOwner: TComponent); +begin + inherited; + FMinClientWidth := 32; + FMinClientHeight := 32; + { Initialize the client size to 32x32 } + SetBounds(Left, Top, 32, 32); +end; + +procedure TTBToolWindow.Paint; +var + R: TRect; +begin + { Draw dotted border in design mode } + if csDesigning in ComponentState then + with Canvas do begin + R := ClientRect; + Pen.Style := psDot; + Pen.Color := clBtnShadow; + Brush.Style := bsClear; + Rectangle(R.Left, R.Top, R.Right, R.Bottom); + Pen.Style := psSolid; + end; +end; + +procedure TTBToolWindow.ReadPositionData(const Data: TTBReadPositionData); +begin + inherited; + { Restore ClientAreaWidth/ClientAreaHeight variables } + if Resizable then + with Data do + SetClientAreaSize(ReadIntProc(Name, rvClientWidth, FBarWidth, ExtraData), + ReadIntProc(Name, rvClientHeight, FBarHeight, ExtraData)); +end; + +procedure TTBToolWindow.WritePositionData(const Data: TTBWritePositionData); +begin + inherited; + { Write values of FBarWidth/FBarHeight } + with Data do begin + WriteIntProc(Name, rvClientWidth, FBarWidth, ExtraData); + WriteIntProc(Name, rvClientHeight, FBarHeight, ExtraData); + end; +end; + +procedure TTBToolWindow.GetMinMaxSize(var AMinClientWidth, AMinClientHeight, + AMaxClientWidth, AMaxClientHeight: Integer); +begin + AMinClientWidth := FMinClientWidth; + AMinClientHeight := FMinClientHeight; + AMaxClientWidth := FMaxClientWidth; + AMaxClientHeight := FMaxClientHeight; +end; + +procedure TTBToolWindow.SizeChanging(const AWidth, AHeight: Integer); +begin + FBarWidth := AWidth; + if Parent <> nil then Dec(FBarWidth, Width - ClientWidth); + FBarHeight := AHeight; + if Parent <> nil then Dec(FBarHeight, Height - ClientHeight); +end; + +function TTBToolWindow.CalcSize(ADock: TTBDock): TPoint; +begin + Result.X := FBarWidth; + Result.Y := FBarHeight; + if Assigned(ADock) and (FullSize or Stretch) then begin + { If docked and stretching, return the minimum size so that the toolbar + can shrink below FBarWidth/FBarHeight } + if not(ADock.Position in [dpLeft, dpRight]) then + Result.X := FMinClientWidth + else + Result.Y := FMinClientHeight; + end; +end; + +procedure TTBToolWindow.GetBaseSize(var ASize: TPoint); +begin + ASize := CalcSize(CurrentDock); +end; + +function TTBToolWindow.DoArrange(CanMoveControls: Boolean; + PreviousDockType: TTBDockType; NewFloating: Boolean; NewDock: TTBDock): TPoint; +begin + Result := CalcSize(NewDock); +end; + +function TTBToolWindow.GetClientAreaWidth: Integer; +begin + if Parent = nil then + Result := Width + else + Result := ClientWidth; +end; + +procedure TTBToolWindow.SetClientAreaWidth(Value: Integer); +begin + SetClientAreaSize(Value, ClientAreaHeight); +end; + +function TTBToolWindow.GetClientAreaHeight: Integer; +begin + if Parent = nil then + Result := Height + else + Result := ClientHeight; +end; + +procedure TTBToolWindow.SetClientAreaHeight(Value: Integer); +begin + SetClientAreaSize(ClientAreaWidth, Value); +end; + +procedure TTBToolWindow.SetClientAreaSize(AWidth, AHeight: Integer); +var + Client: TRect; +begin + if Parent = nil then + SetBounds(Left, Top, AWidth, AHeight) + else begin + Client := GetClientRect; + SetBounds(Left, Top, Width - Client.Right + AWidth, + Height - Client.Bottom + AHeight); + end; +end; + +end. diff --git a/official/2.1.6+2.1.beta1/Source/TB2Toolbar.pas b/official/2.1.6+2.1.beta1/Source/TB2Toolbar.pas new file mode 100644 index 0000000..2e2c010 --- /dev/null +++ b/official/2.1.6+2.1.beta1/Source/TB2Toolbar.pas @@ -0,0 +1,1716 @@ +unit TB2Toolbar; + +{ + Toolbar2000 + Copyright (C) 1998-2005 by Jordan Russell + All rights reserved. + + The contents of this file are subject to the "Toolbar2000 License"; you may + not use or distribute this file except in compliance with the + "Toolbar2000 License". A copy of the "Toolbar2000 License" may be found in + TB2k-LICENSE.txt or at: + http://www.jrsoftware.org/files/tb2k/TB2k-LICENSE.txt + + Alternatively, the contents of this file may be used under the terms of the + GNU General Public License (the "GPL"), in which case the provisions of the + GPL are applicable instead of those in the "Toolbar2000 License". A copy of + the GPL may be found in GPL-LICENSE.txt or at: + http://www.jrsoftware.org/files/tb2k/GPL-LICENSE.txt + If you wish to allow use of your version of this file only under the terms of + the GPL and not to allow others to use your version of this file under the + "Toolbar2000 License", indicate your decision by deleting the provisions + above and replace them with the notice and other provisions required by the + GPL. If you do not delete the provisions above, a recipient may use your + version of this file under either the "Toolbar2000 License" or the GPL. + + $jrsoftware: tb2k/Source/TB2Toolbar.pas,v 1.108 2005/07/30 18:17:20 jr Exp $ +} + +interface + +{$I TB2Ver.inc} + +uses + {$IFDEF JR_D9} Types, {$ENDIF} + Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, ImgList, + Menus, ActnList, + TB2Item, TB2Dock; + +type + TTBCustomToolbar = class; + TTBChevronItem = class; + TTBChevronItemClass = class of TTBChevronItem; + + TTBToolbarViewClass = class of TTBToolbarView; + TTBToolbarView = class(TTBView) + private + FToolbar: TTBCustomToolbar; + protected + procedure AutoSize(AWidth, AHeight: Integer); override; + procedure DoUpdatePositions(var ASize: TPoint); override; + function GetChevronItem: TTBCustomItem; override; + function GetMDIButtonsItem: TTBCustomItem; override; + function GetMDISystemMenuItem: TTBCustomItem; override; + public + constructor Create(AOwner: TComponent); override; + function GetFont: TFont; override; + procedure InvalidatePositions; override; + end; + + TTBChevronPriorityForNewItems = (tbcpHighest, tbcpLowest); + + TTBCustomToolbar = class(TTBCustomDockableWindow, ITBItems) + private + FBaseSize: TPoint; + FChevronItem: TTBChevronItem; + FChevronMoveItems: Boolean; + FChevronPriorityForNewItems: TTBChevronPriorityForNewItems; + FDisableAlignArrange: Integer; + FFloatingWidth: Integer; + FIgnoreMouseLeave: Boolean; + FItem: TTBRootItem; + FLastWrappedLines: Integer; + FMenuBar: Boolean; + FOnShortCut: TShortCutEvent; + FProcessShortCuts: Boolean; + FMainWindowHookInstalled: Boolean; + FShrinkMode: TTBShrinkMode; + FSizeData: Pointer; + FSystemFont: Boolean; + FUpdateActions: Boolean; + + procedure CancelHover; + function CalcChevronOffset(const ADock: TTBDock; + const AOrientation: TTBViewOrientation): Integer; + function CalcWrapOffset(const ADock: TTBDock): Integer; + function CreateWrapper(Index: Integer; Ctl: TControl): TTBControlItem; + function FindWrapper(Ctl: TControl): TTBControlItem; + function GetChevronHint: String; + function GetImages: TCustomImageList; + function GetItems: TTBCustomItem; + function GetLinkSubitems: TTBCustomItem; + function GetOptions: TTBItemOptions; + procedure InstallMainWindowHook; + function IsChevronHintStored: Boolean; + class function MainWindowHook(var Message: TMessage): Boolean; + procedure SetChevronHint(const Value: String); + procedure SetChevronMoveItems(Value: Boolean); + procedure SetChevronPriorityForNewItems(Value: TTBChevronPriorityForNewItems); + procedure SetFloatingWidth(Value: Integer); + procedure SetImages(Value: TCustomImageList); + procedure SetLinkSubitems(Value: TTBCustomItem); + procedure SetMainWindowHook; + procedure SetMenuBar(Value: Boolean); + procedure SetOptions(Value: TTBItemOptions); + procedure SetProcessShortCuts(Value: Boolean); + procedure SetShrinkMode(Value: TTBShrinkMode); + procedure SetSystemFont(Value: Boolean); + procedure UninstallMainWindowHook; + procedure UpdateViewProperties; + + procedure CMColorChanged(var Message: TMessage); message CM_COLORCHANGED; + procedure CMControlChange(var Message: TCMControlChange); message CM_CONTROLCHANGE; + procedure CMControlListChange(var Message: TCMControlListChange); message CM_CONTROLLISTCHANGE; + procedure CMFontChanged(var Message: TMessage); message CM_FONTCHANGED; + procedure CMDialogChar(var Message: TCMDialogChar); message CM_DIALOGCHAR; + procedure CMDialogKey(var Message: TCMDialogKey); message CM_DIALOGKEY; + procedure CMHintShow(var Message: TCMHintShow); message CM_HINTSHOW; + procedure CMMouseLeave(var Message: TMessage); message CM_MOUSELEAVE; + procedure CMShowHintChanged(var Message: TMessage); message CM_SHOWHINTCHANGED; + procedure CMWinIniChange(var Message: TWMSettingChange); message CM_WININICHANGE; + procedure WMCancelMode(var Message: TWMCancelMode); message WM_CANCELMODE; + procedure WMGetObject(var Message: TMessage); message WM_GETOBJECT; + procedure WMMouseLeave(var Message: TMessage); message WM_MOUSELEAVE; + procedure WMNCMouseMove(var Message: TWMNCMouseMove); message WM_NCMOUSEMOVE; + {$IFNDEF JR_D5} + procedure WMRButtonUp(var Message: TWMRButtonUp); message WM_RBUTTONUP; + {$ENDIF} + procedure WMSetCursor(var Message: TWMSetCursor); message WM_SETCURSOR; + procedure WMSysCommand(var Message: TWMSysCommand); message WM_SYSCOMMAND; + protected + FMDIButtonsItem: TTBCustomItem; + FMDISystemMenuItem: TTBCustomItem; + FView: TTBToolbarView; + procedure AlignControls(AControl: TControl; var Rect: TRect); override; + procedure BuildPotentialSizesList(SizesList: TList); dynamic; + procedure ControlExistsAtPos(const P: TPoint; var ControlExists: Boolean); + override; + function DoArrange(CanMoveControls: Boolean; PreviousDockType: TTBDockType; + NewFloating: Boolean; NewDock: TTBDock): TPoint; override; + {$IFDEF JR_D5} + procedure DoContextPopup(MousePos: TPoint; var Handled: Boolean); override; + {$ENDIF} + procedure GetBaseSize(var ASize: TPoint); override; + procedure GetChildren(Proc: TGetChildProc; Root: TComponent); override; + procedure GetMinBarSize(var MinimumSize: TPoint); + procedure GetMinShrinkSize(var AMinimumSize: Integer); override; + function GetShrinkMode: TTBShrinkMode; override; + function GetChevronItemClass: TTBChevronItemClass; dynamic; + function GetItemClass: TTBRootItemClass; dynamic; + function GetViewClass: TTBToolbarViewClass; dynamic; + procedure Loaded; override; + procedure MouseDown(Button: TMouseButton; Shift: TShiftState; + X, Y: Integer); override; + procedure MouseMove(Shift: TShiftState; X, Y: Integer); override; + procedure Paint; override; + procedure ResizeBegin(ASizeHandle: TTBSizeHandle); override; + procedure ResizeTrack(var Rect: TRect; const OrigRect: TRect); override; + procedure ResizeTrackAccept; override; + procedure ResizeEnd; override; + procedure SetChildOrder(Child: TComponent; Order: Integer); override; + + property SystemFont: Boolean read FSystemFont write SetSystemFont default True; + property OnShortCut: TShortCutEvent read FOnShortCut write FOnShortCut; + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + procedure BeginUpdate; + procedure EndUpdate; + procedure CreateWrappersForAllControls; + procedure GetTabOrderList(List: TList); override; + procedure InitiateAction; override; + function IsShortCut(var Message: TWMKey): Boolean; + function KeyboardOpen(Key: Char; RequirePrimaryAccel: Boolean): Boolean; + procedure ReadPositionData(const Data: TTBReadPositionData); override; + procedure WritePositionData(const Data: TTBWritePositionData); override; + + property ChevronHint: String read GetChevronHint write SetChevronHint stored IsChevronHintStored; + property ChevronMoveItems: Boolean read FChevronMoveItems write SetChevronMoveItems default True; + property ChevronPriorityForNewItems: TTBChevronPriorityForNewItems read FChevronPriorityForNewItems + write SetChevronPriorityForNewItems default tbcpHighest; + property FloatingWidth: Integer read FFloatingWidth write SetFloatingWidth default 0; + property Images: TCustomImageList read GetImages write SetImages; + property Items: TTBRootItem read FItem; + property LinkSubitems: TTBCustomItem read GetLinkSubitems write SetLinkSubitems; + property Options: TTBItemOptions read GetOptions write SetOptions default []; + property MenuBar: Boolean read FMenuBar write SetMenuBar default False; + property ProcessShortCuts: Boolean read FProcessShortCuts write SetProcessShortCuts default False; + property ShrinkMode: TTBShrinkMode read FShrinkMode write SetShrinkMode default tbsmChevron; + property UpdateActions: Boolean read FUpdateActions write FUpdateActions default True; + property View: TTBToolbarView read FView; + published + property Hint stored False; { Hint is set dynamically; don't save it } + end; + + TTBToolbar = class(TTBCustomToolbar) + published + property ActivateParent; + property Align; + property Anchors; + property AutoResize; + property BorderStyle; + property Caption; + property ChevronHint; + property ChevronMoveItems; + property ChevronPriorityForNewItems; + property CloseButton; + property CloseButtonWhenDocked; + property Color; + property CurrentDock; + property DefaultDock; + property DockableTo; + property DockMode; + property DockPos; + property DockRow; + property DragHandleStyle; + property FloatingMode; + property FloatingWidth; + property Font; + property FullSize; + property HideWhenInactive; + property Images; + property Items; + property LastDock; + property LinkSubitems; + property MenuBar; + property Options; + property ParentFont; + property ParentShowHint; + property PopupMenu; + property ProcessShortCuts; + property Resizable; + property ShowCaption; + property ShowHint; + property ShrinkMode; + property SmoothDrag; + property Stretch; + property SystemFont; + property TabOrder; + property UpdateActions; + property UseLastDock; + property Visible; + + property OnClose; + property OnCloseQuery; + {$IFDEF JR_D5} + property OnContextPopup; + {$ENDIF} + property OnDragDrop; + property OnDragOver; + property OnMouseDown; + property OnMouseMove; + property OnMouseUp; + property OnMove; + property OnRecreated; + property OnRecreating; + property OnDockChanged; + property OnDockChanging; + property OnDockChangingHidden; + property OnResize; + property OnShortCut; + property OnVisibleChanged; + end; + +{ TTBChevronItem & TTBChevronItemViewer } + + TTBChevronItem = class(TTBCustomItem) + private + FToolbar: TTBCustomToolbar; + function GetDefaultHint: String; + public + constructor Create(AOwner: TComponent); override; + function GetChevronParentView: TTBView; override; + function GetItemViewerClass(AView: TTBView): TTBItemViewerClass; override; + end; + + TTBChevronItemViewer = class(TTBItemViewer) + protected + procedure Paint(const Canvas: TCanvas; const ClientAreaRect: TRect; + IsSelected, IsPushed, UseDisabledShadow: Boolean); override; + end; + +const + tbChevronSize = 12; + + +implementation + +uses + TB2Consts, TB2Common, TB2Hook; + +const + { Constants for TTBCustomToolbar-specific registry values. Do not localize! } + rvFloatRightX = 'FloatRightX'; + DockTypeToOrientation: array[TTBDockType] of TTBViewOrientation = + (tbvoHorizontal, tbvoFloating, tbvoHorizontal, tbvoVertical); + +type + { Used internally by the TCustomToolbar97.Resize* procedures } + PToolbar97SizeData = ^TToolbar97SizeData; + TToolbar97SizeData = record + SizeHandle: TTBSizeHandle; + NewSizes: TList; { List of valid new sizes. Items are casted into TSmallPoints } + OrigLeft, OrigTop, OrigWidth, OrigHeight, NCXDiff: Integer; + CurRightX: Integer; + DisableSensCheck, OpSide: Boolean; + SizeSens: Integer; + end; + + +procedure HookProc(Code: THookProcCode; Wnd: HWND; WParam: WPARAM; + LParam: LPARAM); +var + Msg: PMsg; + MainForm: TForm; +begin + { Work around an annoying Windows or VCL bug. If you close all MDI child + windows, the MDI client window gets the focus, and when it has the focus, + pressing Alt+[char] doesn't send a WM_SYSCOMMAND message to the form for + some reason. It seems silly to have to use a hook for this, but I don't + see a better workaround. + Also, route Alt+- to the main form so that when an MDI child form is + maximized, Alt+- brings up the TB2k MDI system menu instead of the + system's. } + if (Code = hpGetMessage) and (WParam = PM_REMOVE) then begin + Msg := PMsg(LParam); + if (Msg.message = WM_SYSCHAR) and (Msg.hwnd <> 0) then begin + { Note: On Windows NT/2000/XP, even though we install the hook using + SetWindowsHookExW, Msg.wParam may either be an ANSI character or a + Unicode character, due to an apparent bug on these platforms. It is + an ANSI character when the message passes through a separate + SetWindowsHookExA-installed WH_GETMESSAGE hook first, and that hook + calls us via CallNextHookEx. Windows apparently "forgets" to convert + the character from ANSI back to Unicode in this case. + We can't convert the character code because there seems to be no way + to detect whether it is ANSI or Unicode. So we can't really do much + with Msg.wParam, apart from comparing it against character codes that + are the same between ANSI and Unicode, such as '-'. } + MainForm := Application.MainForm; + if Assigned(MainForm) and MainForm.HandleAllocated and (GetCapture = 0) and + ((Msg.hwnd = MainForm.ClientHandle) or + ((Msg.wParam = Ord('-')) and (MainForm.ClientHandle <> 0) and + IsChild(MainForm.ClientHandle, Msg.hwnd))) then begin + { Redirect the message to the main form. + Note: Unfortunately, due to a bug in Windows NT 4.0 (and not + 2000/XP/9x/Me), modifications to the message don't take effect if + another WH_GETMESSAGE hook has been installed above this one. + (The bug is that CallNextHookEx copies lParam^ to a local buffer, but + does not propogate the changes made by the hook back to lParam^ when + it returns.) I don't know of any clean workaround, other than to + ensure other WH_GETMESSAGE hooks are installed *before* + Toolbar2000's. } + Msg.hwnd := MainForm.Handle; + end; + end; + end; +end; + +constructor TTBChevronItem.Create(AOwner: TComponent); +begin + inherited; + FToolbar := AOwner as TTBCustomToolbar; + ItemStyle := ItemStyle + [tbisSubMenu, tbisNoAutoOpen]; + Hint := GetDefaultHint; + Caption := EscapeAmpersands(GetShortHint(Hint)); +end; + +function TTBChevronItem.GetChevronParentView: TTBView; +begin + Result := FToolbar.FView; +end; + +function TTBChevronItem.GetDefaultHint: String; +begin + Result := STBChevronItemMoreButtonsHint; +end; + +function TTBChevronItem.GetItemViewerClass(AView: TTBView): TTBItemViewerClass; +begin + Result := TTBChevronItemViewer; +end; + +procedure TTBChevronItemViewer.Paint(const Canvas: TCanvas; + const ClientAreaRect: TRect; IsSelected, IsPushed, UseDisabledShadow: Boolean); +const + Pattern: array[Boolean, 0..15] of Byte = ( + ($CC, 0, $66, 0, $33, 0, $66, 0, $CC, 0, 0, 0, 0, 0, 0, 0), + ($88, 0, $D8, 0, $70, 0, $20, 0, $88, 0, $D8, 0, $70, 0, $20, 0)); +var + DC: HDC; + R2: TRect; + TempBmp: TBitmap; + + procedure DrawPattern(const Color, Offset: Integer); + begin + SelectObject(DC, GetSysColorBrush(Color)); + BitBlt(DC, R2.Left, R2.Top + Offset, R2.Right - R2.Left, + R2.Bottom - R2.Top, TempBmp.Canvas.Handle, 0, 0, $00E20746 {ROP_DSPDxax}); + end; + +begin + DC := Canvas.Handle; + R2 := ClientAreaRect; + if Item.Enabled then begin + if IsPushed then + DrawEdge(DC, R2, BDR_SUNKENOUTER, BF_RECT) + else if IsSelected and not(csDesigning in Item.ComponentState) then + DrawEdge(DC, R2, BDR_RAISEDINNER, BF_RECT); + end; + + if View.Orientation <> tbvoVertical then begin + R2.Top := 4; + R2.Bottom := R2.Top + 5; + Inc(R2.Left, 2); + R2.Right := R2.Left + 8; + end + else begin + R2.Left := R2.Right - 9; + R2.Right := R2.Left + 5; + Inc(R2.Top, 2); + R2.Bottom := R2.Top + 8; + end; + if IsPushed then + OffsetRect(R2, 1, 1); + TempBmp := TBitmap.Create; + try + TempBmp.Handle := CreateBitmap(8, 8, 1, 1, + @Pattern[View.Orientation = tbvoVertical]); + SetTextColor(DC, clBlack); + SetBkColor(DC, clWhite); + if Item.Enabled then + DrawPattern(COLOR_BTNTEXT, 0) + else begin + DrawPattern(COLOR_BTNHIGHLIGHT, 1); + DrawPattern(COLOR_BTNSHADOW, 0); + end; + finally + TempBmp.Free; + end; +end; + + +{ TTBToolbarView } + +constructor TTBToolbarView.Create(AOwner: TComponent); +begin + FToolbar := AOwner as TTBCustomToolbar; + inherited; +end; + +procedure TTBToolbarView.AutoSize(AWidth, AHeight: Integer); +begin + FToolbar.FBaseSize := BaseSize; + if FToolbar.IsAutoResized then + FToolbar.ChangeSize(AWidth, AHeight); +end; + +procedure TTBToolbarView.DoUpdatePositions(var ASize: TPoint); +begin + { Reset CurrentSize because it probably won't be valid after positions + are recalculated [2001-06-24] } + FToolbar.CurrentSize := 0; + FToolbar.GetMinBarSize(ASize); + { On FullSize toolbars, increase ASize.X/Y to WrapOffset so that + right-aligned items always appear at the right edge even when the toolbar + isn't wrapping } + if FToolbar.FullSize then begin + if (Orientation = tbvoHorizontal) and (ASize.X < WrapOffset) then + ASize.X := WrapOffset + else if (Orientation = tbvoVertical) and (ASize.Y < WrapOffset) then + ASize.Y := WrapOffset; + end; + { Increment FDisableAlignArrange so that we don't recursively arrange when + CalculatePositions moves controls } + Inc(FToolbar.FDisableAlignArrange); + try + inherited; + finally + Dec(FToolbar.FDisableAlignArrange); + end; +end; + +procedure TTBToolbarView.InvalidatePositions; +begin + { Reset CurrentSize because it probably won't be valid after positions + are recalculated [2001-06-04] } + FToolbar.CurrentSize := 0; + inherited; +end; + +function TTBToolbarView.GetFont: TFont; +begin + if not FToolbar.SystemFont then + Result := FToolbar.Font + else + Result := inherited GetFont; +end; + +function TTBToolbarView.GetChevronItem: TTBCustomItem; +begin + Result := FToolbar.FChevronItem; +end; + +function TTBToolbarView.GetMDIButtonsItem: TTBCustomItem; +begin + Result := FToolbar.FMDIButtonsItem; +end; + +function TTBToolbarView.GetMDISystemMenuItem: TTBCustomItem; +begin + Result := FToolbar.FMDISystemMenuItem; +end; + + +{ TTBCustomToolbar } + +type + {}TTBCustomItemAccess = class(TTBCustomItem); + TTBItemViewerAccess = class(TTBItemViewer); + +constructor TTBCustomToolbar.Create(AOwner: TComponent); +begin + inherited; + ControlStyle := ControlStyle + [csAcceptsControls, csActionClient] - + [csCaptureMouse]; + DockableWindowStyles := DockableWindowStyles - [tbdsResizeEightCorner, + tbdsResizeClipCursor]; + FItem := GetItemClass.Create(Self); + FItem.ParentComponent := Self; + FChevronItem := GetChevronItemClass.Create(Self); + FChevronItem.LinkSubitems := FItem; + FChevronMoveItems := True; + FView := GetViewClass.CreateView(Self, nil, FItem, Self, True, False, + not(csDesigning in ComponentState)); + FView.BackgroundColor := clBtnFace; + FUpdateActions := True; + FShrinkMode := tbsmChevron; + FSystemFont := True; + Color := clBtnFace; + SetBounds(Left, Top, 23, 22);{} +end; + +destructor TTBCustomToolbar.Destroy; +begin + { Call Destroying to ensure csDestroying is in ComponentState now. Only + needed for Delphi 4 and earlier since Delphi 5 calls Destroying in + TComponent.BeforeDestruction } + Destroying; + UninstallHookProc(Self, HookProc); + UninstallMainWindowHook; + FreeAndNil(FView); + FreeAndNil(FChevronItem); + FreeAndNil(FItem); + inherited; +end; + +function TTBCustomToolbar.GetItems: TTBCustomItem; +begin + Result := FItem; +end; + +function TTBCustomToolbar.GetItemClass: TTBRootItemClass; +begin + Result := TTBRootItem; +end; + +function TTBCustomToolbar.GetViewClass: TTBToolbarViewClass; +begin + Result := TTBToolbarView; +end; + +function TTBCustomToolbar.GetChevronItemClass: TTBChevronItemClass; +begin + Result := TTBChevronItem; +end; + +procedure TTBCustomToolbar.CreateWrappersForAllControls; +{ Create wrappers for any controls that don't already have them } +var + L: TList; + I, J, C: Integer; +begin + if ControlCount = 0 then + Exit; + L := TList.Create; + try + L.Capacity := ControlCount; + for I := 0 to ControlCount-1 do + L.Add(Controls[I]); + C := FItem.Count-1; + for I := 0 to C do + if FItem[I] is TTBControlItem then begin + J := L.IndexOf(TTBControlItem(FItem[I]).Control); + if J <> -1 then + L[J] := nil; + end; + for I := 0 to L.Count-1 do + if Assigned(L[I]) then + CreateWrapper(FItem.Count, L[I]); + finally + L.Free; + end; +end; + +procedure TTBCustomToolbar.Loaded; +begin + CreateWrappersForAllControls; + inherited; +end; + +procedure TTBCustomToolbar.GetChildren(Proc: TGetChildProc; Root: TComponent); +begin + TTBCustomItemAccess(FItem).GetChildren(Proc, Root); + inherited; +end; + +procedure TTBCustomToolbar.SetChildOrder(Child: TComponent; Order: Integer); +begin + if Child is TTBCustomItem then + TTBCustomItemAccess(FItem).SetChildOrder(Child, Order); +end; + +procedure TTBCustomToolbar.AlignControls(AControl: TControl; var Rect: TRect); +{ VCL calls this whenever any child controls in the toolbar are moved, sized, + inserted, etc., and also when the toolbar is resized. } +begin + if FDisableAlignArrange = 0 then + Arrange; +end; + +procedure TTBCustomToolbar.InitiateAction; +begin + inherited; + {}{ also add this to popupmenu(?) } + { Update visible top-level items } + if FUpdateActions then + FView.InitiateActions; +end; + +procedure TTBCustomToolbar.CMColorChanged(var Message: TMessage); +begin + { Synchronize FView.BackgroundColor with the new color } + if Assigned(FView) then + FView.BackgroundColor := Color; + inherited; +end; + +function TTBCustomToolbar.CreateWrapper(Index: Integer; + Ctl: TControl): TTBControlItem; +var + I: Integer; + S: String; +begin + Result := TTBControlItem.CreateControlItem(Owner, Ctl); + if (csDesigning in ComponentState) and Assigned(Owner) then begin + { Needs a name for compatibility with form inheritance } + I := 1; + while True do begin + S := Format('TBControlItem%d', [I]); + if Owner.FindComponent(S) = nil then + Break; + Inc(I); + end; + Result.Name := S; + end; + FItem.Insert(Index, Result); +end; + +function TTBCustomToolbar.FindWrapper(Ctl: TControl): TTBControlItem; +var + I: Integer; + Item: TTBCustomItem; +begin + Result := nil; + for I := 0 to FItem.Count-1 do begin + Item := FItem[I]; + if (Item is TTBControlItem) and + (TTBControlItem(Item).Control = Ctl) then begin + Result := TTBControlItem(Item); + Break; + end; + end; +end; + +procedure TTBCustomToolbar.CMControlChange(var Message: TCMControlChange); +{ A CM_CONTROLCHANGE handler must be used instead of a CM_CONTROLLISTCHANGE + handler because when a CM_CONTROLLISTCHANGE message is sent it is relayed to + *all* parents. CM_CONTROLCHANGE messages are only sent to the immediate + parent. } +begin + inherited; + { Don't automatically create TTBControlItem wrappers if the component + is loading or being updated to reflect changes in an ancestor form, + because wrappers will be streamed in } + if Message.Inserting and not(csLoading in ComponentState) and + not(csUpdating in ComponentState) and + (FindWrapper(Message.Control) = nil) then + CreateWrapper(FItem.Count, Message.Control); +end; + +procedure TTBCustomToolbar.CMControlListChange(var Message: TCMControlListChange); +{ Don't handle deletions inside CM_CONTROLCHANGE because CM_CONTROLCHANGE is + sent *before* a control begins removing itself from its parent. (It used + to handle both insertions and deletions inside CM_CONTROLCHANGE but this + caused AV's.) } +var + Item: TTBControlItem; +begin + inherited; + if not Message.Inserting and Assigned(FItem) then begin + while True do begin + Item := FindWrapper(Message.Control); + if Item = nil then Break; + { The control is being removed the control, not necessarily destroyed, + so set DontFreeControl to True } + Item.DontFreeControl := True; + Item.Free; + end; + end; +end; + +procedure TTBCustomToolbar.CMHintShow(var Message: TCMHintShow); +{ Since the items on a toolbar aren't "real" controls, it needs a CM_HINTSHOW + handler for their hints to be displayed. } +var + V: TTBItemViewer; +begin + with Message.HintInfo^ do begin + HintStr := ''; + V := FView.ViewerFromPoint(CursorPos); + if Assigned(V) then begin + if not IsRectEmpty(V.BoundsRect) then begin + CursorRect := V.BoundsRect; + HintStr := V.GetHintText; + end; + end; + end; +end; + +procedure TTBCustomToolbar.CMShowHintChanged(var Message: TMessage); +begin + inherited; + if ShowHint then + FView.Style := FView.Style + [vsAlwaysShowHints] + else + FView.Style := FView.Style - [vsAlwaysShowHints]; +end; + +procedure TTBCustomToolbar.WMGetObject(var Message: TMessage); +begin + if not FView.HandleWMGetObject(Message) then + inherited; +end; + +procedure TTBCustomToolbar.WMSetCursor(var Message: TWMSetCursor); +var + P: TPoint; + Cursor: HCURSOR; + R: TRect; +begin + if not(csDesigning in ComponentState) and + (Message.CursorWnd = WindowHandle) and + (Smallint(Message.HitTest) = HTCLIENT) then begin + GetCursorPos(P); + FView.UpdateSelection(@P, True); + if Assigned(FView.Selected) then begin + Cursor := 0; + R := FView.Selected.BoundsRect; + P := ScreenToClient(P); + Dec(P.X, R.Left); + Dec(P.Y, R.Top); + TTBItemViewerAccess(FView.Selected).GetCursor(P, Cursor); + if Cursor <> 0 then begin + SetCursor(Cursor); + Message.Result := 1; + Exit; + end; + end; + end; + inherited; +end; + +procedure TTBCustomToolbar.WMSysCommand(var Message: TWMSysCommand); +var + AnsiKey: Char; +begin + if FMenuBar and Enabled and Showing then + with Message do + if (CmdType and $FFF0 = SC_KEYMENU) and (Key <> VK_SPACE) and + (GetCapture = 0) then begin + if Win32Platform = VER_PLATFORM_WIN32_NT then begin + { On Windows NT 4/2000/XP, Key is a wide character, so we have to + convert it. Pressing Alt+N in a Russian input locale, for example, + results in a Key value of $0442. + This could perhaps be considered a bug in Windows NT since the + character codes in other messages such as WM_SYSCHAR aren't left + in Unicode form. + The conversion isn't done with the system code page, but rather + with the code page of the currently active input locale, like + Windows does when sending WM_(SYS)CHAR messages. } + if WideCharToMultiByte(GetInputLocaleCodePage, 0, @WideChar(Key), 1, + @AnsiKey, 1, nil, nil) <> 1 then + Exit; { shouldn't fail, but if it does, we can't continue } + end + else begin + { On Windows 95/98/Me, Key is not a wide character. } + AnsiKey := Char(Key); + end; + if not KeyboardOpen(AnsiKey, False) then begin + if Key = Ord('-') then Exit; + MessageBeep(0); + end; + Result := 1; + end; +end; + +procedure TTBCustomToolbar.Paint; +var + R: TRect; +begin + { Draw dotted border in design mode on undocked toolbars } + if not Docked and (csDesigning in ComponentState) then + with Canvas do begin + R := ClientRect; + Pen.Style := psDot; + Pen.Color := clBtnShadow; + Brush.Style := bsClear; + Rectangle(R.Left, R.Top, R.Right, R.Bottom); + Pen.Style := psSolid; + end; + FView.DrawSubitems(Canvas); +end; + +procedure TTBCustomToolbar.CMDialogKey(var Message: TCMDialogKey); +begin + if (Message.CharCode = VK_MENU) and FMenuBar then + FView.SetAccelsVisibility(True); + inherited; +end; + +procedure TTBCustomToolbar.CMDialogChar(var Message: TCMDialogChar); +begin + { On toolbars that aren't menu bars, handle CM_DIALOGCHAR instead of + WM_SYSCOMMAND } + if not FMenuBar and Enabled and Showing and (Message.CharCode <> 0) then + if KeyboardOpen(Chr(Message.CharCode), True) then begin + Message.Result := 1; + Exit; + end; + inherited; +end; + +procedure TTBCustomToolbar.CancelHover; +begin + if not MouseCapture then + FView.UpdateSelection(nil, True); +end; + +procedure TTBCustomToolbar.CMMouseLeave(var Message: TMessage); +begin + CancelHover; + inherited; +end; + +{$IFDEF JR_D5} +procedure TTBCustomToolbar.DoContextPopup(MousePos: TPoint; + var Handled: Boolean); +begin + CancelHover; + inherited; +end; +{$ENDIF} + +{$IFNDEF JR_D5} +{ Delphi 4 and earlier don't have a DoContextPopup method; we instead have to + trap WM_RBUTTONUP to determine if a popup menu (might) be displayed } +procedure TTBCustomToolbar.WMRButtonUp(var Message: TWMRButtonUp); +begin + CancelHover; + inherited; +end; +{$ENDIF} + +procedure TTBCustomToolbar.MouseMove(Shift: TShiftState; X, Y: Integer); +var + P: TPoint; + Item: TTBCustomItem; +begin + if not(csDesigning in ComponentState) then begin + P := ClientToScreen(Point(X, Y)); + FView.UpdateSelection(@P, True); + if Assigned(FView.Selected) then begin + Item := FView.Selected.Item; + if not(tboLongHintInMenuOnly in Item.EffectiveOptions) then + Hint := Item.Hint + else + Hint := ''; + + with TTBItemViewerAccess(FView.Find(Item)) do + begin + MouseMove(X - BoundsRect.Left, Y - BoundsRect.Top); + end; + end + else + Hint := ''; + end; + { Call TrackMouseEvent to be sure that we are notified when the mouse leaves + the window. We won't get a CM_MOUSELEAVE message if the mouse moves + directly from the toolbar to another application's window } + CallTrackMouseEvent(Handle, TME_LEAVE); + inherited; +end; + +procedure TTBCustomToolbar.WMCancelMode(var Message: TWMCancelMode); +begin + inherited; + { We can receive a WM_CANCELMODE message during a modal loop if a dialog + pops up. Respond by hiding menus to make it look like the modal loop + has returned, even though it really hasn't yet. + Note: Similar code in TTBModalHandler.WndProc. } + if vsModal in FView.State then + FView.CancelMode; +end; + +procedure TTBCustomToolbar.WMMouseLeave(var Message: TMessage); +begin + { A WM_MOUSELEAVE handler is necessary because the control won't get a + CM_MOUSELEAVE message if the user presses Alt+Space. Also, CM_MOUSELEAVE + messages are also not sent if the application is in a + Application.ProcessMessages loop. } + if not FIgnoreMouseLeave then + CancelHover; + inherited; +end; + +procedure TTBCustomToolbar.WMNCMouseMove(var Message: TWMNCMouseMove); +begin + Hint := ''; + CancelHover; + inherited; +end; + +function TTBCustomToolbar.KeyboardOpen(Key: Char; + RequirePrimaryAccel: Boolean): Boolean; +var + I: TTBItemViewer; + IsOnlyItemWithAccel: Boolean; +begin + I := nil; + FView.SetAccelsVisibility(True); + try + Result := False; + if Key = #0 then begin + I := FView.FirstSelectable; + if I = nil then Exit; + FView.Selected := I; + FView.EnterToolbarLoop([]); + end + else begin + I := FView.NextSelectableWithAccel(nil, Key, RequirePrimaryAccel, + IsOnlyItemWithAccel); + if (I = nil) or not I.Item.Enabled then + Exit; + if IsOnlyItemWithAccel then begin + FView.Selected := I; + FView.EnterToolbarLoop([tbetExecuteSelected]); + end + else if FMenuBar then begin + FView.Selected := I; + FView.EnterToolbarLoop([]); + end + else + Exit; + end; + Result := True; + finally + if Assigned(I) then + FView.SetAccelsVisibility(False); + end; +end; + +procedure TTBCustomToolbar.MouseDown(Button: TMouseButton; Shift: TShiftState; + X, Y: Integer); +var + OldParent: TWinControl; + P: TPoint; + Item: TTBCustomItem; +begin + OldParent := Parent; + inherited; + if Parent <> OldParent then + { if the inherited handler (TTBDockableWindow.MouseDown) changed the Parent + (due to the toolbar moving between docks), nothing else should be done } + Exit; + if not(csDesigning in ComponentState) and (Button = mbLeft) then begin + P := ClientToScreen(Point(X, Y)); + FView.UpdateSelection(@P, True); + if Assigned(FView.Selected) then begin + Item := FView.Selected.Item; + if not(tbisClicksTransparent in TTBCustomItemAccess(Item).ItemStyle) then begin + FIgnoreMouseLeave := True; + try + FView.EnterToolbarLoop([tbetMouseDown]); + finally + FIgnoreMouseLeave := False; + end; + end; + end; + end; +end; + +procedure TTBCustomToolbar.CMFontChanged(var Message: TMessage); +begin + inherited; + if not FSystemFont then + Arrange; +end; + +function TTBCustomToolbar.GetChevronHint: String; +begin + Result := FChevronItem.Hint; +end; + +procedure TTBCustomToolbar.SetChevronHint(const Value: String); +begin + FChevronItem.Hint := Value; + FChevronItem.Caption := EscapeAmpersands(GetShortHint(Value)); +end; + +procedure TTBCustomToolbar.SetChevronMoveItems(Value: Boolean); +begin + if FChevronMoveItems <> Value then begin + FChevronMoveItems := Value; + FView.UsePriorityList := Value and not(csDesigning in ComponentState); + end; +end; + +procedure TTBCustomToolbar.SetChevronPriorityForNewItems(Value: TTBChevronPriorityForNewItems); +begin + FChevronPriorityForNewItems := Value; + FView.NewViewersGetHighestPriority := (Value = tbcpHighest); +end; + +function TTBCustomToolbar.IsChevronHintStored: Boolean; +begin + Result := (FChevronItem.Hint <> FChevronItem.GetDefaultHint); +end; + +function TTBCustomToolbar.GetImages: TCustomImageList; +begin + Result := FItem.SubMenuImages; +end; + +procedure TTBCustomToolbar.SetImages(Value: TCustomImageList); +begin + FItem.SubMenuImages := Value; +end; + +function TTBCustomToolbar.GetLinkSubitems: TTBCustomItem; +begin + Result := FItem.LinkSubitems; +end; + +procedure TTBCustomToolbar.SetLinkSubitems(Value: TTBCustomItem); +begin + FItem.LinkSubitems := Value; +end; + +procedure TTBCustomToolbar.SetMenuBar(Value: Boolean); +begin + if FMenuBar <> Value then begin + FMenuBar := Value; + if Value then begin + ControlStyle := ControlStyle + [csMenuEvents]; + FView.Style := FView.Style + [vsMenuBar, vsUseHiddenAccels]; + end + else begin + ControlStyle := ControlStyle - [csMenuEvents]; + FView.Style := FView.Style - [vsMenuBar, vsUseHiddenAccels]; + end; + if not(csLoading in ComponentState) then begin + FullSize := Value; + if Value then + ShrinkMode := tbsmWrap + else + ShrinkMode := tbsmChevron; + CloseButton := not Value; + ProcessShortCuts := Value; + end; + if Value and not(csDesigning in ComponentState) then + InstallHookProc(Self, HookProc, [hpGetMessage]) + else + UninstallHookProc(Self, HookProc); + SetMainWindowHook; + end; +end; + +function TTBCustomToolbar.GetOptions: TTBItemOptions; +begin + Result := FItem.Options; +end; + +procedure TTBCustomToolbar.SetOptions(Value: TTBItemOptions); +begin + FItem.Options := Value; +end; + +procedure TTBCustomToolbar.SetProcessShortCuts(Value: Boolean); +begin + if FProcessShortCuts <> Value then begin + FProcessShortCuts := Value; + SetMainWindowHook; + end; +end; + +procedure TTBCustomToolbar.SetSystemFont(Value: Boolean); +begin + if FSystemFont <> Value then begin + FSystemFont := Value; + Arrange; + end; +end; + +procedure TTBCustomToolbar.SetShrinkMode(Value: TTBShrinkMode); +begin + if FShrinkMode <> Value then begin + FShrinkMode := Value; + if Docked then + CurrentDock.ArrangeToolbars + else if not Floating then + Arrange; + end; +end; + +procedure TTBCustomToolbar.SetFloatingWidth(Value: Integer); +begin + if FFloatingWidth <> Value then begin + FFloatingWidth := Value; + if Floating then begin + UpdateViewProperties; + Arrange; + end; + end; +end; + +function TTBCustomToolbar.CalcWrapOffset(const ADock: TTBDock): Integer; +begin + if ADock = nil then + Result := FFloatingWidth + else begin + if FShrinkMode = tbsmWrap then begin + if not(ADock.Position in [dpLeft, dpRight]) then + Result := ADock.Width - ADock.NonClientWidth - NonClientWidth + else + Result := ADock.Height - ADock.NonClientHeight - NonClientHeight; + end + else + Result := 0; + end; +end; + +function TTBCustomToolbar.CalcChevronOffset(const ADock: TTBDock; + const AOrientation: TTBViewOrientation): Integer; +begin + if (FShrinkMode = tbsmChevron) and Docked and (ADock = CurrentDock) then begin + Result := CurrentSize; + { Subtract non-client size } + if AOrientation <> tbvoVertical then + Dec(Result, NonClientWidth) + else + Dec(Result, NonClientHeight); + if Result < 0 then + Result := 0; { in case CurrentSize wasn't properly initialized yet } + end + else + Result := 0; +end; + +procedure TTBCustomToolbar.UpdateViewProperties; +var + DT: TTBDockType; +begin + DT := TBGetDockTypeOf(CurrentDock, Floating); + FView.Orientation := DockTypeToOrientation[DT]; + FView.ChevronSize := tbChevronSize; + if Assigned(CurrentDock) or Floating then begin + FView.ChevronOffset := CalcChevronOffset(CurrentDock, FView.Orientation); + FView.WrapOffset := CalcWrapOffset(CurrentDock); + end + else begin + FView.ChevronOffset := 0; + FView.WrapOffset := 0; + { Only enable chevron/wrapping when the width of the toolbar is fixed } + if not AutoResize or ((akLeft in Anchors) and (akRight in Anchors)) then begin + if FShrinkMode = tbsmChevron then + FView.ChevronOffset := Width - NonClientWidth + else if FShrinkMode = tbsmWrap then + FView.WrapOffset := Width - NonClientWidth; + end; + end; +end; + +{}{DOCKING STUFF} + +procedure TTBCustomToolbar.ReadPositionData(const Data: TTBReadPositionData); +begin + inherited; + with Data do + FloatingWidth := ReadIntProc(Name, rvFloatRightX, 0, ExtraData); +end; + +procedure TTBCustomToolbar.WritePositionData(const Data: TTBWritePositionData); +begin + inherited; + with Data do + WriteIntProc(Name, rvFloatRightX, FFloatingWidth, ExtraData); +end; + +procedure TTBCustomToolbar.GetMinBarSize(var MinimumSize: TPoint); +var + WH: Integer; +begin + MinimumSize.X := 0; + MinimumSize.Y := 0; + if Docked then begin + WH := CurrentDock.GetMinRowSize(EffectiveDockRow, Self); + if not(CurrentDock.Position in [dpLeft, dpRight]) then + MinimumSize.Y := WH + else + MinimumSize.X := WH; + end; +end; + +procedure TTBCustomToolbar.GetBaseSize(var ASize: TPoint); +begin + FView.ValidatePositions; + ASize := FBaseSize; +end; + +function TTBCustomToolbar.DoArrange(CanMoveControls: Boolean; + PreviousDockType: TTBDockType; NewFloating: Boolean; NewDock: TTBDock): TPoint; +var + DT: TTBDockType; + O: TTBViewOrientation; + TempBaseSize: TPoint; +begin + //outputdebugstring (pchar(format('%s.DoArrange(%d)', [Name, Ord(CanMoveControls)]))); + if CanMoveControls then begin + UpdateViewProperties; + Result := FView.UpdatePositions; + end + else begin + DT := TBGetDockTypeOf(NewDock, NewFloating); + O := DockTypeToOrientation[DT]; + Result.X := 0; + Result.Y := 0; + FView.CalculatePositions(False, O, CalcWrapOffset(NewDock), + CalcChevronOffset(NewDock, O), tbChevronSize, TempBaseSize, Result, + FLastWrappedLines); + end; +end; + +procedure TTBCustomToolbar.ControlExistsAtPos(const P: TPoint; + var ControlExists: Boolean); +var + P2: TPoint; +begin + inherited; + if not ControlExists and not(csDesigning in ComponentState) then begin + P2 := ClientToScreen(P); + FView.UpdateSelection(@P2, True); + if Assigned(FView.Selected) and + not(tbisClicksTransparent in TTBCustomItemAccess(FView.Selected.Item).ItemStyle) then + ControlExists := True; + end; +end; + +procedure TTBCustomToolbar.BuildPotentialSizesList(SizesList: TList); +var + Margins: TRect; + MinX, SaveWrapX: Integer; + X, PrevWrappedLines: Integer; + S: TPoint; + S2: TSmallPoint; +begin + View.GetMargins(tbvoFloating, Margins); + MinX := Margins.Left + Margins.Right; + SaveWrapX := FFloatingWidth; + try + { Add the widest size to the list } + FFloatingWidth := 0; + S := DoArrange(False, dtNotDocked, True, nil); + SizesList.Add(Pointer(PointToSmallPoint(S))); + { Calculate and add rest of sizes to the list } + PrevWrappedLines := 1; + X := S.X-1; + while X >= MinX do begin + FFloatingWidth := X; + S := DoArrange(False, dtNotDocked, True, nil); + if S.X > X then { if it refuses to go any smaller } + Break + else + if X = S.X then begin + S2 := PointToSmallPoint(S); + if FLastWrappedLines <> PrevWrappedLines then + SizesList.Add(Pointer(S2)) + else + SizesList[SizesList.Count-1] := Pointer(S2); + PrevWrappedLines := FLastWrappedLines; + Dec(X); + end + else + X := S.X; + end; + finally + FFloatingWidth := SaveWrapX; + end; +end; + +function CompareNewSizes(const Item1, Item2, ExtraData: Pointer): Integer; far; +begin + { Sorts in descending order } + if ExtraData = nil then + Result := TSmallPoint(Item2).X - TSmallPoint(Item1).X + else + Result := TSmallPoint(Item2).Y - TSmallPoint(Item1).Y; +end; + +procedure TTBCustomToolbar.ResizeBegin(ASizeHandle: TTBSizeHandle); +const + MaxSizeSens = 12; +var + I, NewSize: Integer; + S, N: TSmallPoint; + P: TPoint; +begin + inherited; + + FSizeData := AllocMem(SizeOf(TToolbar97SizeData)); + + with PToolbar97SizeData(FSizeData)^ do begin + SizeHandle := ASizeHandle; + OrigLeft := Parent.Left; + OrigTop := Parent.Top; + OrigWidth := Parent.Width; + OrigHeight := Parent.Height; + NCXDiff := ClientToScreen(Point(0, 0)).X - OrigLeft; + CurRightX := FFloatingWidth; + DisableSensCheck := False; + OpSide := False; + + NewSizes := TList.Create; + BuildPotentialSizesList(NewSizes); + for I := 0 to NewSizes.Count-1 do begin + P := SmallPointToPoint(TSmallPoint(NewSizes.List[I])); + AddFloatingNCAreaToSize(P); + NewSizes.List[I] := Pointer(PointToSmallPoint(P)); + end; + ListSortEx(NewSizes, CompareNewSizes, + Pointer(Ord(ASizeHandle in [twshTop, twshBottom]))); + + SizeSens := MaxSizeSens; + { Adjust sensitivity if it's too high } + for I := 0 to NewSizes.Count-1 do begin + Pointer(S) := NewSizes[I]; + if (S.X = Width) and (S.Y = Height) then begin + if I > 0 then begin + Pointer(N) := NewSizes[I-1]; + if ASizeHandle in [twshLeft, twshRight] then + NewSize := N.X - S.X - 1 + else + NewSize := N.Y - S.Y - 1; + if NewSize < SizeSens then SizeSens := NewSize; + end; + if I < NewSizes.Count-1 then begin + Pointer(N) := NewSizes[I+1]; + if ASizeHandle in [twshLeft, twshRight] then + NewSize := S.X - N.X - 1 + else + NewSize := S.Y - N.Y - 1; + if NewSize < SizeSens then SizeSens := NewSize; + end; + Break; + end; + end; + if SizeSens < 0 then SizeSens := 0; + end; +end; + +procedure TTBCustomToolbar.ResizeTrack(var Rect: TRect; const OrigRect: TRect); +var + Pos: TPoint; + NewOpSide: Boolean; + Reverse: Boolean; + I: Integer; + P: TSmallPoint; +begin + inherited; + + with PToolbar97SizeData(FSizeData)^ do begin + GetCursorPos(Pos); + + Dec(Pos.X, OrigLeft); Dec(Pos.Y, OrigTop); + if SizeHandle = twshLeft then + Pos.X := OrigWidth-Pos.X + else + if SizeHandle = twshTop then + Pos.Y := OrigHeight-Pos.Y; + + { Adjust Pos to make up for the "sizing sensitivity", as seen in Office 97 } + if SizeHandle in [twshLeft, twshRight] then + NewOpSide := Pos.X < OrigWidth + else + NewOpSide := Pos.Y < OrigHeight; + if (not DisableSensCheck) or (OpSide <> NewOpSide) then begin + DisableSensCheck := False; + OpSide := NewOpSide; + if SizeHandle in [twshLeft, twshRight] then begin + if (Pos.X >= OrigWidth-SizeSens) and (Pos.X < OrigWidth+SizeSens) then + Pos.X := OrigWidth; + end + else begin + if (Pos.Y >= OrigHeight-SizeSens) and (Pos.Y < OrigHeight+SizeSens) then + Pos.Y := OrigHeight; + end; + end; + + Rect := OrigRect; + + if SizeHandle in [twshLeft, twshRight] then + Reverse := Pos.X > OrigWidth + else + Reverse := Pos.Y > OrigHeight; + if not Reverse then + I := NewSizes.Count-1 + else + I := 0; + while True do begin + if (not Reverse and (I < 0)) or + (Reverse and (I >= NewSizes.Count)) then + Break; + Pointer(P) := NewSizes[I]; + if SizeHandle in [twshLeft, twshRight] then begin + if (not Reverse and ((I = NewSizes.Count-1) or (Pos.X >= P.X))) or + (Reverse and ((I = 0) or (Pos.X < P.X))) then begin + if I = 0 then + CurRightX := 0 + else + CurRightX := P.X - NCXDiff*2; + if SizeHandle = twshRight then + Rect.Right := Rect.Left + P.X + else + Rect.Left := Rect.Right - P.X; + Rect.Bottom := Rect.Top + P.Y; + DisableSensCheck := not EqualRect(Rect, OrigRect); + end; + end + else begin + if (not Reverse and ((I = NewSizes.Count-1) or (Pos.Y >= P.Y))) or + (Reverse and ((I = 0) or (Pos.Y < P.Y))) then begin + if I = NewSizes.Count-1 then + CurRightX := 0 + else + CurRightX := P.X - NCXDiff*2; + if SizeHandle = twshBottom then + Rect.Bottom := Rect.Top + P.Y + else + Rect.Top := Rect.Bottom - P.Y; + Rect.Right := Rect.Left + P.X; + DisableSensCheck := not EqualRect(Rect, OrigRect); + end; + end; + if not Reverse then + Dec(I) + else + Inc(I); + end; + end; +end; + +procedure TTBCustomToolbar.ResizeTrackAccept; +begin + inherited; + FloatingWidth := PToolbar97SizeData(FSizeData)^.CurRightX; +end; + +procedure TTBCustomToolbar.ResizeEnd; +begin + inherited; + if Assigned(FSizeData) then begin + PToolbar97SizeData(FSizeData)^.NewSizes.Free; + FreeMem(FSizeData); + FSizeData := nil; + end; +end; + +function TTBCustomToolbar.GetShrinkMode: TTBShrinkMode; +begin + Result := FShrinkMode; +end; + +procedure TTBCustomToolbar.GetMinShrinkSize(var AMinimumSize: Integer); +var + I: TTBItemViewer; +begin + I := FView.HighestPriorityViewer; + if Assigned(I) then begin + if not(CurrentDock.Position in [dpLeft, dpRight]) then + AMinimumSize := I.BoundsRect.Right - I.BoundsRect.Left + else + AMinimumSize := I.BoundsRect.Bottom - I.BoundsRect.Top; + end; + if not(CurrentDock.Position in [dpLeft, dpRight]) then + Inc(AMinimumSize, NonClientWidth) + else + Inc(AMinimumSize, NonClientHeight); + Inc(AMinimumSize, tbChevronSize); +end; + +procedure TTBCustomToolbar.BeginUpdate; +begin + FView.BeginUpdate; +end; + +procedure TTBCustomToolbar.EndUpdate; +begin + FView.EndUpdate; +end; + +procedure TTBCustomToolbar.GetTabOrderList(List: TList); +var + CtlList: TList; + I, J: Integer; + CtlI, CtlJ: TWinControl; +begin + inherited; + { Remove off-edge items and their children from List } + CtlList := TList.Create; + try + FView.GetOffEdgeControlList(CtlList); + for I := 0 to CtlList.Count-1 do begin + CtlI := CtlList[I]; + J := 0; + while J < List.Count do begin + CtlJ := List[J]; + if (CtlJ = CtlI) or CtlI.ContainsControl(CtlJ) then + List.Delete(J) + else + Inc(J); + end; + end; + finally + CtlList.Free; + end; +end; + +procedure TTBCustomToolbar.CMWinIniChange(var Message: TWMSettingChange); +begin + inherited; + if Message.Flag = SPI_SETNONCLIENTMETRICS then begin + TBInitToolbarSystemFont; + Arrange; + end; +end; + +function TTBCustomToolbar.IsShortCut(var Message: TWMKey): Boolean; +begin + Result := False; + if Assigned(FOnShortCut) then + FOnShortCut(Message, Result); + Result := Result or FItem.IsShortCut(Message); +end; + +var + HookCount: Integer; + HookList: TList; + +class function TTBCustomToolbar.MainWindowHook(var Message: TMessage): Boolean; + + function GetActiveForm: TCustomForm; + var + Wnd: HWND; + Ctl: TWinControl; + begin + { Note: We don't use Screen.ActiveCustomForm because when an EXE calls a + DLL that shows a modal form, Screen.ActiveCustomForm doesn't change in + the EXE; it remains set to the last form that was active in the EXE. + Use FindControl(GetActiveWindow) instead to avoid this problem; it will + return nil when a form in another module is active. } + Result := nil; + Wnd := GetActiveWindow; + if Wnd <> 0 then begin + Ctl := FindControl(Wnd); + if Assigned(Ctl) and (Ctl is TCustomForm) then + Result := TCustomForm(Ctl); + end; + end; + + function HandleShortCutOnForm(const Form: TCustomForm): Boolean; + var + I: Integer; + Toolbar: TTBCustomToolbar; + begin + Result := False; + if Form = nil then + Exit; + for I := 0 to HookList.Count-1 do begin + Toolbar := HookList[I]; + if Toolbar.ProcessShortCuts and + (TBGetToolWindowParentForm(Toolbar) = Form) and + IsWindowEnabled(Form.Handle) and + Toolbar.IsShortCut(TWMKey(Message)) then begin + Message.Result := 1; + Result := True; + Exit; + end; + end; + end; + + function TraverseControls(Container: TWinControl): Boolean; + var + I: Integer; + Control: TControl; + begin + Result := False; + if Container.Showing then + for I := 0 to Container.ControlCount - 1 do begin + Control := Container.Controls[I]; + if Control.Visible and Control.Enabled then begin + if (csMenuEvents in Control.ControlStyle) and + ((Control is TTBDock) or (Control is TTBCustomToolbar)) and + (Control.Perform(WM_SYSCOMMAND, TMessage(Message).WParam, + TMessage(Message).LParam) <> 0) or (Control is TWinControl) and + TraverseControls(TWinControl(Control)) then begin + Result := True; + Exit; + end; + end; + end; + end; + +var + ActiveForm: TCustomForm; + ActiveMDIChild: TForm; +begin + Result := False; + if (Message.Msg = CM_APPKEYDOWN) and Assigned(HookList) then begin + { Process shortcuts on toolbars. Search forms in this order: + 1. If the active form is an MDI parent form, the active MDI child form + if it has the focus. + 2. The active form. + 3. The main form. } + ActiveForm := GetActiveForm; + if Assigned(ActiveForm) and (ActiveForm is TForm) and + (TForm(ActiveForm).FormStyle = fsMDIForm) then begin + ActiveMDIChild := TForm(ActiveForm).ActiveMDIChild; + { Don't search the child form if a control on the MDI parent form is + currently focused (i.e. Screen.ActiveCustomForm <> ActiveMDIChild) } + if Assigned(ActiveMDIChild) and + (Screen.ActiveCustomForm = ActiveMDIChild) and + HandleShortCutOnForm(ActiveMDIChild) then begin + Result := True; + Exit; + end; + end; + if HandleShortCutOnForm(ActiveForm) then + Result := True + else begin + if (Application.MainForm <> ActiveForm) and + HandleShortCutOnForm(Application.MainForm) then + Result := True; + end; + end + else if Message.Msg = CM_APPSYSCOMMAND then begin + { Handle "Alt or Alt+[key] pressed on secondary form" case. If there's a + menu bar on the active form we want the keypress to go to it instead of + to the main form (the VCL's default handling). } + ActiveForm := GetActiveForm; + if Assigned(ActiveForm) and IsWindowEnabled(ActiveForm.Handle) and + IsWindowVisible(ActiveForm.Handle) and TraverseControls(ActiveForm) then begin + Message.Result := 1; + Result := True; + end; + end; +end; + +procedure TTBCustomToolbar.SetMainWindowHook; +begin + if (ProcessShortCuts or MenuBar) and not(csDesigning in ComponentState) then + InstallMainWindowHook + else + UninstallMainWindowHook; +end; + +procedure TTBCustomToolbar.InstallMainWindowHook; +begin + if FMainWindowHookInstalled then + Exit; + if HookCount = 0 then + Application.HookMainWindow(MainWindowHook); + Inc(HookCount); + AddToList(HookList, Self); + FMainWindowHookInstalled := True; +end; + +procedure TTBCustomToolbar.UninstallMainWindowHook; +begin + if not FMainWindowHookInstalled then + Exit; + FMainWindowHookInstalled := False; + RemoveFromList(HookList, Self); + Dec(HookCount); + if HookCount = 0 then + Application.UnhookMainWindow(MainWindowHook); +end; + +end. diff --git a/official/2.1.6+2.1.beta1/Source/TB2Toolbar.pas.orig b/official/2.1.6+2.1.beta1/Source/TB2Toolbar.pas.orig new file mode 100644 index 0000000..98c3a44 --- /dev/null +++ b/official/2.1.6+2.1.beta1/Source/TB2Toolbar.pas.orig @@ -0,0 +1,1711 @@ +unit TB2Toolbar; + +{ + Toolbar2000 + Copyright (C) 1998-2005 by Jordan Russell + All rights reserved. + + The contents of this file are subject to the "Toolbar2000 License"; you may + not use or distribute this file except in compliance with the + "Toolbar2000 License". A copy of the "Toolbar2000 License" may be found in + TB2k-LICENSE.txt or at: + http://www.jrsoftware.org/files/tb2k/TB2k-LICENSE.txt + + Alternatively, the contents of this file may be used under the terms of the + GNU General Public License (the "GPL"), in which case the provisions of the + GPL are applicable instead of those in the "Toolbar2000 License". A copy of + the GPL may be found in GPL-LICENSE.txt or at: + http://www.jrsoftware.org/files/tb2k/GPL-LICENSE.txt + If you wish to allow use of your version of this file only under the terms of + the GPL and not to allow others to use your version of this file under the + "Toolbar2000 License", indicate your decision by deleting the provisions + above and replace them with the notice and other provisions required by the + GPL. If you do not delete the provisions above, a recipient may use your + version of this file under either the "Toolbar2000 License" or the GPL. + + $jrsoftware: tb2k/Source/TB2Toolbar.pas,v 1.108 2005/07/30 18:17:20 jr Exp $ +} + +interface + +{$I TB2Ver.inc} + +uses + {$IFDEF JR_D9} Types, {$ENDIF} + Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, ImgList, + Menus, ActnList, + TB2Item, TB2Dock; + +type + TTBCustomToolbar = class; + TTBChevronItem = class; + TTBChevronItemClass = class of TTBChevronItem; + + TTBToolbarViewClass = class of TTBToolbarView; + TTBToolbarView = class(TTBView) + private + FToolbar: TTBCustomToolbar; + protected + procedure AutoSize(AWidth, AHeight: Integer); override; + procedure DoUpdatePositions(var ASize: TPoint); override; + function GetChevronItem: TTBCustomItem; override; + function GetMDIButtonsItem: TTBCustomItem; override; + function GetMDISystemMenuItem: TTBCustomItem; override; + public + constructor Create(AOwner: TComponent); override; + function GetFont: TFont; override; + procedure InvalidatePositions; override; + end; + + TTBChevronPriorityForNewItems = (tbcpHighest, tbcpLowest); + + TTBCustomToolbar = class(TTBCustomDockableWindow, ITBItems) + private + FBaseSize: TPoint; + FChevronItem: TTBChevronItem; + FChevronMoveItems: Boolean; + FChevronPriorityForNewItems: TTBChevronPriorityForNewItems; + FDisableAlignArrange: Integer; + FFloatingWidth: Integer; + FIgnoreMouseLeave: Boolean; + FItem: TTBRootItem; + FLastWrappedLines: Integer; + FMenuBar: Boolean; + FOnShortCut: TShortCutEvent; + FProcessShortCuts: Boolean; + FMainWindowHookInstalled: Boolean; + FShrinkMode: TTBShrinkMode; + FSizeData: Pointer; + FSystemFont: Boolean; + FUpdateActions: Boolean; + + procedure CancelHover; + function CalcChevronOffset(const ADock: TTBDock; + const AOrientation: TTBViewOrientation): Integer; + function CalcWrapOffset(const ADock: TTBDock): Integer; + function CreateWrapper(Index: Integer; Ctl: TControl): TTBControlItem; + function FindWrapper(Ctl: TControl): TTBControlItem; + function GetChevronHint: String; + function GetImages: TCustomImageList; + function GetItems: TTBCustomItem; + function GetLinkSubitems: TTBCustomItem; + function GetOptions: TTBItemOptions; + procedure InstallMainWindowHook; + function IsChevronHintStored: Boolean; + class function MainWindowHook(var Message: TMessage): Boolean; + procedure SetChevronHint(const Value: String); + procedure SetChevronMoveItems(Value: Boolean); + procedure SetChevronPriorityForNewItems(Value: TTBChevronPriorityForNewItems); + procedure SetFloatingWidth(Value: Integer); + procedure SetImages(Value: TCustomImageList); + procedure SetLinkSubitems(Value: TTBCustomItem); + procedure SetMainWindowHook; + procedure SetMenuBar(Value: Boolean); + procedure SetOptions(Value: TTBItemOptions); + procedure SetProcessShortCuts(Value: Boolean); + procedure SetShrinkMode(Value: TTBShrinkMode); + procedure SetSystemFont(Value: Boolean); + procedure UninstallMainWindowHook; + procedure UpdateViewProperties; + + procedure CMColorChanged(var Message: TMessage); message CM_COLORCHANGED; + procedure CMControlChange(var Message: TCMControlChange); message CM_CONTROLCHANGE; + procedure CMControlListChange(var Message: TCMControlListChange); message CM_CONTROLLISTCHANGE; + procedure CMFontChanged(var Message: TMessage); message CM_FONTCHANGED; + procedure CMDialogChar(var Message: TCMDialogChar); message CM_DIALOGCHAR; + procedure CMDialogKey(var Message: TCMDialogKey); message CM_DIALOGKEY; + procedure CMHintShow(var Message: TCMHintShow); message CM_HINTSHOW; + procedure CMMouseLeave(var Message: TMessage); message CM_MOUSELEAVE; + procedure CMShowHintChanged(var Message: TMessage); message CM_SHOWHINTCHANGED; + procedure CMWinIniChange(var Message: TWMSettingChange); message CM_WININICHANGE; + procedure WMCancelMode(var Message: TWMCancelMode); message WM_CANCELMODE; + procedure WMGetObject(var Message: TMessage); message WM_GETOBJECT; + procedure WMMouseLeave(var Message: TMessage); message WM_MOUSELEAVE; + procedure WMNCMouseMove(var Message: TWMNCMouseMove); message WM_NCMOUSEMOVE; + {$IFNDEF JR_D5} + procedure WMRButtonUp(var Message: TWMRButtonUp); message WM_RBUTTONUP; + {$ENDIF} + procedure WMSetCursor(var Message: TWMSetCursor); message WM_SETCURSOR; + procedure WMSysCommand(var Message: TWMSysCommand); message WM_SYSCOMMAND; + protected + FMDIButtonsItem: TTBCustomItem; + FMDISystemMenuItem: TTBCustomItem; + FView: TTBToolbarView; + procedure AlignControls(AControl: TControl; var Rect: TRect); override; + procedure BuildPotentialSizesList(SizesList: TList); dynamic; + procedure ControlExistsAtPos(const P: TPoint; var ControlExists: Boolean); + override; + function DoArrange(CanMoveControls: Boolean; PreviousDockType: TTBDockType; + NewFloating: Boolean; NewDock: TTBDock): TPoint; override; + {$IFDEF JR_D5} + procedure DoContextPopup(MousePos: TPoint; var Handled: Boolean); override; + {$ENDIF} + procedure GetBaseSize(var ASize: TPoint); override; + procedure GetChildren(Proc: TGetChildProc; Root: TComponent); override; + procedure GetMinBarSize(var MinimumSize: TPoint); + procedure GetMinShrinkSize(var AMinimumSize: Integer); override; + function GetShrinkMode: TTBShrinkMode; override; + function GetChevronItemClass: TTBChevronItemClass; dynamic; + function GetItemClass: TTBRootItemClass; dynamic; + function GetViewClass: TTBToolbarViewClass; dynamic; + procedure Loaded; override; + procedure MouseDown(Button: TMouseButton; Shift: TShiftState; + X, Y: Integer); override; + procedure MouseMove(Shift: TShiftState; X, Y: Integer); override; + procedure Paint; override; + procedure ResizeBegin(ASizeHandle: TTBSizeHandle); override; + procedure ResizeTrack(var Rect: TRect; const OrigRect: TRect); override; + procedure ResizeTrackAccept; override; + procedure ResizeEnd; override; + procedure SetChildOrder(Child: TComponent; Order: Integer); override; + + property SystemFont: Boolean read FSystemFont write SetSystemFont default True; + property OnShortCut: TShortCutEvent read FOnShortCut write FOnShortCut; + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + procedure BeginUpdate; + procedure EndUpdate; + procedure CreateWrappersForAllControls; + procedure GetTabOrderList(List: TList); override; + procedure InitiateAction; override; + function IsShortCut(var Message: TWMKey): Boolean; + function KeyboardOpen(Key: Char; RequirePrimaryAccel: Boolean): Boolean; + procedure ReadPositionData(const Data: TTBReadPositionData); override; + procedure WritePositionData(const Data: TTBWritePositionData); override; + + property ChevronHint: String read GetChevronHint write SetChevronHint stored IsChevronHintStored; + property ChevronMoveItems: Boolean read FChevronMoveItems write SetChevronMoveItems default True; + property ChevronPriorityForNewItems: TTBChevronPriorityForNewItems read FChevronPriorityForNewItems + write SetChevronPriorityForNewItems default tbcpHighest; + property FloatingWidth: Integer read FFloatingWidth write SetFloatingWidth default 0; + property Images: TCustomImageList read GetImages write SetImages; + property Items: TTBRootItem read FItem; + property LinkSubitems: TTBCustomItem read GetLinkSubitems write SetLinkSubitems; + property Options: TTBItemOptions read GetOptions write SetOptions default []; + property MenuBar: Boolean read FMenuBar write SetMenuBar default False; + property ProcessShortCuts: Boolean read FProcessShortCuts write SetProcessShortCuts default False; + property ShrinkMode: TTBShrinkMode read FShrinkMode write SetShrinkMode default tbsmChevron; + property UpdateActions: Boolean read FUpdateActions write FUpdateActions default True; + property View: TTBToolbarView read FView; + published + property Hint stored False; { Hint is set dynamically; don't save it } + end; + + TTBToolbar = class(TTBCustomToolbar) + published + property ActivateParent; + property Align; + property Anchors; + property AutoResize; + property BorderStyle; + property Caption; + property ChevronHint; + property ChevronMoveItems; + property ChevronPriorityForNewItems; + property CloseButton; + property CloseButtonWhenDocked; + property Color; + property CurrentDock; + property DefaultDock; + property DockableTo; + property DockMode; + property DockPos; + property DockRow; + property DragHandleStyle; + property FloatingMode; + property FloatingWidth; + property Font; + property FullSize; + property HideWhenInactive; + property Images; + property Items; + property LastDock; + property LinkSubitems; + property MenuBar; + property Options; + property ParentFont; + property ParentShowHint; + property PopupMenu; + property ProcessShortCuts; + property Resizable; + property ShowCaption; + property ShowHint; + property ShrinkMode; + property SmoothDrag; + property Stretch; + property SystemFont; + property TabOrder; + property UpdateActions; + property UseLastDock; + property Visible; + + property OnClose; + property OnCloseQuery; + {$IFDEF JR_D5} + property OnContextPopup; + {$ENDIF} + property OnDragDrop; + property OnDragOver; + property OnMouseDown; + property OnMouseMove; + property OnMouseUp; + property OnMove; + property OnRecreated; + property OnRecreating; + property OnDockChanged; + property OnDockChanging; + property OnDockChangingHidden; + property OnResize; + property OnShortCut; + property OnVisibleChanged; + end; + +{ TTBChevronItem & TTBChevronItemViewer } + + TTBChevronItem = class(TTBCustomItem) + private + FToolbar: TTBCustomToolbar; + function GetDefaultHint: String; + public + constructor Create(AOwner: TComponent); override; + function GetChevronParentView: TTBView; override; + function GetItemViewerClass(AView: TTBView): TTBItemViewerClass; override; + end; + + TTBChevronItemViewer = class(TTBItemViewer) + protected + procedure Paint(const Canvas: TCanvas; const ClientAreaRect: TRect; + IsSelected, IsPushed, UseDisabledShadow: Boolean); override; + end; + +const + tbChevronSize = 12; + + +implementation + +uses + TB2Consts, TB2Common, TB2Hook; + +const + { Constants for TTBCustomToolbar-specific registry values. Do not localize! } + rvFloatRightX = 'FloatRightX'; + DockTypeToOrientation: array[TTBDockType] of TTBViewOrientation = + (tbvoHorizontal, tbvoFloating, tbvoHorizontal, tbvoVertical); + +type + { Used internally by the TCustomToolbar97.Resize* procedures } + PToolbar97SizeData = ^TToolbar97SizeData; + TToolbar97SizeData = record + SizeHandle: TTBSizeHandle; + NewSizes: TList; { List of valid new sizes. Items are casted into TSmallPoints } + OrigLeft, OrigTop, OrigWidth, OrigHeight, NCXDiff: Integer; + CurRightX: Integer; + DisableSensCheck, OpSide: Boolean; + SizeSens: Integer; + end; + + +procedure HookProc(Code: THookProcCode; Wnd: HWND; WParam: WPARAM; + LParam: LPARAM); +var + Msg: PMsg; + MainForm: TForm; +begin + { Work around an annoying Windows or VCL bug. If you close all MDI child + windows, the MDI client window gets the focus, and when it has the focus, + pressing Alt+[char] doesn't send a WM_SYSCOMMAND message to the form for + some reason. It seems silly to have to use a hook for this, but I don't + see a better workaround. + Also, route Alt+- to the main form so that when an MDI child form is + maximized, Alt+- brings up the TB2k MDI system menu instead of the + system's. } + if (Code = hpGetMessage) and (WParam = PM_REMOVE) then begin + Msg := PMsg(LParam); + if (Msg.message = WM_SYSCHAR) and (Msg.hwnd <> 0) then begin + { Note: On Windows NT/2000/XP, even though we install the hook using + SetWindowsHookExW, Msg.wParam may either be an ANSI character or a + Unicode character, due to an apparent bug on these platforms. It is + an ANSI character when the message passes through a separate + SetWindowsHookExA-installed WH_GETMESSAGE hook first, and that hook + calls us via CallNextHookEx. Windows apparently "forgets" to convert + the character from ANSI back to Unicode in this case. + We can't convert the character code because there seems to be no way + to detect whether it is ANSI or Unicode. So we can't really do much + with Msg.wParam, apart from comparing it against character codes that + are the same between ANSI and Unicode, such as '-'. } + MainForm := Application.MainForm; + if Assigned(MainForm) and MainForm.HandleAllocated and (GetCapture = 0) and + ((Msg.hwnd = MainForm.ClientHandle) or + ((Msg.wParam = Ord('-')) and (MainForm.ClientHandle <> 0) and + IsChild(MainForm.ClientHandle, Msg.hwnd))) then begin + { Redirect the message to the main form. + Note: Unfortunately, due to a bug in Windows NT 4.0 (and not + 2000/XP/9x/Me), modifications to the message don't take effect if + another WH_GETMESSAGE hook has been installed above this one. + (The bug is that CallNextHookEx copies lParam^ to a local buffer, but + does not propogate the changes made by the hook back to lParam^ when + it returns.) I don't know of any clean workaround, other than to + ensure other WH_GETMESSAGE hooks are installed *before* + Toolbar2000's. } + Msg.hwnd := MainForm.Handle; + end; + end; + end; +end; + +constructor TTBChevronItem.Create(AOwner: TComponent); +begin + inherited; + FToolbar := AOwner as TTBCustomToolbar; + ItemStyle := ItemStyle + [tbisSubMenu, tbisNoAutoOpen]; + Hint := GetDefaultHint; + Caption := EscapeAmpersands(GetShortHint(Hint)); +end; + +function TTBChevronItem.GetChevronParentView: TTBView; +begin + Result := FToolbar.FView; +end; + +function TTBChevronItem.GetDefaultHint: String; +begin + Result := STBChevronItemMoreButtonsHint; +end; + +function TTBChevronItem.GetItemViewerClass(AView: TTBView): TTBItemViewerClass; +begin + Result := TTBChevronItemViewer; +end; + +procedure TTBChevronItemViewer.Paint(const Canvas: TCanvas; + const ClientAreaRect: TRect; IsSelected, IsPushed, UseDisabledShadow: Boolean); +const + Pattern: array[Boolean, 0..15] of Byte = ( + ($CC, 0, $66, 0, $33, 0, $66, 0, $CC, 0, 0, 0, 0, 0, 0, 0), + ($88, 0, $D8, 0, $70, 0, $20, 0, $88, 0, $D8, 0, $70, 0, $20, 0)); +var + DC: HDC; + R2: TRect; + TempBmp: TBitmap; + + procedure DrawPattern(const Color, Offset: Integer); + begin + SelectObject(DC, GetSysColorBrush(Color)); + BitBlt(DC, R2.Left, R2.Top + Offset, R2.Right - R2.Left, + R2.Bottom - R2.Top, TempBmp.Canvas.Handle, 0, 0, $00E20746 {ROP_DSPDxax}); + end; + +begin + DC := Canvas.Handle; + R2 := ClientAreaRect; + if Item.Enabled then begin + if IsPushed then + DrawEdge(DC, R2, BDR_SUNKENOUTER, BF_RECT) + else if IsSelected and not(csDesigning in Item.ComponentState) then + DrawEdge(DC, R2, BDR_RAISEDINNER, BF_RECT); + end; + + if View.Orientation <> tbvoVertical then begin + R2.Top := 4; + R2.Bottom := R2.Top + 5; + Inc(R2.Left, 2); + R2.Right := R2.Left + 8; + end + else begin + R2.Left := R2.Right - 9; + R2.Right := R2.Left + 5; + Inc(R2.Top, 2); + R2.Bottom := R2.Top + 8; + end; + if IsPushed then + OffsetRect(R2, 1, 1); + TempBmp := TBitmap.Create; + try + TempBmp.Handle := CreateBitmap(8, 8, 1, 1, + @Pattern[View.Orientation = tbvoVertical]); + SetTextColor(DC, clBlack); + SetBkColor(DC, clWhite); + if Item.Enabled then + DrawPattern(COLOR_BTNTEXT, 0) + else begin + DrawPattern(COLOR_BTNHIGHLIGHT, 1); + DrawPattern(COLOR_BTNSHADOW, 0); + end; + finally + TempBmp.Free; + end; +end; + + +{ TTBToolbarView } + +constructor TTBToolbarView.Create(AOwner: TComponent); +begin + FToolbar := AOwner as TTBCustomToolbar; + inherited; +end; + +procedure TTBToolbarView.AutoSize(AWidth, AHeight: Integer); +begin + FToolbar.FBaseSize := BaseSize; + if FToolbar.IsAutoResized then + FToolbar.ChangeSize(AWidth, AHeight); +end; + +procedure TTBToolbarView.DoUpdatePositions(var ASize: TPoint); +begin + { Reset CurrentSize because it probably won't be valid after positions + are recalculated [2001-06-24] } + FToolbar.CurrentSize := 0; + FToolbar.GetMinBarSize(ASize); + { On FullSize toolbars, increase ASize.X/Y to WrapOffset so that + right-aligned items always appear at the right edge even when the toolbar + isn't wrapping } + if FToolbar.FullSize then begin + if (Orientation = tbvoHorizontal) and (ASize.X < WrapOffset) then + ASize.X := WrapOffset + else if (Orientation = tbvoVertical) and (ASize.Y < WrapOffset) then + ASize.Y := WrapOffset; + end; + { Increment FDisableAlignArrange so that we don't recursively arrange when + CalculatePositions moves controls } + Inc(FToolbar.FDisableAlignArrange); + try + inherited; + finally + Dec(FToolbar.FDisableAlignArrange); + end; +end; + +procedure TTBToolbarView.InvalidatePositions; +begin + { Reset CurrentSize because it probably won't be valid after positions + are recalculated [2001-06-04] } + FToolbar.CurrentSize := 0; + inherited; +end; + +function TTBToolbarView.GetFont: TFont; +begin + if not FToolbar.SystemFont then + Result := FToolbar.Font + else + Result := inherited GetFont; +end; + +function TTBToolbarView.GetChevronItem: TTBCustomItem; +begin + Result := FToolbar.FChevronItem; +end; + +function TTBToolbarView.GetMDIButtonsItem: TTBCustomItem; +begin + Result := FToolbar.FMDIButtonsItem; +end; + +function TTBToolbarView.GetMDISystemMenuItem: TTBCustomItem; +begin + Result := FToolbar.FMDISystemMenuItem; +end; + + +{ TTBCustomToolbar } + +type + {}TTBCustomItemAccess = class(TTBCustomItem); + TTBItemViewerAccess = class(TTBItemViewer); + +constructor TTBCustomToolbar.Create(AOwner: TComponent); +begin + inherited; + ControlStyle := ControlStyle + [csAcceptsControls, csActionClient] - + [csCaptureMouse]; + DockableWindowStyles := DockableWindowStyles - [tbdsResizeEightCorner, + tbdsResizeClipCursor]; + FItem := GetItemClass.Create(Self); + FItem.ParentComponent := Self; + FChevronItem := GetChevronItemClass.Create(Self); + FChevronItem.LinkSubitems := FItem; + FChevronMoveItems := True; + FView := GetViewClass.CreateView(Self, nil, FItem, Self, True, False, + not(csDesigning in ComponentState)); + FView.BackgroundColor := clBtnFace; + FUpdateActions := True; + FShrinkMode := tbsmChevron; + FSystemFont := True; + Color := clBtnFace; + SetBounds(Left, Top, 23, 22);{} +end; + +destructor TTBCustomToolbar.Destroy; +begin + { Call Destroying to ensure csDestroying is in ComponentState now. Only + needed for Delphi 4 and earlier since Delphi 5 calls Destroying in + TComponent.BeforeDestruction } + Destroying; + UninstallHookProc(Self, HookProc); + UninstallMainWindowHook; + FreeAndNil(FView); + FreeAndNil(FChevronItem); + FreeAndNil(FItem); + inherited; +end; + +function TTBCustomToolbar.GetItems: TTBCustomItem; +begin + Result := FItem; +end; + +function TTBCustomToolbar.GetItemClass: TTBRootItemClass; +begin + Result := TTBRootItem; +end; + +function TTBCustomToolbar.GetViewClass: TTBToolbarViewClass; +begin + Result := TTBToolbarView; +end; + +function TTBCustomToolbar.GetChevronItemClass: TTBChevronItemClass; +begin + Result := TTBChevronItem; +end; + +procedure TTBCustomToolbar.CreateWrappersForAllControls; +{ Create wrappers for any controls that don't already have them } +var + L: TList; + I, J, C: Integer; +begin + if ControlCount = 0 then + Exit; + L := TList.Create; + try + L.Capacity := ControlCount; + for I := 0 to ControlCount-1 do + L.Add(Controls[I]); + C := FItem.Count-1; + for I := 0 to C do + if FItem[I] is TTBControlItem then begin + J := L.IndexOf(TTBControlItem(FItem[I]).Control); + if J <> -1 then + L[J] := nil; + end; + for I := 0 to L.Count-1 do + if Assigned(L[I]) then + CreateWrapper(FItem.Count, L[I]); + finally + L.Free; + end; +end; + +procedure TTBCustomToolbar.Loaded; +begin + CreateWrappersForAllControls; + inherited; +end; + +procedure TTBCustomToolbar.GetChildren(Proc: TGetChildProc; Root: TComponent); +begin + TTBCustomItemAccess(FItem).GetChildren(Proc, Root); + inherited; +end; + +procedure TTBCustomToolbar.SetChildOrder(Child: TComponent; Order: Integer); +begin + if Child is TTBCustomItem then + TTBCustomItemAccess(FItem).SetChildOrder(Child, Order); +end; + +procedure TTBCustomToolbar.AlignControls(AControl: TControl; var Rect: TRect); +{ VCL calls this whenever any child controls in the toolbar are moved, sized, + inserted, etc., and also when the toolbar is resized. } +begin + if FDisableAlignArrange = 0 then + Arrange; +end; + +procedure TTBCustomToolbar.InitiateAction; +begin + inherited; + {}{ also add this to popupmenu(?) } + { Update visible top-level items } + if FUpdateActions then + FView.InitiateActions; +end; + +procedure TTBCustomToolbar.CMColorChanged(var Message: TMessage); +begin + { Synchronize FView.BackgroundColor with the new color } + if Assigned(FView) then + FView.BackgroundColor := Color; + inherited; +end; + +function TTBCustomToolbar.CreateWrapper(Index: Integer; + Ctl: TControl): TTBControlItem; +var + I: Integer; + S: String; +begin + Result := TTBControlItem.CreateControlItem(Owner, Ctl); + if (csDesigning in ComponentState) and Assigned(Owner) then begin + { Needs a name for compatibility with form inheritance } + I := 1; + while True do begin + S := Format('TBControlItem%d', [I]); + if Owner.FindComponent(S) = nil then + Break; + Inc(I); + end; + Result.Name := S; + end; + FItem.Insert(Index, Result); +end; + +function TTBCustomToolbar.FindWrapper(Ctl: TControl): TTBControlItem; +var + I: Integer; + Item: TTBCustomItem; +begin + Result := nil; + for I := 0 to FItem.Count-1 do begin + Item := FItem[I]; + if (Item is TTBControlItem) and + (TTBControlItem(Item).Control = Ctl) then begin + Result := TTBControlItem(Item); + Break; + end; + end; +end; + +procedure TTBCustomToolbar.CMControlChange(var Message: TCMControlChange); +{ A CM_CONTROLCHANGE handler must be used instead of a CM_CONTROLLISTCHANGE + handler because when a CM_CONTROLLISTCHANGE message is sent it is relayed to + *all* parents. CM_CONTROLCHANGE messages are only sent to the immediate + parent. } +begin + inherited; + { Don't automatically create TTBControlItem wrappers if the component + is loading or being updated to reflect changes in an ancestor form, + because wrappers will be streamed in } + if Message.Inserting and not(csLoading in ComponentState) and + not(csUpdating in ComponentState) and + (FindWrapper(Message.Control) = nil) then + CreateWrapper(FItem.Count, Message.Control); +end; + +procedure TTBCustomToolbar.CMControlListChange(var Message: TCMControlListChange); +{ Don't handle deletions inside CM_CONTROLCHANGE because CM_CONTROLCHANGE is + sent *before* a control begins removing itself from its parent. (It used + to handle both insertions and deletions inside CM_CONTROLCHANGE but this + caused AV's.) } +var + Item: TTBControlItem; +begin + inherited; + if not Message.Inserting and Assigned(FItem) then begin + while True do begin + Item := FindWrapper(Message.Control); + if Item = nil then Break; + { The control is being removed the control, not necessarily destroyed, + so set DontFreeControl to True } + Item.DontFreeControl := True; + Item.Free; + end; + end; +end; + +procedure TTBCustomToolbar.CMHintShow(var Message: TCMHintShow); +{ Since the items on a toolbar aren't "real" controls, it needs a CM_HINTSHOW + handler for their hints to be displayed. } +var + V: TTBItemViewer; +begin + with Message.HintInfo^ do begin + HintStr := ''; + V := FView.ViewerFromPoint(CursorPos); + if Assigned(V) then begin + if not IsRectEmpty(V.BoundsRect) then begin + CursorRect := V.BoundsRect; + HintStr := V.GetHintText; + end; + end; + end; +end; + +procedure TTBCustomToolbar.CMShowHintChanged(var Message: TMessage); +begin + inherited; + if ShowHint then + FView.Style := FView.Style + [vsAlwaysShowHints] + else + FView.Style := FView.Style - [vsAlwaysShowHints]; +end; + +procedure TTBCustomToolbar.WMGetObject(var Message: TMessage); +begin + if not FView.HandleWMGetObject(Message) then + inherited; +end; + +procedure TTBCustomToolbar.WMSetCursor(var Message: TWMSetCursor); +var + P: TPoint; + Cursor: HCURSOR; + R: TRect; +begin + if not(csDesigning in ComponentState) and + (Message.CursorWnd = WindowHandle) and + (Smallint(Message.HitTest) = HTCLIENT) then begin + GetCursorPos(P); + FView.UpdateSelection(@P, True); + if Assigned(FView.Selected) then begin + Cursor := 0; + R := FView.Selected.BoundsRect; + P := ScreenToClient(P); + Dec(P.X, R.Left); + Dec(P.Y, R.Top); + TTBItemViewerAccess(FView.Selected).GetCursor(P, Cursor); + if Cursor <> 0 then begin + SetCursor(Cursor); + Message.Result := 1; + Exit; + end; + end; + end; + inherited; +end; + +procedure TTBCustomToolbar.WMSysCommand(var Message: TWMSysCommand); +var + AnsiKey: Char; +begin + if FMenuBar and Enabled and Showing then + with Message do + if (CmdType and $FFF0 = SC_KEYMENU) and (Key <> VK_SPACE) and + (GetCapture = 0) then begin + if Win32Platform = VER_PLATFORM_WIN32_NT then begin + { On Windows NT 4/2000/XP, Key is a wide character, so we have to + convert it. Pressing Alt+N in a Russian input locale, for example, + results in a Key value of $0442. + This could perhaps be considered a bug in Windows NT since the + character codes in other messages such as WM_SYSCHAR aren't left + in Unicode form. + The conversion isn't done with the system code page, but rather + with the code page of the currently active input locale, like + Windows does when sending WM_(SYS)CHAR messages. } + if WideCharToMultiByte(GetInputLocaleCodePage, 0, @WideChar(Key), 1, + @AnsiKey, 1, nil, nil) <> 1 then + Exit; { shouldn't fail, but if it does, we can't continue } + end + else begin + { On Windows 95/98/Me, Key is not a wide character. } + AnsiKey := Char(Key); + end; + if not KeyboardOpen(AnsiKey, False) then begin + if Key = Ord('-') then Exit; + MessageBeep(0); + end; + Result := 1; + end; +end; + +procedure TTBCustomToolbar.Paint; +var + R: TRect; +begin + { Draw dotted border in design mode on undocked toolbars } + if not Docked and (csDesigning in ComponentState) then + with Canvas do begin + R := ClientRect; + Pen.Style := psDot; + Pen.Color := clBtnShadow; + Brush.Style := bsClear; + Rectangle(R.Left, R.Top, R.Right, R.Bottom); + Pen.Style := psSolid; + end; + FView.DrawSubitems(Canvas); +end; + +procedure TTBCustomToolbar.CMDialogKey(var Message: TCMDialogKey); +begin + if (Message.CharCode = VK_MENU) and FMenuBar then + FView.SetAccelsVisibility(True); + inherited; +end; + +procedure TTBCustomToolbar.CMDialogChar(var Message: TCMDialogChar); +begin + { On toolbars that aren't menu bars, handle CM_DIALOGCHAR instead of + WM_SYSCOMMAND } + if not FMenuBar and Enabled and Showing and (Message.CharCode <> 0) then + if KeyboardOpen(Chr(Message.CharCode), True) then begin + Message.Result := 1; + Exit; + end; + inherited; +end; + +procedure TTBCustomToolbar.CancelHover; +begin + if not MouseCapture then + FView.UpdateSelection(nil, True); +end; + +procedure TTBCustomToolbar.CMMouseLeave(var Message: TMessage); +begin + CancelHover; + inherited; +end; + +{$IFDEF JR_D5} +procedure TTBCustomToolbar.DoContextPopup(MousePos: TPoint; + var Handled: Boolean); +begin + CancelHover; + inherited; +end; +{$ENDIF} + +{$IFNDEF JR_D5} +{ Delphi 4 and earlier don't have a DoContextPopup method; we instead have to + trap WM_RBUTTONUP to determine if a popup menu (might) be displayed } +procedure TTBCustomToolbar.WMRButtonUp(var Message: TWMRButtonUp); +begin + CancelHover; + inherited; +end; +{$ENDIF} + +procedure TTBCustomToolbar.MouseMove(Shift: TShiftState; X, Y: Integer); +var + P: TPoint; + Item: TTBCustomItem; +begin + if not(csDesigning in ComponentState) then begin + P := ClientToScreen(Point(X, Y)); + FView.UpdateSelection(@P, True); + if Assigned(FView.Selected) then begin + Item := FView.Selected.Item; + if not(tboLongHintInMenuOnly in Item.EffectiveOptions) then + Hint := Item.Hint + else + Hint := ''; + end + else + Hint := ''; + end; + { Call TrackMouseEvent to be sure that we are notified when the mouse leaves + the window. We won't get a CM_MOUSELEAVE message if the mouse moves + directly from the toolbar to another application's window } + CallTrackMouseEvent(Handle, TME_LEAVE); + inherited; +end; + +procedure TTBCustomToolbar.WMCancelMode(var Message: TWMCancelMode); +begin + inherited; + { We can receive a WM_CANCELMODE message during a modal loop if a dialog + pops up. Respond by hiding menus to make it look like the modal loop + has returned, even though it really hasn't yet. + Note: Similar code in TTBModalHandler.WndProc. } + if vsModal in FView.State then + FView.CancelMode; +end; + +procedure TTBCustomToolbar.WMMouseLeave(var Message: TMessage); +begin + { A WM_MOUSELEAVE handler is necessary because the control won't get a + CM_MOUSELEAVE message if the user presses Alt+Space. Also, CM_MOUSELEAVE + messages are also not sent if the application is in a + Application.ProcessMessages loop. } + if not FIgnoreMouseLeave then + CancelHover; + inherited; +end; + +procedure TTBCustomToolbar.WMNCMouseMove(var Message: TWMNCMouseMove); +begin + Hint := ''; + CancelHover; + inherited; +end; + +function TTBCustomToolbar.KeyboardOpen(Key: Char; + RequirePrimaryAccel: Boolean): Boolean; +var + I: TTBItemViewer; + IsOnlyItemWithAccel: Boolean; +begin + I := nil; + FView.SetAccelsVisibility(True); + try + Result := False; + if Key = #0 then begin + I := FView.FirstSelectable; + if I = nil then Exit; + FView.Selected := I; + FView.EnterToolbarLoop([]); + end + else begin + I := FView.NextSelectableWithAccel(nil, Key, RequirePrimaryAccel, + IsOnlyItemWithAccel); + if (I = nil) or not I.Item.Enabled then + Exit; + if IsOnlyItemWithAccel then begin + FView.Selected := I; + FView.EnterToolbarLoop([tbetExecuteSelected]); + end + else if FMenuBar then begin + FView.Selected := I; + FView.EnterToolbarLoop([]); + end + else + Exit; + end; + Result := True; + finally + if Assigned(I) then + FView.SetAccelsVisibility(False); + end; +end; + +procedure TTBCustomToolbar.MouseDown(Button: TMouseButton; Shift: TShiftState; + X, Y: Integer); +var + OldParent: TWinControl; + P: TPoint; + Item: TTBCustomItem; +begin + OldParent := Parent; + inherited; + if Parent <> OldParent then + { if the inherited handler (TTBDockableWindow.MouseDown) changed the Parent + (due to the toolbar moving between docks), nothing else should be done } + Exit; + if not(csDesigning in ComponentState) and (Button = mbLeft) then begin + P := ClientToScreen(Point(X, Y)); + FView.UpdateSelection(@P, True); + if Assigned(FView.Selected) then begin + Item := FView.Selected.Item; + if not(tbisClicksTransparent in TTBCustomItemAccess(Item).ItemStyle) then begin + FIgnoreMouseLeave := True; + try + FView.EnterToolbarLoop([tbetMouseDown]); + finally + FIgnoreMouseLeave := False; + end; + end; + end; + end; +end; + +procedure TTBCustomToolbar.CMFontChanged(var Message: TMessage); +begin + inherited; + if not FSystemFont then + Arrange; +end; + +function TTBCustomToolbar.GetChevronHint: String; +begin + Result := FChevronItem.Hint; +end; + +procedure TTBCustomToolbar.SetChevronHint(const Value: String); +begin + FChevronItem.Hint := Value; + FChevronItem.Caption := EscapeAmpersands(GetShortHint(Value)); +end; + +procedure TTBCustomToolbar.SetChevronMoveItems(Value: Boolean); +begin + if FChevronMoveItems <> Value then begin + FChevronMoveItems := Value; + FView.UsePriorityList := Value and not(csDesigning in ComponentState); + end; +end; + +procedure TTBCustomToolbar.SetChevronPriorityForNewItems(Value: TTBChevronPriorityForNewItems); +begin + FChevronPriorityForNewItems := Value; + FView.NewViewersGetHighestPriority := (Value = tbcpHighest); +end; + +function TTBCustomToolbar.IsChevronHintStored: Boolean; +begin + Result := (FChevronItem.Hint <> FChevronItem.GetDefaultHint); +end; + +function TTBCustomToolbar.GetImages: TCustomImageList; +begin + Result := FItem.SubMenuImages; +end; + +procedure TTBCustomToolbar.SetImages(Value: TCustomImageList); +begin + FItem.SubMenuImages := Value; +end; + +function TTBCustomToolbar.GetLinkSubitems: TTBCustomItem; +begin + Result := FItem.LinkSubitems; +end; + +procedure TTBCustomToolbar.SetLinkSubitems(Value: TTBCustomItem); +begin + FItem.LinkSubitems := Value; +end; + +procedure TTBCustomToolbar.SetMenuBar(Value: Boolean); +begin + if FMenuBar <> Value then begin + FMenuBar := Value; + if Value then begin + ControlStyle := ControlStyle + [csMenuEvents]; + FView.Style := FView.Style + [vsMenuBar, vsUseHiddenAccels]; + end + else begin + ControlStyle := ControlStyle - [csMenuEvents]; + FView.Style := FView.Style - [vsMenuBar, vsUseHiddenAccels]; + end; + if not(csLoading in ComponentState) then begin + FullSize := Value; + if Value then + ShrinkMode := tbsmWrap + else + ShrinkMode := tbsmChevron; + CloseButton := not Value; + ProcessShortCuts := Value; + end; + if Value and not(csDesigning in ComponentState) then + InstallHookProc(Self, HookProc, [hpGetMessage]) + else + UninstallHookProc(Self, HookProc); + SetMainWindowHook; + end; +end; + +function TTBCustomToolbar.GetOptions: TTBItemOptions; +begin + Result := FItem.Options; +end; + +procedure TTBCustomToolbar.SetOptions(Value: TTBItemOptions); +begin + FItem.Options := Value; +end; + +procedure TTBCustomToolbar.SetProcessShortCuts(Value: Boolean); +begin + if FProcessShortCuts <> Value then begin + FProcessShortCuts := Value; + SetMainWindowHook; + end; +end; + +procedure TTBCustomToolbar.SetSystemFont(Value: Boolean); +begin + if FSystemFont <> Value then begin + FSystemFont := Value; + Arrange; + end; +end; + +procedure TTBCustomToolbar.SetShrinkMode(Value: TTBShrinkMode); +begin + if FShrinkMode <> Value then begin + FShrinkMode := Value; + if Docked then + CurrentDock.ArrangeToolbars + else if not Floating then + Arrange; + end; +end; + +procedure TTBCustomToolbar.SetFloatingWidth(Value: Integer); +begin + if FFloatingWidth <> Value then begin + FFloatingWidth := Value; + if Floating then begin + UpdateViewProperties; + Arrange; + end; + end; +end; + +function TTBCustomToolbar.CalcWrapOffset(const ADock: TTBDock): Integer; +begin + if ADock = nil then + Result := FFloatingWidth + else begin + if FShrinkMode = tbsmWrap then begin + if not(ADock.Position in [dpLeft, dpRight]) then + Result := ADock.Width - ADock.NonClientWidth - NonClientWidth + else + Result := ADock.Height - ADock.NonClientHeight - NonClientHeight; + end + else + Result := 0; + end; +end; + +function TTBCustomToolbar.CalcChevronOffset(const ADock: TTBDock; + const AOrientation: TTBViewOrientation): Integer; +begin + if (FShrinkMode = tbsmChevron) and Docked and (ADock = CurrentDock) then begin + Result := CurrentSize; + { Subtract non-client size } + if AOrientation <> tbvoVertical then + Dec(Result, NonClientWidth) + else + Dec(Result, NonClientHeight); + if Result < 0 then + Result := 0; { in case CurrentSize wasn't properly initialized yet } + end + else + Result := 0; +end; + +procedure TTBCustomToolbar.UpdateViewProperties; +var + DT: TTBDockType; +begin + DT := TBGetDockTypeOf(CurrentDock, Floating); + FView.Orientation := DockTypeToOrientation[DT]; + FView.ChevronSize := tbChevronSize; + if Assigned(CurrentDock) or Floating then begin + FView.ChevronOffset := CalcChevronOffset(CurrentDock, FView.Orientation); + FView.WrapOffset := CalcWrapOffset(CurrentDock); + end + else begin + FView.ChevronOffset := 0; + FView.WrapOffset := 0; + { Only enable chevron/wrapping when the width of the toolbar is fixed } + if not AutoResize or ((akLeft in Anchors) and (akRight in Anchors)) then begin + if FShrinkMode = tbsmChevron then + FView.ChevronOffset := Width - NonClientWidth + else if FShrinkMode = tbsmWrap then + FView.WrapOffset := Width - NonClientWidth; + end; + end; +end; + +{}{DOCKING STUFF} + +procedure TTBCustomToolbar.ReadPositionData(const Data: TTBReadPositionData); +begin + inherited; + with Data do + FloatingWidth := ReadIntProc(Name, rvFloatRightX, 0, ExtraData); +end; + +procedure TTBCustomToolbar.WritePositionData(const Data: TTBWritePositionData); +begin + inherited; + with Data do + WriteIntProc(Name, rvFloatRightX, FFloatingWidth, ExtraData); +end; + +procedure TTBCustomToolbar.GetMinBarSize(var MinimumSize: TPoint); +var + WH: Integer; +begin + MinimumSize.X := 0; + MinimumSize.Y := 0; + if Docked then begin + WH := CurrentDock.GetMinRowSize(EffectiveDockRow, Self); + if not(CurrentDock.Position in [dpLeft, dpRight]) then + MinimumSize.Y := WH + else + MinimumSize.X := WH; + end; +end; + +procedure TTBCustomToolbar.GetBaseSize(var ASize: TPoint); +begin + FView.ValidatePositions; + ASize := FBaseSize; +end; + +function TTBCustomToolbar.DoArrange(CanMoveControls: Boolean; + PreviousDockType: TTBDockType; NewFloating: Boolean; NewDock: TTBDock): TPoint; +var + DT: TTBDockType; + O: TTBViewOrientation; + TempBaseSize: TPoint; +begin + //outputdebugstring (pchar(format('%s.DoArrange(%d)', [Name, Ord(CanMoveControls)]))); + if CanMoveControls then begin + UpdateViewProperties; + Result := FView.UpdatePositions; + end + else begin + DT := TBGetDockTypeOf(NewDock, NewFloating); + O := DockTypeToOrientation[DT]; + Result.X := 0; + Result.Y := 0; + FView.CalculatePositions(False, O, CalcWrapOffset(NewDock), + CalcChevronOffset(NewDock, O), tbChevronSize, TempBaseSize, Result, + FLastWrappedLines); + end; +end; + +procedure TTBCustomToolbar.ControlExistsAtPos(const P: TPoint; + var ControlExists: Boolean); +var + P2: TPoint; +begin + inherited; + if not ControlExists and not(csDesigning in ComponentState) then begin + P2 := ClientToScreen(P); + FView.UpdateSelection(@P2, True); + if Assigned(FView.Selected) and + not(tbisClicksTransparent in TTBCustomItemAccess(FView.Selected.Item).ItemStyle) then + ControlExists := True; + end; +end; + +procedure TTBCustomToolbar.BuildPotentialSizesList(SizesList: TList); +var + Margins: TRect; + MinX, SaveWrapX: Integer; + X, PrevWrappedLines: Integer; + S: TPoint; + S2: TSmallPoint; +begin + View.GetMargins(tbvoFloating, Margins); + MinX := Margins.Left + Margins.Right; + SaveWrapX := FFloatingWidth; + try + { Add the widest size to the list } + FFloatingWidth := 0; + S := DoArrange(False, dtNotDocked, True, nil); + SizesList.Add(Pointer(PointToSmallPoint(S))); + { Calculate and add rest of sizes to the list } + PrevWrappedLines := 1; + X := S.X-1; + while X >= MinX do begin + FFloatingWidth := X; + S := DoArrange(False, dtNotDocked, True, nil); + if S.X > X then { if it refuses to go any smaller } + Break + else + if X = S.X then begin + S2 := PointToSmallPoint(S); + if FLastWrappedLines <> PrevWrappedLines then + SizesList.Add(Pointer(S2)) + else + SizesList[SizesList.Count-1] := Pointer(S2); + PrevWrappedLines := FLastWrappedLines; + Dec(X); + end + else + X := S.X; + end; + finally + FFloatingWidth := SaveWrapX; + end; +end; + +function CompareNewSizes(const Item1, Item2, ExtraData: Pointer): Integer; far; +begin + { Sorts in descending order } + if ExtraData = nil then + Result := TSmallPoint(Item2).X - TSmallPoint(Item1).X + else + Result := TSmallPoint(Item2).Y - TSmallPoint(Item1).Y; +end; + +procedure TTBCustomToolbar.ResizeBegin(ASizeHandle: TTBSizeHandle); +const + MaxSizeSens = 12; +var + I, NewSize: Integer; + S, N: TSmallPoint; + P: TPoint; +begin + inherited; + + FSizeData := AllocMem(SizeOf(TToolbar97SizeData)); + + with PToolbar97SizeData(FSizeData)^ do begin + SizeHandle := ASizeHandle; + OrigLeft := Parent.Left; + OrigTop := Parent.Top; + OrigWidth := Parent.Width; + OrigHeight := Parent.Height; + NCXDiff := ClientToScreen(Point(0, 0)).X - OrigLeft; + CurRightX := FFloatingWidth; + DisableSensCheck := False; + OpSide := False; + + NewSizes := TList.Create; + BuildPotentialSizesList(NewSizes); + for I := 0 to NewSizes.Count-1 do begin + P := SmallPointToPoint(TSmallPoint(NewSizes.List[I])); + AddFloatingNCAreaToSize(P); + NewSizes.List[I] := Pointer(PointToSmallPoint(P)); + end; + ListSortEx(NewSizes, CompareNewSizes, + Pointer(Ord(ASizeHandle in [twshTop, twshBottom]))); + + SizeSens := MaxSizeSens; + { Adjust sensitivity if it's too high } + for I := 0 to NewSizes.Count-1 do begin + Pointer(S) := NewSizes[I]; + if (S.X = Width) and (S.Y = Height) then begin + if I > 0 then begin + Pointer(N) := NewSizes[I-1]; + if ASizeHandle in [twshLeft, twshRight] then + NewSize := N.X - S.X - 1 + else + NewSize := N.Y - S.Y - 1; + if NewSize < SizeSens then SizeSens := NewSize; + end; + if I < NewSizes.Count-1 then begin + Pointer(N) := NewSizes[I+1]; + if ASizeHandle in [twshLeft, twshRight] then + NewSize := S.X - N.X - 1 + else + NewSize := S.Y - N.Y - 1; + if NewSize < SizeSens then SizeSens := NewSize; + end; + Break; + end; + end; + if SizeSens < 0 then SizeSens := 0; + end; +end; + +procedure TTBCustomToolbar.ResizeTrack(var Rect: TRect; const OrigRect: TRect); +var + Pos: TPoint; + NewOpSide: Boolean; + Reverse: Boolean; + I: Integer; + P: TSmallPoint; +begin + inherited; + + with PToolbar97SizeData(FSizeData)^ do begin + GetCursorPos(Pos); + + Dec(Pos.X, OrigLeft); Dec(Pos.Y, OrigTop); + if SizeHandle = twshLeft then + Pos.X := OrigWidth-Pos.X + else + if SizeHandle = twshTop then + Pos.Y := OrigHeight-Pos.Y; + + { Adjust Pos to make up for the "sizing sensitivity", as seen in Office 97 } + if SizeHandle in [twshLeft, twshRight] then + NewOpSide := Pos.X < OrigWidth + else + NewOpSide := Pos.Y < OrigHeight; + if (not DisableSensCheck) or (OpSide <> NewOpSide) then begin + DisableSensCheck := False; + OpSide := NewOpSide; + if SizeHandle in [twshLeft, twshRight] then begin + if (Pos.X >= OrigWidth-SizeSens) and (Pos.X < OrigWidth+SizeSens) then + Pos.X := OrigWidth; + end + else begin + if (Pos.Y >= OrigHeight-SizeSens) and (Pos.Y < OrigHeight+SizeSens) then + Pos.Y := OrigHeight; + end; + end; + + Rect := OrigRect; + + if SizeHandle in [twshLeft, twshRight] then + Reverse := Pos.X > OrigWidth + else + Reverse := Pos.Y > OrigHeight; + if not Reverse then + I := NewSizes.Count-1 + else + I := 0; + while True do begin + if (not Reverse and (I < 0)) or + (Reverse and (I >= NewSizes.Count)) then + Break; + Pointer(P) := NewSizes[I]; + if SizeHandle in [twshLeft, twshRight] then begin + if (not Reverse and ((I = NewSizes.Count-1) or (Pos.X >= P.X))) or + (Reverse and ((I = 0) or (Pos.X < P.X))) then begin + if I = 0 then + CurRightX := 0 + else + CurRightX := P.X - NCXDiff*2; + if SizeHandle = twshRight then + Rect.Right := Rect.Left + P.X + else + Rect.Left := Rect.Right - P.X; + Rect.Bottom := Rect.Top + P.Y; + DisableSensCheck := not EqualRect(Rect, OrigRect); + end; + end + else begin + if (not Reverse and ((I = NewSizes.Count-1) or (Pos.Y >= P.Y))) or + (Reverse and ((I = 0) or (Pos.Y < P.Y))) then begin + if I = NewSizes.Count-1 then + CurRightX := 0 + else + CurRightX := P.X - NCXDiff*2; + if SizeHandle = twshBottom then + Rect.Bottom := Rect.Top + P.Y + else + Rect.Top := Rect.Bottom - P.Y; + Rect.Right := Rect.Left + P.X; + DisableSensCheck := not EqualRect(Rect, OrigRect); + end; + end; + if not Reverse then + Dec(I) + else + Inc(I); + end; + end; +end; + +procedure TTBCustomToolbar.ResizeTrackAccept; +begin + inherited; + FloatingWidth := PToolbar97SizeData(FSizeData)^.CurRightX; +end; + +procedure TTBCustomToolbar.ResizeEnd; +begin + inherited; + if Assigned(FSizeData) then begin + PToolbar97SizeData(FSizeData)^.NewSizes.Free; + FreeMem(FSizeData); + FSizeData := nil; + end; +end; + +function TTBCustomToolbar.GetShrinkMode: TTBShrinkMode; +begin + Result := FShrinkMode; +end; + +procedure TTBCustomToolbar.GetMinShrinkSize(var AMinimumSize: Integer); +var + I: TTBItemViewer; +begin + I := FView.HighestPriorityViewer; + if Assigned(I) then begin + if not(CurrentDock.Position in [dpLeft, dpRight]) then + AMinimumSize := I.BoundsRect.Right - I.BoundsRect.Left + else + AMinimumSize := I.BoundsRect.Bottom - I.BoundsRect.Top; + end; + if not(CurrentDock.Position in [dpLeft, dpRight]) then + Inc(AMinimumSize, NonClientWidth) + else + Inc(AMinimumSize, NonClientHeight); + Inc(AMinimumSize, tbChevronSize); +end; + +procedure TTBCustomToolbar.BeginUpdate; +begin + FView.BeginUpdate; +end; + +procedure TTBCustomToolbar.EndUpdate; +begin + FView.EndUpdate; +end; + +procedure TTBCustomToolbar.GetTabOrderList(List: TList); +var + CtlList: TList; + I, J: Integer; + CtlI, CtlJ: TWinControl; +begin + inherited; + { Remove off-edge items and their children from List } + CtlList := TList.Create; + try + FView.GetOffEdgeControlList(CtlList); + for I := 0 to CtlList.Count-1 do begin + CtlI := CtlList[I]; + J := 0; + while J < List.Count do begin + CtlJ := List[J]; + if (CtlJ = CtlI) or CtlI.ContainsControl(CtlJ) then + List.Delete(J) + else + Inc(J); + end; + end; + finally + CtlList.Free; + end; +end; + +procedure TTBCustomToolbar.CMWinIniChange(var Message: TWMSettingChange); +begin + inherited; + if Message.Flag = SPI_SETNONCLIENTMETRICS then begin + TBInitToolbarSystemFont; + Arrange; + end; +end; + +function TTBCustomToolbar.IsShortCut(var Message: TWMKey): Boolean; +begin + Result := False; + if Assigned(FOnShortCut) then + FOnShortCut(Message, Result); + Result := Result or FItem.IsShortCut(Message); +end; + +var + HookCount: Integer; + HookList: TList; + +class function TTBCustomToolbar.MainWindowHook(var Message: TMessage): Boolean; + + function GetActiveForm: TCustomForm; + var + Wnd: HWND; + Ctl: TWinControl; + begin + { Note: We don't use Screen.ActiveCustomForm because when an EXE calls a + DLL that shows a modal form, Screen.ActiveCustomForm doesn't change in + the EXE; it remains set to the last form that was active in the EXE. + Use FindControl(GetActiveWindow) instead to avoid this problem; it will + return nil when a form in another module is active. } + Result := nil; + Wnd := GetActiveWindow; + if Wnd <> 0 then begin + Ctl := FindControl(Wnd); + if Assigned(Ctl) and (Ctl is TCustomForm) then + Result := TCustomForm(Ctl); + end; + end; + + function HandleShortCutOnForm(const Form: TCustomForm): Boolean; + var + I: Integer; + Toolbar: TTBCustomToolbar; + begin + Result := False; + if Form = nil then + Exit; + for I := 0 to HookList.Count-1 do begin + Toolbar := HookList[I]; + if Toolbar.ProcessShortCuts and + (TBGetToolWindowParentForm(Toolbar) = Form) and + IsWindowEnabled(Form.Handle) and + Toolbar.IsShortCut(TWMKey(Message)) then begin + Message.Result := 1; + Result := True; + Exit; + end; + end; + end; + + function TraverseControls(Container: TWinControl): Boolean; + var + I: Integer; + Control: TControl; + begin + Result := False; + if Container.Showing then + for I := 0 to Container.ControlCount - 1 do begin + Control := Container.Controls[I]; + if Control.Visible and Control.Enabled then begin + if (csMenuEvents in Control.ControlStyle) and + ((Control is TTBDock) or (Control is TTBCustomToolbar)) and + (Control.Perform(WM_SYSCOMMAND, TMessage(Message).WParam, + TMessage(Message).LParam) <> 0) or (Control is TWinControl) and + TraverseControls(TWinControl(Control)) then begin + Result := True; + Exit; + end; + end; + end; + end; + +var + ActiveForm: TCustomForm; + ActiveMDIChild: TForm; +begin + Result := False; + if (Message.Msg = CM_APPKEYDOWN) and Assigned(HookList) then begin + { Process shortcuts on toolbars. Search forms in this order: + 1. If the active form is an MDI parent form, the active MDI child form + if it has the focus. + 2. The active form. + 3. The main form. } + ActiveForm := GetActiveForm; + if Assigned(ActiveForm) and (ActiveForm is TForm) and + (TForm(ActiveForm).FormStyle = fsMDIForm) then begin + ActiveMDIChild := TForm(ActiveForm).ActiveMDIChild; + { Don't search the child form if a control on the MDI parent form is + currently focused (i.e. Screen.ActiveCustomForm <> ActiveMDIChild) } + if Assigned(ActiveMDIChild) and + (Screen.ActiveCustomForm = ActiveMDIChild) and + HandleShortCutOnForm(ActiveMDIChild) then begin + Result := True; + Exit; + end; + end; + if HandleShortCutOnForm(ActiveForm) then + Result := True + else begin + if (Application.MainForm <> ActiveForm) and + HandleShortCutOnForm(Application.MainForm) then + Result := True; + end; + end + else if Message.Msg = CM_APPSYSCOMMAND then begin + { Handle "Alt or Alt+[key] pressed on secondary form" case. If there's a + menu bar on the active form we want the keypress to go to it instead of + to the main form (the VCL's default handling). } + ActiveForm := GetActiveForm; + if Assigned(ActiveForm) and IsWindowEnabled(ActiveForm.Handle) and + IsWindowVisible(ActiveForm.Handle) and TraverseControls(ActiveForm) then begin + Message.Result := 1; + Result := True; + end; + end; +end; + +procedure TTBCustomToolbar.SetMainWindowHook; +begin + if (ProcessShortCuts or MenuBar) and not(csDesigning in ComponentState) then + InstallMainWindowHook + else + UninstallMainWindowHook; +end; + +procedure TTBCustomToolbar.InstallMainWindowHook; +begin + if FMainWindowHookInstalled then + Exit; + if HookCount = 0 then + Application.HookMainWindow(MainWindowHook); + Inc(HookCount); + AddToList(HookList, Self); + FMainWindowHookInstalled := True; +end; + +procedure TTBCustomToolbar.UninstallMainWindowHook; +begin + if not FMainWindowHookInstalled then + Exit; + FMainWindowHookInstalled := False; + RemoveFromList(HookList, Self); + Dec(HookCount); + if HookCount = 0 then + Application.UnhookMainWindow(MainWindowHook); +end; + +end. diff --git a/official/2.1.6+2.1.beta1/Source/TB2Ver.inc b/official/2.1.6+2.1.beta1/Source/TB2Ver.inc new file mode 100644 index 0000000..720ea8d --- /dev/null +++ b/official/2.1.6+2.1.beta1/Source/TB2Ver.inc @@ -0,0 +1,37 @@ +{ $jrsoftware: tb2k/Source/TB2Ver.inc,v 1.5 2004/12/19 21:57:34 jr Exp $ } + +{ Determine Delphi/C++Builder version } +{$IFNDEF WIN32} Delphi 1 is not supported. {$ENDIF} +{$IFNDEF VER90} { if it's not Delphi 2.0 } + {$IFNDEF VER93} { and it's not C++Builder 1.0 } + {$DEFINE JR_D3} { then it must be at least Delphi 3 or C++Builder 3 } + {$IFNDEF VER100} { if it's not Delphi 3.0 } + {$IFNDEF VER120} { Delphi 4/5's command line compiler doesn't like the ObjExportAll directive, so don't include it on Delphi 4/5 } + {$IFNDEF VER130} + {$ObjExportAll On} { <- needed for compatibility with run-time packages in C++Builder 3+ } + {$ENDIF} + {$ENDIF} + {$IFNDEF VER110} { and it's not C++Builder 3.0 } + {$DEFINE JR_D4} { then it must be at least Delphi 4 or C++Builder 4 } + {$IFNDEF VER120} {$IFNDEF VER125} { if it's not Delphi 4 or C++Builder 4 } + {$DEFINE JR_D5} { then it must be at least Delphi 5 or C++Builder 5 } + {$IFNDEF VER130} { if it's not Delphi 5 or C++Builder 5 } + {$DEFINE JR_D6} { then it must be at least Delphi 6 or C++Builder 6 } + {$IFNDEF VER140} { if it's not Delphi 6 or C++Builder 6 } + {$DEFINE JR_D7} { then it must be at least Delphi 7 } + {$IFNDEF VER150} { if it's not Delphi 7 } + {$DEFINE JR_D9} { then it must be at least Delphi 9 (2005) } + {$ENDIF} + {$ENDIF} + {$ENDIF} + {$ENDIF} {$ENDIF} + {$ENDIF} + {$ENDIF} + {$ENDIF} +{$ENDIF} + +{$ALIGN ON} +{$BOOLEVAL OFF} +{$LONGSTRINGS ON} +{$TYPEDADDRESS OFF} +{$WRITEABLECONST ON} diff --git a/official/2.1.6+2.1.beta1/Source/TB2Version.pas b/official/2.1.6+2.1.beta1/Source/TB2Version.pas new file mode 100644 index 0000000..0ca7ffb --- /dev/null +++ b/official/2.1.6+2.1.beta1/Source/TB2Version.pas @@ -0,0 +1,55 @@ +unit TB2Version; + +{ + Toolbar2000 + Copyright (C) 1998-2005 by Jordan Russell + All rights reserved. + + The contents of this file are subject to the "Toolbar2000 License"; you may + not use or distribute this file except in compliance with the + "Toolbar2000 License". A copy of the "Toolbar2000 License" may be found in + TB2k-LICENSE.txt or at: + http://www.jrsoftware.org/files/tb2k/TB2k-LICENSE.txt + + Alternatively, the contents of this file may be used under the terms of the + GNU General Public License (the "GPL"), in which case the provisions of the + GPL are applicable instead of those in the "Toolbar2000 License". A copy of + the GPL may be found in GPL-LICENSE.txt or at: + http://www.jrsoftware.org/files/tb2k/GPL-LICENSE.txt + If you wish to allow use of your version of this file only under the terms of + the GPL and not to allow others to use your version of this file under the + "Toolbar2000 License", indicate your decision by deleting the provisions + above and replace them with the notice and other provisions required by the + GPL. If you do not delete the provisions above, a recipient may use your + version of this file under either the "Toolbar2000 License" or the GPL. + + $jrsoftware: tb2k/Source/TB2Version.pas,v 1.61 2005/07/30 18:34:13 jr Exp $ +} + +interface + +{$I TB2Ver.inc} + +const + Toolbar2000Version = '2.1.6'; + Toolbar2000VersionPropText = 'Toolbar2000 version ' + Toolbar2000Version; + +type + TToolbar2000Version = type string; + +const + Sig: PChar = '- ' + Toolbar2000VersionPropText + + {$IFDEF VER90} '/D2'+ {$ENDIF} {$IFDEF VER93} '/CB1'+ {$ENDIF} + {$IFDEF VER100} '/D3'+ {$ENDIF} {$IFDEF VER110} '/CB3'+ {$ENDIF} + {$IFDEF VER120} '/D4'+ {$ENDIF} {$IFDEF VER125} '/CB4'+ {$ENDIF} + {$IFNDEF BCB} {$IFDEF VER130} '/D5'+ {$ENDIF} {$ELSE} {$IFDEF VER130} '/CB5'+ {$ENDIF} {$ENDIF} + {$IFNDEF BCB} {$IFDEF VER140} '/D6'+ {$ENDIF} {$ELSE} {$IFDEF VER140} '/CB6'+ {$ENDIF} {$ENDIF} + {$IFNDEF BCB} {$IFDEF VER150} '/D7'+ {$ENDIF} {$ELSE} {$IFDEF VER150} '/CB7'+ {$ENDIF} {$ENDIF} + {$IFNDEF BCB} {$IFDEF VER170} '/D9'+ {$ENDIF} {$ELSE} {$IFDEF VER170} '/CB9'+ {$ENDIF} {$ENDIF} + ', Copyright (C) 1998-2005 by Jordan Russell -'; + +implementation + +initialization + Sig := Sig; +end. diff --git a/official/2.1.6+2.1.beta1/Source/_cvs_patch-2_1_4.bat b/official/2.1.6+2.1.beta1/Source/_cvs_patch-2_1_4.bat new file mode 100644 index 0000000..ff38eca --- /dev/null +++ b/official/2.1.6+2.1.beta1/Source/_cvs_patch-2_1_4.bat @@ -0,0 +1 @@ +patch -p0 --backup < _cvs_patch-2_1_4.diff diff --git a/official/2.1.6+2.1.beta1/Source/_cvs_patch-2_1_4.diff b/official/2.1.6+2.1.beta1/Source/_cvs_patch-2_1_4.diff new file mode 100644 index 0000000..49460d7 --- /dev/null +++ b/official/2.1.6+2.1.beta1/Source/_cvs_patch-2_1_4.diff @@ -0,0 +1,1441 @@ +Index: TB2Common.pas +=================================================================== +RCS file: /data/cvs/tb2k/Source/TB2Common.pas,v +retrieving revision 1.28 +diff -u -r1.28 TB2Common.pas +--- TB2Common.pas 26 Feb 2004 07:05:57 -0000 1.28 ++++ TB2Common.pas 29 May 2004 22:19:14 -0000 +@@ -868,40 +868,82 @@ + procedure DrawRotatedText(const DC: HDC; AText: String; const ARect: TRect; + const AFormat: Cardinal); + { Like DrawText, but draws the text at a 270 degree angle. +- The only format flag this function respects is DT_HIDEPREFIX. Text is always +- drawn centered. } ++ The format flag this function respects are ++ DT_NOPREFIX, DT_HIDEPREFIX, DT_CENTER, DT_END_ELLIPSIS, DT_NOCLIP } + var + RotatedFont, SaveFont: HFONT; + TextMetrics: TTextMetric; +- X, Y, P, I, SU, FU: Integer; ++ X, Y, P, I, SU, FU, W: Integer; + SaveAlign: UINT; + SavePen, Pen: HPEN; ++ Clip: Boolean; ++ ++ function GetSize(DC: HDC; const S: string): Integer; ++ var ++ Size: TSize; ++ begin ++ GetTextExtentPoint32(DC, PChar(S), Length(S), Size); ++ Result := Size.cx; ++ end; ++ + begin ++ if Length(AText) = 0 then Exit; ++ + RotatedFont := CreateRotatedFont(DC); + SaveFont := SelectObject(DC, RotatedFont); + + GetTextMetrics(DC, TextMetrics); + X := ARect.Left + ((ARect.Right - ARect.Left) - TextMetrics.tmHeight) div 2; +- Y := ARect.Top + ((ARect.Bottom - ARect.Top) - GetTextWidth(DC, AText, True)) div 2; ++ ++ Clip := (AFormat and DT_NOCLIP) <> DT_NOCLIP; + + { Find the index of the character that should be underlined. Delete '&' + characters from the string. Like DrawText, only the last prefixed character + will be underlined. } + P := 0; + I := 1; +- while I <= Length(AText) do begin +- if AText[I] in LeadBytes then +- Inc(I) +- else if AText[I] = '&' then begin +- Delete(AText, I, 1); +- { Note: PChar cast is so that if Delete deleted the last character in +- the string, we don't step past the end of the string (which would cause +- an AV if AText is now empty), but rather look at the null character +- and treat it as an accelerator key like DrawText. } +- if PChar(AText)[I-1] <> '&' then +- P := I; ++ if (AFormat and DT_NOPREFIX) <> DT_NOPREFIX then ++ while I <= Length(AText) do begin ++ if AText[I] in LeadBytes then ++ Inc(I) ++ else if AText[I] = '&' then begin ++ Delete(AText, I, 1); ++ { Note: PChar cast is so that if Delete deleted the last character in ++ the string, we don't step past the end of the string (which would cause ++ an AV if AText is now empty), but rather look at the null character ++ and treat it as an accelerator key like DrawText. } ++ if PChar(AText)[I-1] <> '&' then ++ P := I; ++ end; ++ Inc(I); ++ end; ++ ++ if (AFormat and DT_END_ELLIPSIS) = DT_END_ELLIPSIS then ++ begin ++ if (Length(AText) > 1) and (GetSize(DC, AText) > ARect.Bottom - ARect.Top) then ++ begin ++ W := ARect.Bottom - ARect.Top; ++ if W > 2 then ++ begin ++ Delete(AText, Length(AText), 1); ++ while (Length(AText) > 1) and (GetSize(DC, AText + '...') > W) do ++ Delete(AText, Length(AText), 1); ++ end ++ else AText := AText[1]; ++ if P > Length(AText) then P := 0; ++ AText := AText + '...'; + end; +- Inc(I); ++ end; ++ ++ if (AFormat and DT_CENTER) = DT_CENTER then ++ Y := ARect.Top + ((ARect.Bottom - ARect.Top) - GetSize(DC, AText)) div 2 ++ else ++ Y := ARect.Top; ++ ++ if Clip then ++ begin ++ SaveDC(DC); ++ with ARect do IntersectClipRect(DC, Left, Top, Right, Bottom); + end; + + SaveAlign := SetTextAlign(DC, TA_BOTTOM); +@@ -920,6 +962,8 @@ + DeleteObject(Pen); + end; + ++ if Clip then RestoreDC(DC, -1); ++ + SelectObject(DC, SaveFont); + DeleteObject(RotatedFont); + end; +Index: TB2Dock.pas +=================================================================== +RCS file: /data/cvs/tb2k/Source/TB2Dock.pas,v +retrieving revision 1.88 +diff -u -r1.88 TB2Dock.pas +--- TB2Dock.pas 26 Feb 2004 07:05:57 -0000 1.88 ++++ TB2Dock.pas 29 May 2004 22:19:14 -0000 +@@ -82,9 +82,6 @@ + FDisableArrangeToolbars: Integer; { Increment to disable ArrangeToolbars } + FArrangeToolbarsNeeded: Boolean; + FNonClientWidth, FNonClientHeight: Integer; +- DockList: TList; { List of the toolbars docked, and those floating and have LastDock +- pointing to the dock. Items are casted in TTBCustomDockableWindow's. } +- DockVisibleList: TList; { Similar to DockList, but lists only docked and visible toolbars } + + { Property access methods } + //function GetVersion: TToolbar97Version; +@@ -102,14 +99,11 @@ + { Internal } + procedure BackgroundChanged(Sender: TObject); + procedure ChangeDockList(const Insert: Boolean; const Bar: TTBCustomDockableWindow); +- procedure ChangeWidthHeight(const NewWidth, NewHeight: Integer); + procedure CommitPositions; + procedure DrawNCArea(const DrawToDC: Boolean; const ADC: HDC; + const Clip: HRGN); + function GetDesignModeRowOf(const XY: Integer): Integer; +- function HasVisibleToolbars: Boolean; + procedure RelayMsgToFloatingBars(var Message: TMessage); +- function ToolbarVisibleOnDock(const AToolbar: TTBCustomDockableWindow): Boolean; + procedure ToolbarVisibilityChanged(const Bar: TTBCustomDockableWindow; + const ForceRemove: Boolean); + +@@ -128,21 +122,30 @@ + procedure WMPrintClient(var Message: TMessage); message WM_PRINTCLIENT; + procedure WMSysCommand(var Message: TWMSysCommand); message WM_SYSCOMMAND; + protected ++ DockList: TList; { List of the toolbars docked, and those floating and have LastDock ++ pointing to the dock. Items are casted in TTBCustomDockableWindow's. } ++ DockVisibleList: TList; { Similar to DockList, but lists only docked and visible toolbars } ++ function Accepts(ADockableWindow: TTBCustomDockableWindow): Boolean; virtual; + procedure AlignControls(AControl: TControl; var Rect: TRect); override; ++ procedure ChangeWidthHeight(const NewWidth, NewHeight: Integer); + procedure DrawBackground(DC: HDC; const DrawRect: TRect); virtual; + function GetPalette: HPALETTE; override; ++ function HasVisibleToolbars: Boolean; + procedure InvalidateBackgrounds; + procedure Loaded; override; + procedure Notification(AComponent: TComponent; Operation: TOperation); override; + procedure SetParent(AParent: TWinControl); override; ++ function ToolbarVisibleOnDock(const AToolbar: TTBCustomDockableWindow): Boolean; + procedure Paint; override; + function UsingBackground: Boolean; virtual; ++ property ArrangeToolbarsNeeded: Boolean read FArrangeToolbarsNeeded write FArrangeToolbarsNeeded; ++ property DisableArrangeToolbars: Integer read FDisableArrangeToolbars write FDisableArrangeToolbars; + public + constructor Create(AOwner: TComponent); override; + procedure CreateParams(var Params: TCreateParams); override; + destructor Destroy; override; + +- procedure ArrangeToolbars; ++ procedure ArrangeToolbars; virtual; + procedure BeginUpdate; + procedure EndUpdate; + function GetCurrentRowSize(const Row: Integer; var AFullSize: Boolean): Integer; +@@ -266,6 +269,7 @@ + private + { Property variables } + FAutoResize: Boolean; ++ FDblClickUndock: Boolean; + FDockPos, FDockRow, FEffectiveDockPos, FEffectiveDockRow: Integer; + FDocked: Boolean; + FCurrentDock, FDefaultDock, FLastDock: TTBDock; +@@ -427,6 +431,7 @@ + { Methods accessible to descendants } + procedure Arrange; + function CalcNCSizes: TPoint; virtual; ++ function CanDockTo(ADock: TTBDock): Boolean; virtual; + procedure ChangeSize(AWidth, AHeight: Integer); + function ChildControlTransparent(Ctl: TControl): Boolean; dynamic; + procedure Close; +@@ -451,7 +456,10 @@ + procedure ResizeTrack(var Rect: TRect; const OrigRect: TRect); dynamic; + procedure ResizeTrackAccept; dynamic; + procedure SizeChanging(const AWidth, AHeight: Integer); virtual; ++ property EffectiveDockPosAccess: Integer read FEffectiveDockPos write FEffectiveDockPos; ++ property EffectiveDockRowAccess: Integer read FEffectiveDockRow write FEffectiveDockRow; + public ++ property DblClickUndock: Boolean read FDblClickUndock write FDblClickUndock default True; + property Docked: Boolean read FDocked; + property CurrentDock: TTBDock read FCurrentDock write SetCurrentDock stored False; + property CurrentSize: Integer read FCurrentSize write FCurrentSize; +@@ -1000,6 +1008,11 @@ + end; + end; + ++function TTBDock.Accepts(ADockableWindow: TTBCustomDockableWindow): Boolean; ++begin ++ Result := AllowDrag; ++end; ++ + procedure TTBDock.AlignControls(AControl: TControl; var Rect: TRect); + begin + ArrangeToolbars; +@@ -2494,6 +2507,7 @@ + FActivateParent := True; + FBorderStyle := bsSingle; + FCloseButton := True; ++ FDblClickUndock := True; + FDockableTo := [dpTop, dpBottom, dpLeft, dpRight]; + FDockableWindowStyles := [tbdsResizeEightCorner, tbdsResizeClipCursor]; + FDockPos := -1; +@@ -2911,6 +2925,11 @@ + RemoveFromList(FDockForms, Form); + end; + ++function TTBCustomDockableWindow.CanDockTo(ADock: TTBDock): Boolean; ++begin ++ Result := ADock.Position in DockableTo; ++end; ++ + function TTBCustomDockableWindow.IsAutoResized: Boolean; + begin + Result := AutoResize or Assigned(CurrentDock) or Floating; +@@ -3879,11 +3898,6 @@ + + procedure BuildDockList; + +- function AcceptableDock(const D: TTBDock): Boolean; +- begin +- Result := D.FAllowDrag and (D.Position in DockableTo); +- end; +- + procedure Recurse(const ParentCtl: TWinControl); + var + D: TTBDockPosition; +@@ -3900,7 +3914,7 @@ + if (Controls[I] is TWinControl) and not(Controls[I] is TTBDock) then + Recurse(TWinControl(Controls[I])); + end; +- if (ParentCtl is TTBDock) and AcceptableDock(TTBDock(ParentCtl)) and ++ if (ParentCtl is TTBDock) and TTBDock(ParentCtl).Accepts(Self) and CanDockTo(TTBDock(ParentCtl)) and + (DockList.IndexOf(ParentCtl) = -1) then + DockList.Add(ParentCtl); + end; +@@ -3912,7 +3926,7 @@ + begin + { Manually add CurrentDock to the DockList first so that it gets priority + over other docks } +- if Assigned(CurrentDock) and AcceptableDock(CurrentDock) then ++ if Assigned(CurrentDock) and CurrentDock.Accepts(Self) and CanDockTo(CurrentDock) then + DockList.Add(CurrentDock); + ParentForm := TBGetToolWindowParentForm(Self); + DockFormsList := TList.Create; +@@ -4201,19 +4215,20 @@ + procedure TTBCustomDockableWindow.DoubleClick; + begin + if Docked then begin +- if DockMode = dmCanFloat then begin ++ if DblClickUndock and (DockMode = dmCanFloat) then begin + Floating := True; + MoveOnScreen(True); + end; + end +- else +- if Assigned(LastDock) then +- Parent := LastDock +- else +- if Assigned(DefaultDock) then begin +- FDockRow := ForceDockAtTopRow; +- FDockPos := ForceDockAtLeftPos; +- Parent := DefaultDock; ++ else if Floating then begin ++ if Assigned(LastDock) then ++ Parent := LastDock ++ else ++ if Assigned(DefaultDock) then begin ++ FDockRow := ForceDockAtTopRow; ++ FDockPos := ForceDockAtLeftPos; ++ Parent := DefaultDock; ++ end; + end; + end; + +Index: TB2DsgnItemEditor.pas +=================================================================== +RCS file: /data/cvs/tb2k/Source/TB2DsgnItemEditor.pas,v +retrieving revision 1.52 +diff -u -r1.52 TB2DsgnItemEditor.pas +--- TB2DsgnItemEditor.pas 26 Feb 2004 07:05:57 -0000 1.52 ++++ TB2DsgnItemEditor.pas 29 May 2004 22:19:14 -0000 +@@ -152,6 +152,12 @@ + procedure TBRegisterItemClass(AClass: TTBCustomItemClass; + const ACaption: String; ResInstance: HINST); + ++type ++ TTBDsgnEditorHook = procedure(Sender: TTBItemEditForm) of object; ++ ++procedure TBRegisterDsgnEditorHook(Hook: TTBDsgnEditorHook); ++procedure TBUnregisterDsgnEditorHook(Hook: TTBDsgnEditorHook); ++ + implementation + + {$R *.DFM} +@@ -179,6 +185,7 @@ + var + ItemClasses: TList; + ItemImageList: TImageList; ++ EditFormHooks: TList; + + {$IFNDEF JR_D6} + function CreateSelectionList: TDesignerSelectionList; +@@ -240,7 +247,18 @@ + const ACaption: String; ResInstance: HINST); + var + Info: PItemClassInfo; ++ I: Integer; + begin ++ if ItemClasses <> nil then ++ for I := ItemClasses.Count - 1 downto 0 do ++ begin ++ Info := ItemClasses[I]; ++ if Info.ItemClass = AClass then ++ begin ++ Dispose(Info); ++ ItemClasses.Delete(I); ++ end; ++ end; + New(Info); + Info.ItemClass := AClass; + Info.Caption := ACaption; +@@ -357,6 +375,11 @@ + Item.OnClick := MoreItemClick; + MoreMenu.Add(Item); + end; ++ { Run the hooks } ++ ++ if EditFormHooks <> nil then ++ for I := 0 to EditFormHooks.Count - 1 do ++ TTBDsgnEditorHook(EditFormHooks[I]^)(Self); + end; + + destructor TTBItemEditForm.Destroy; +@@ -1332,14 +1355,44 @@ + Result := '(TB2000 Items)'; + end; + ++ ++procedure TBRegisterDsgnEditorHook(Hook: TTBDsgnEditorHook); ++var ++ H: ^TTBDsgnEditorHook; ++begin ++ New(H); ++ H^ := Hook; ++ EditFormHooks.Add(H); ++end; ++ ++procedure TBUnregisterDsgnEditorHook(Hook: TTBDsgnEditorHook); ++var ++ H: ^TTBDsgnEditorHook; ++ I: Integer; ++begin ++ for I := EditFormHooks.Count - 1 downto 0 do ++ begin ++ H := EditFormHooks[I]; ++ if (TMethod(H^).Code = TMethod(Hook).Code) and ++ (TMethod(H^).Data = TMethod(Hook).Data) then ++ begin ++ Dispose(H); ++ EditFormHooks.Delete(I); ++// Break; ++ end; ++ end; ++end; ++ + initialization + ItemImageList := TImageList.Create(nil); + ItemImageList.Handle := ImageList_LoadImage(HInstance, 'TB2_DSGNEDITORIMAGES', + 16, 0, clFuchsia, IMAGE_BITMAP, 0); + ItemClasses := TList.Create; ++ EditFormHooks := TList.Create; + AddModuleUnloadProc(UnregisterModuleItemClasses); + finalization + RemoveModuleUnloadProc(UnregisterModuleItemClasses); + FreeItemClasses; + FreeAndNil(ItemImageList); ++ FreeAndNil(EditFormHooks); + end. +Index: TB2ExtItems.pas +=================================================================== +RCS file: /data/cvs/tb2k/Source/TB2ExtItems.pas,v +retrieving revision 1.56 +diff -u -r1.56 TB2ExtItems.pas +--- TB2ExtItems.pas 26 Feb 2004 07:05:57 -0000 1.56 ++++ TB2ExtItems.pas 29 May 2004 22:19:14 -0000 +@@ -43,6 +43,11 @@ + EditItemDefaultEditOptions = []; + EditItemDefaultEditWidth = 64; + ++{ Change reasons for TTBEditItem.Text property } ++ tcrSetProperty = 0; // direct assignment to TTBEditItem.Text property ++ tcrActionLink = 1; // change comes from an action link ++ tcrEditControl = 2; // change is caused by typing in edit area ++ + type + TTBEditItem = class; + TTBEditItemViewer = class; +@@ -96,6 +101,7 @@ + FEditCaption: String; + FEditOptions: TTBEditItemOptions; + FEditWidth: Integer; ++ FExtendedAccept: Boolean; + FMaxLength: Integer; + FOnAcceptText: TTBAcceptTextEvent; + FOnBeginEdit: TTBBeginEditEvent; +@@ -112,10 +118,15 @@ + procedure SetText(Value: String); + protected + procedure ActionChange(Sender: TObject; CheckDefaults: Boolean); override; ++ function DoAcceptText(var NewText: string): Boolean; virtual; + procedure DoBeginEdit(Viewer: TTBEditItemViewer); virtual; ++ procedure DoTextChanging(const OldText: String; var NewText: String; Reason: Integer); virtual; ++ procedure DoTextChanged(Reason: Integer); virtual; + function GetActionLinkClass: TTBCustomItemActionLinkClass; override; + function GetItemViewerClass(AView: TTBView): TTBItemViewerClass; override; + function NeedToRecreateViewer(AViewer: TTBItemViewer): Boolean; override; ++ property ExtendedAccept: Boolean read FExtendedAccept write FExtendedAccept default False; ++ procedure SetTextEx(Value: String; Reason: Integer); + public + constructor Create(AOwner: TComponent); override; + procedure Clear; +@@ -146,6 +157,8 @@ + property OnSelect; + end; + ++ TEditClass = class of TEdit; ++ + TTBEditItemViewer = class(TTBItemViewer) + private + FEditControl: TEdit; +@@ -162,6 +175,7 @@ + function GetAccValue(var Value: WideString): Boolean; override; + function GetCaptionText: String; override; + procedure GetCursor(const Pt: TPoint; var ACursor: HCURSOR); override; ++ function GetEditControlClass: TEditClass; virtual; + procedure GetEditRect(var R: TRect); virtual; + procedure MouseDown(Shift: TShiftState; X, Y: Integer; + var MouseDownOnMenu: Boolean); override; +@@ -365,7 +379,7 @@ + + procedure TTBEditItemActionLink.SetText(const Value: String); + begin +- if IsTextLinked then TTBEditItem(FClient).Text := Value; ++ if IsTextLinked then TTBEditItem(FClient).SetTextEx(Value , tcrActionLink); + end; + + +@@ -389,7 +403,7 @@ + if not CheckDefaults or (Self.EditOptions = []) then + Self.EditOptions := EditOptions; + if not CheckDefaults or (Self.Text = '') then +- Self.Text := Text; ++ Self.SetTextEx(Text, tcrActionLink); + if not CheckDefaults or not Assigned(Self.OnAcceptText) then + Self.OnAcceptText := OnAcceptText; + end; +@@ -496,15 +510,41 @@ + end; + end; + +-procedure TTBEditItem.SetText(Value: String); ++function TTBEditItem.DoAcceptText(var NewText: string): Boolean; ++begin ++ Result := True; ++ if Assigned(FOnAcceptText) then FOnAcceptText(Self, NewText, Result); ++end; ++ ++procedure TTBEditItem.DoTextChanging(const OldText: String; var NewText: String; Reason: Integer); + begin + case FCharCase of +- ecUpperCase: Value := AnsiUpperCase(Value); +- ecLowerCase: Value := AnsiLowerCase(Value); ++ ecUpperCase: NewText := AnsiUpperCase(NewText); ++ ecLowerCase: NewText := AnsiLowerCase(NewText); ++ end; ++end; ++ ++procedure TTBEditItem.DoTextChanged(Reason: Integer); ++begin ++end; ++ ++procedure TTBEditItem.SetText(Value: String); ++begin ++ DoTextChanging(FText, Value, tcrSetProperty); ++ if FText <> Value then begin ++ FText := Value; ++ Change(False); ++ DoTextChanged(tcrSetProperty); + end; ++end; ++ ++procedure TTBEditItem.SetTextEx(Value: String; Reason: Integer); ++begin ++ DoTextChanging(FText, Value, Reason); + if FText <> Value then begin + FText := Value; + Change(False); ++ DoTextChanged(Reason); + end; + end; + +@@ -518,14 +558,9 @@ + procedure AcceptText; + var + S: String; +- Accept: Boolean; + begin + S := FEditControl.Text; +- Accept := True; +- if Assigned(Item.FOnAcceptText) then +- Item.FOnAcceptText(Self, S, Accept); +- if Accept then +- Item.Text := S; ++ if Item.DoAcceptText(S) then Item.SetTextEx(S, tcrEditControl); + end; + + begin +@@ -552,6 +587,11 @@ + TEditAccess(FEditControl).WndProc(Message); + end; + ++function TTBEditItemViewer.GetEditControlClass: TEditClass; ++begin ++ Result := TEdit; ++end; ++ + procedure TTBEditItemViewer.GetEditRect(var R: TRect); + var + Item: TTBEditItem; +@@ -771,6 +811,7 @@ + Item: TTBEditItem; + R: TRect; + ActiveWnd, FocusWnd: HWND; ++ S: string; + begin + Item := TTBEditItem(Self.Item); + GetEditRect(R); +@@ -784,8 +825,8 @@ + + { Create the edit control } + InflateRect(R, -3, -3); +- //View.FreeNotification(Self); +- FEditControl := TEdit.Create(nil); ++ //View.FreeNotification (Self); ++ FEditControl := GetEditControlClass.Create(nil); + try + FEditControl.Name := Format('%s_edit_control_%p', [ClassName, + Pointer(FEditControl)]); +@@ -812,9 +853,14 @@ + FEditControlStatus := [ecsContinueLoop]; + ControlMessageLoop; + finally ++ S := FEditControl.Text; + FreeAndNil(FEditControl); + end; + ++ with TTBEditItem(Item) do ++ if (FEditControlStatus = [ecsContinueLoop]) and ExtendedAccept then ++ if DoAcceptText(S) then SetTextEx(S, tcrEditControl); ++ + { ensure the area underneath the edit control is repainted immediately } + View.Window.Update; + { If app is still active, set focus to previous control and restore capture +Index: TB2Item.pas +=================================================================== +RCS file: /data/cvs/tb2k/Source/TB2Item.pas,v +retrieving revision 1.258 +diff -u -r1.258 TB2Item.pas +--- TB2Item.pas 26 Feb 2004 07:05:57 -0000 1.258 ++++ TB2Item.pas 29 May 2004 22:19:15 -0000 +@@ -1,5 +1,5 @@ + unit TB2Item; +- ++ + { + Toolbar2000 + Copyright (C) 1998-2004 by Jordan Russell +@@ -23,7 +23,7 @@ + GPL. If you do not delete the provisions above, a recipient may use your + version of this file under either the "Toolbar2000 License" or the GPL. + +- $jrsoftware: tb2k/Source/TB2Item.pas,v 1.258 2004/02/26 07:05:57 jr Exp $ ++ $jrsoftware: tb2k/Source/TB2Item.pas,v 1.259 2004/05/05 08:43:18 jr Exp $ + } + + interface +@@ -41,6 +41,14 @@ + Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, + StdCtrls, CommCtrl, Menus, ActnList, ImgList, TB2Anim; + ++const ++ WM_TB2K_POPUPSHOWING = WM_USER + 554; ++ ++ { Parameter in LParam of WM_TB2K_POPUPSHOWING } ++ TPS_ANIMSTART = 1; // animation query: if Result <> 0, do not animate! ++ TPS_ANIMFINISHED = 2; // only fired when animation thread is done ++ TPS_NOANIM = 3; // fired when animation is done, or if showing with no animation ++ + type + TTBCustomItem = class; + TTBCustomItemClass = class of TTBCustomItem; +@@ -82,7 +90,7 @@ + TTBItemStyle = set of (tbisSubmenu, tbisSelectable, tbisSeparator, + tbisEmbeddedGroup, tbisClicksTransparent, tbisCombo, tbisNoAutoOpen, + tbisSubitemsEditable, tbisNoLineBreak, tbisRightAlign, tbisDontSelectFirst, +- tbisRedrawOnSelChange, tbisRedrawOnMouseOverChange); ++ tbisRedrawOnSelChange, tbisRedrawOnMouseOverChange, tbisStretch); + TTBPopupAlignment = (tbpaLeft, tbpaRight, tbpaCenter); + TTBPopupEvent = procedure(Sender: TTBCustomItem; FromLink: Boolean) of object; + TTBSelectEvent = procedure(Sender: TTBCustomItem; Viewer: TTBItemViewer; +@@ -97,6 +105,18 @@ + {$IFNDEF JR_D5} + TImageIndex = type Integer; + {$ENDIF} ++ TTBPopupPositionRec = record ++ PositionAsSubmenu: Boolean; ++ Alignment: TTBPopupAlignment; ++ Opposite: Boolean; ++ MonitorRect: TRect; ++ ParentItemRect: TRect; ++ NCSizeX: Integer; ++ NCSizeY: Integer; ++ X, Y, W, H: Integer; ++ AnimDir: TTBAnimationDirection; ++ PlaySound: Boolean; ++ end; + + TTBCustomItem = class(TComponent) + private +@@ -186,6 +206,8 @@ + function GetChevronParentView: TTBView; virtual; + procedure GetChildren(Proc: TGetChildProc; Root: TComponent); override; + function GetItemViewerClass(AView: TTBView): TTBItemViewerClass; virtual; ++ procedure GetPopupPosition(ParentView: TTBView; ++ PopupWindow: TTBPopupWindow; var PopupPositionRec: TTBPopupPositionRec); virtual; + function GetPopupWindowClass: TTBPopupWindowClass; virtual; + procedure IndexError; + procedure Loaded; override; +@@ -315,7 +337,7 @@ + function DoExecute: Boolean; virtual; + procedure DrawItemCaption(const Canvas: TCanvas; ARect: TRect; + const ACaption: String; ADrawDisabledShadow: Boolean; AFormat: UINT); virtual; +- procedure Entering; virtual; ++ procedure Entering(OldSelected: TTBItemViewer); virtual; + function GetAccRole: Integer; virtual; + function GetAccValue(var Value: WideString): Boolean; virtual; + function GetCaptionText: String; virtual; +@@ -323,7 +345,7 @@ + function GetImageList: TCustomImageList; + function ImageShown: Boolean; + function IsRotated: Boolean; +- function IsToolbarSize: Boolean; ++ function IsToolbarSize: Boolean; virtual; + function IsPtInButtonPart(X, Y: Integer): Boolean; virtual; + procedure KeyDown(var Key: Word; Shift: TShiftState); virtual; + procedure Leaving; virtual; +@@ -352,7 +374,7 @@ + function GetAccObject: IDispatch; + function GetHintText: String; + function IsAccessible: Boolean; +- function IsToolbarStyle: Boolean; ++ function IsToolbarStyle: Boolean; virtual; + function ScreenToClient(const P: TPoint): TPoint; + end; + PTBItemViewerArray = ^TTBItemViewerArray; +@@ -450,6 +472,8 @@ + procedure KeyDown(var Key: Word; Shift: TShiftState); virtual; + procedure Notification(AComponent: TComponent; Operation: TOperation); override; + procedure SetAccelsVisibility(AShowAccels: Boolean); ++ procedure SetState(AState: TTBViewState); ++ property DoneActionData: TTBDoneActionData read FDoneActionData write FDoneActionData; + public + constructor CreateView(AOwner: TComponent; AParentView: TTBView; + AParentItem: TTBCustomItem; AWindow: TWinControl; +@@ -653,10 +677,12 @@ + procedure WMPrint(var Message: TMessage); message WM_PRINT; + procedure WMPrintClient(var Message: TMessage); message WM_PRINTCLIENT; + procedure WMTB2kStepAnimation(var Message: TMessage); message WM_TB2K_STEPANIMATION; ++ procedure WMTB2kAnimationEnded (var Message: TMessage); message WM_TB2K_ANIMATIONENDED; + protected + procedure CreateParams(var Params: TCreateParams); override; + procedure CreateWnd; override; + procedure DestroyWindowHandle; override; ++ function GetNCSize: TPoint; dynamic; + function GetViewClass: TTBViewClass; dynamic; + procedure Paint; override; + procedure PaintScrollArrows; virtual; +@@ -800,6 +826,21 @@ + var + ToolbarFont: TFont; + ++type ++ TTBModalHandler = class ++ private ++ FCreatedWnd: Boolean; ++ FInited: Boolean; ++ FWnd: HWND; ++ public ++ constructor Create(AExistingWnd: HWND); ++ destructor Destroy; override; ++ procedure Loop(const RootView: TTBView; const AMouseDown, AExecuteSelected, ++ AFromMSAA, TrackRightButton: Boolean); ++ property Wnd: HWND read FWnd; ++ end; ++ ++procedure ProcessDoneAction(const DoneActionData: TTBDoneActionData); + + implementation + +@@ -815,19 +856,6 @@ + ClickList: TList; + + type +- TTBModalHandler = class +- private +- FCreatedWnd: Boolean; +- FInited: Boolean; +- FWnd: HWND; +- public +- constructor Create(AExistingWnd: HWND); +- destructor Destroy; override; +- procedure Loop(const RootView: TTBView; const AMouseDown, AExecuteSelected, +- AFromMSAA, TrackRightButton: Boolean); +- property Wnd: HWND read FWnd; +- end; +- + PItemChangedNotificationData = ^TItemChangedNotificationData; + TItemChangedNotificationData = record + Proc: TTBItemChangedProc; +@@ -1645,10 +1673,11 @@ + var + PlayedSound: Boolean = False; + +-function TTBCustomItem.CreatePopup(const ParentView: TTBView; +- const ParentViewer: TTBItemViewer; const PositionAsSubmenu, SelectFirstItem, +- Customizing: Boolean; const APopupPoint: TPoint; +- const Alignment: TTBPopupAlignment): TTBPopupWindow; ++procedure TTBCustomItem.GetPopupPosition(ParentView: TTBView; ++ PopupWindow: TTBPopupWindow; var PopupPositionRec: TTBPopupPositionRec); ++var ++ X2, Y2: Integer; ++ RepeatCalcX: Boolean; + + function CountObscured(X, Y, W, H: Integer): Integer; + var +@@ -1672,114 +1701,9 @@ + end; + end; + +-var +- EventItem, ParentItem: TTBCustomItem; +- Opposite: Boolean; +- ChevronParentView: TTBView; +- X, X2, Y, Y2, W, H: Integer; +- P: TPoint; +- RepeatCalcX: Boolean; +- ParentItemRect: TRect; +- MonitorRect: TRect; +- AnimDir: TTBAnimationDirection; + begin +- EventItem := ItemContainingItems(Self); +- if EventItem <> Self then +- EventItem.DoPopup(Self, True); +- DoPopup(Self, False); +- +- ChevronParentView := GetChevronParentView; +- if ChevronParentView = nil then +- ParentItem := Self +- else +- ParentItem := ChevronParentView.FParentItem; +- +- Opposite := Assigned(ParentView) and (vsOppositePopup in ParentView.FState); +- Result := GetPopupWindowClass.CreatePopupWindow(nil, ParentView, ParentItem, +- Customizing); +- try +- if Assigned(ChevronParentView) then begin +- ChevronParentView.FreeNotification(Result.View); +- Result.View.FChevronParentView := ChevronParentView; +- Result.View.FIsToolbar := True; +- Result.View.Style := Result.View.Style + +- (ChevronParentView.Style * [vsAlwaysShowHints]); +- Result.Color := clBtnFace; +- end; +- +- { Calculate ParentItemRect, and MonitorRect (the rectangle of the monitor +- that the popup window will be confined to) } +- if Assigned(ParentView) then begin +- ParentView.ValidatePositions; +- ParentItemRect := ParentViewer.BoundsRect; +- P := ParentView.FWindow.ClientToScreen(Point(0, 0)); +- OffsetRect(ParentItemRect, P.X, P.Y); +- if not IsRectEmpty(ParentView.FMonitorRect) then +- MonitorRect := ParentView.FMonitorRect +- else +- MonitorRect := GetRectOfMonitorContainingRect(ParentItemRect, False); +- end +- else begin +- ParentItemRect.TopLeft := APopupPoint; +- ParentItemRect.BottomRight := APopupPoint; +- MonitorRect := GetRectOfMonitorContainingPoint(APopupPoint, False); +- end; +- Result.View.FMonitorRect := MonitorRect; +- +- { Initialize item positions and size of the popup window } +- if ChevronParentView = nil then +- Result.View.FMaxHeight := (MonitorRect.Bottom - MonitorRect.Top) - +- (PopupMenuWindowNCSize * 2) +- else +- Result.View.WrapOffset := (MonitorRect.Right - MonitorRect.Left) - +- (PopupMenuWindowNCSize * 2); +- if SelectFirstItem then +- Result.View.Selected := Result.View.FirstSelectable; +- Result.View.UpdatePositions; +- W := Result.Width; +- H := Result.Height; +- +- { Calculate initial X,Y position of the popup window } +- if Assigned(ParentView) then begin +- if not PositionAsSubmenu then begin +- if ChevronParentView = nil then begin +- if (ParentView = nil) or (ParentView.FOrientation <> tbvoVertical) then begin +- if GetSystemMetrics(SM_MENUDROPALIGNMENT) = 0 then +- X := ParentItemRect.Left +- else +- X := ParentItemRect.Right - W; +- Y := ParentItemRect.Bottom; +- end +- else begin +- X := ParentItemRect.Left - W; +- Y := ParentItemRect.Top; +- end; +- end +- else begin +- if ChevronParentView.FOrientation <> tbvoVertical then begin +- X := ParentItemRect.Right - W; +- Y := ParentItemRect.Bottom; +- end +- else begin +- X := ParentItemRect.Left - W; +- Y := ParentItemRect.Top; +- end; +- end; +- end +- else begin +- X := ParentItemRect.Right - PopupMenuWindowNCSize; +- Y := ParentItemRect.Top - PopupMenuWindowNCSize; +- end; +- end +- else begin +- X := APopupPoint.X; +- Y := APopupPoint.Y; +- case Alignment of +- tbpaRight: Dec(X, W); +- tbpaCenter: Dec(X, W div 2); +- end; +- end; +- ++ with PopupPositionRec do ++ begin + { Adjust the Y position of the popup window } + { If the window is going off the bottom of the monitor, try placing it + above the parent item } +@@ -1788,7 +1712,7 @@ + if not PositionAsSubmenu then + Y2 := ParentItemRect.Top + else +- Y2 := ParentItemRect.Bottom + PopupMenuWindowNCSize; ++ Y2 := ParentItemRect.Bottom + NCSizeY; + Dec(Y2, H); + { Only place it above the parent item if it isn't going to go off the + top of the monitor } +@@ -1864,17 +1788,17 @@ + X2 := X; + if Opposite or (X2 + W > MonitorRect.Right) then begin + if Assigned(ParentView) then +- X2 := ParentItemRect.Left + PopupMenuWindowNCSize; ++ X2 := ParentItemRect.Left + NCSizeX; + Dec(X2, W); + if not Opposite then +- Include(Result.View.FState, vsOppositePopup) ++ Include(PopupWindow.View.FState, vsOppositePopup) + else begin + if X2 < MonitorRect.Left then begin + Opposite := False; + RepeatCalcX := True; + end + else +- Include(Result.View.FState, vsOppositePopup); ++ Include(PopupWindow.View.FState, vsOppositePopup); + end; + end; + until not RepeatCalcX; +@@ -1901,8 +1825,141 @@ + else + Include(AnimDir, tbadLeft); + end; +- Result.FAnimationDirection := AnimDir; ++ end; ++end; ++ ++function TTBCustomItem.CreatePopup(const ParentView: TTBView; ++ const ParentViewer: TTBItemViewer; const PositionAsSubmenu, SelectFirstItem, ++ Customizing: Boolean; const APopupPoint: TPoint; ++ const Alignment: TTBPopupAlignment): TTBPopupWindow; ++var ++ EventItem, ParentItem: TTBCustomItem; ++ Opposite: Boolean; ++ ChevronParentView: TTBView; ++ X, Y, W, H: Integer; ++ P: TPoint; ++ ParentItemRect: TRect; ++ MonitorRect: TRect; ++ PopupRec: TTBPopupPositionRec; ++ NCSize: TPoint; ++begin ++ EventItem := ItemContainingItems(Self); ++ if EventItem <> Self then ++ EventItem.DoPopup(Self, True); ++ DoPopup(Self, False); ++ ++ ChevronParentView := GetChevronParentView; ++ if ChevronParentView = nil then ++ ParentItem := Self ++ else ++ ParentItem := ChevronParentView.FParentItem; + ++ Opposite := Assigned(ParentView) and (vsOppositePopup in ParentView.FState); ++ Result := GetPopupWindowClass.CreatePopupWindow(nil, ParentView, ParentItem, ++ Customizing); ++ try ++ if Assigned(ChevronParentView) then begin ++ ChevronParentView.FreeNotification(Result.View); ++ Result.View.FChevronParentView := ChevronParentView; ++ Result.View.FIsToolbar := True; ++ Result.View.Style := Result.View.Style + ++ (ChevronParentView.Style * [vsAlwaysShowHints]); ++ Result.Color := clBtnFace; ++ end; ++ ++ { Calculate ParentItemRect, and MonitorRect (the rectangle of the monitor ++ that the popup window will be confined to) } ++ if Assigned(ParentView) then begin ++ ParentView.ValidatePositions; ++ ParentItemRect := ParentViewer.BoundsRect; ++ P := ParentView.FWindow.ClientToScreen(Point(0, 0)); ++ OffsetRect(ParentItemRect, P.X, P.Y); ++ if not IsRectEmpty(ParentView.FMonitorRect) then ++ MonitorRect := ParentView.FMonitorRect ++ else ++ MonitorRect := GetRectOfMonitorContainingRect(ParentItemRect, False); ++ end ++ else begin ++ ParentItemRect.TopLeft := APopupPoint; ++ ParentItemRect.BottomRight := APopupPoint; ++ MonitorRect := GetRectOfMonitorContainingPoint(APopupPoint, False); ++ end; ++ Result.View.FMonitorRect := MonitorRect; ++ ++ { Initialize item positions and size of the popup window } ++ NCSize := Result.GetNCSize; ++ if ChevronParentView = nil then ++ Result.View.FMaxHeight := (MonitorRect.Bottom - MonitorRect.Top) - ++ (NCSize.Y * 2) ++ else ++ Result.View.WrapOffset := (MonitorRect.Right - MonitorRect.Left) - ++ (NCSize.X * 2); ++ if SelectFirstItem then ++ Result.View.Selected := Result.View.FirstSelectable; ++ Result.View.UpdatePositions; ++ W := Result.Width; ++ H := Result.Height; ++ ++ { Calculate initial X,Y position of the popup window } ++ if Assigned(ParentView) then begin ++ if not PositionAsSubmenu then begin ++ if ChevronParentView = nil then begin ++ if (ParentView = nil) or (ParentView.FOrientation <> tbvoVertical) then begin ++ if GetSystemMetrics(SM_MENUDROPALIGNMENT) = 0 then ++ X := ParentItemRect.Left ++ else ++ X := ParentItemRect.Right - W; ++ Y := ParentItemRect.Bottom; ++ end ++ else begin ++ X := ParentItemRect.Left - W; ++ Y := ParentItemRect.Top; ++ end; ++ end ++ else begin ++ if ChevronParentView.FOrientation <> tbvoVertical then begin ++ X := ParentItemRect.Right - W; ++ Y := ParentItemRect.Bottom; ++ end ++ else begin ++ X := ParentItemRect.Left - W; ++ Y := ParentItemRect.Top; ++ end; ++ end; ++ end ++ else begin ++ X := ParentItemRect.Right - NCSize.X; ++ Y := ParentItemRect.Top - NCSize.Y; ++ end; ++ end ++ else begin ++ X := APopupPoint.X; ++ Y := APopupPoint.Y; ++ case Alignment of ++ tbpaRight: Dec(X, W); ++ tbpaCenter: Dec(X, W div 2); ++ end; ++ end; ++ ++ PopupRec.PositionAsSubmenu := PositionAsSubmenu; ++ PopupRec.Alignment := Alignment; ++ PopupRec.Opposite := Opposite; ++ PopupRec.MonitorRect := MonitorRect; ++ PopupRec.ParentItemRect := ParentItemRect; ++ PopupRec.NCSizeX := NCSize.X; ++ PopupRec.NCSizeY := NCSize.Y; ++ PopupRec.X := X; ++ PopupRec.Y := Y; ++ PopupRec.W := W; ++ PopupRec.H := H; ++ PopupRec.AnimDir := []; ++ PopupRec.PlaySound := True; ++ GetPopupPosition(ParentView, Result, PopupRec); ++ X := PopupRec.X; ++ Y := PopupRec.Y; ++ W := PopupRec.W; ++ H := PopupRec.H; ++ Result.FAnimationDirection := PopupRec.AnimDir; + Result.SetBounds(X, Y, W, H); + if Assigned(ParentView) then begin + Result.FreeNotification(ParentView); +@@ -1916,7 +1973,7 @@ + end; + end; + Include(Result.View.FState, vsDrawInOrder); +- if not NeedToPlaySound('MenuPopup') then begin ++ if not PopupRec.PlaySound or not NeedToPlaySound('MenuPopup') then begin + { Don't call PlaySound if we don't have to } + Result.Visible := True; + end +@@ -3224,7 +3281,7 @@ + View.Invalidate(Self); + end; + +-procedure TTBItemViewer.Entering; ++procedure TTBItemViewer.Entering(OldSelected: TTBItemViewer); + begin + if Assigned(Item.FOnSelect) then + Item.FOnSelect(Item, Self, True); +@@ -4015,7 +4072,7 @@ + if Assigned(Value) then begin + if tbisRedrawOnSelChange in Value.Item.ItemStyle then + Invalidate(Value); +- Value.Entering; ++ Value.Entering(OldSelected); + end; + NotifyFocusEvent; + +@@ -4308,7 +4365,7 @@ + HighestHeightOnLine := TotalSize.Y; + end; + { Make separators on toolbars as tall/wide as the tallest/widest item } +- if tbisSeparator in Item.ItemStyle then begin ++ if [tbisSeparator, tbisStretch] * Item.ItemStyle <> [] then begin + if AOrientation <> tbvoVertical then + Pos.BoundsRect.Bottom := Pos.BoundsRect.Top + HighestHeightOnLine + else +@@ -5576,12 +5633,30 @@ + Result := GetRootView.FCaptureWnd; + end; + ++procedure TTBView.SetState(AState: TTBViewState); ++begin ++ FState := AState; ++end; ++ + + { TTBModalHandler } + ++const ++ LSFW_LOCK = 1; ++ LSFW_UNLOCK = 2; ++ ++var ++ LockSetForegroundWindowInited: BOOL; ++ LockSetForegroundWindow: function(uLockCode: UINT): BOOL; stdcall; ++ + constructor TTBModalHandler.Create(AExistingWnd: HWND); + begin + inherited Create; ++ if not LockSetForegroundWindowInited then begin ++ LockSetForegroundWindow := GetProcAddress(GetModuleHandle(user32), ++ 'LockSetForegroundWindow'); ++ LockSetForegroundWindowInited := True; ++ end; + LastPos := SmallPointToPoint(TSmallPoint(GetMessagePos())); + if AExistingWnd <> 0 then + FWnd := AExistingWnd +@@ -5589,6 +5664,13 @@ + FWnd := {$IFDEF JR_D6}Classes.{$ENDIF} AllocateHWnd(nil); + FCreatedWnd := True; + end; ++ if Assigned(LockSetForegroundWindow) then begin ++ { Like standard menus, don't allow other apps to steal the focus during ++ our modal loop. This also prevents us from losing activation when ++ "active window tracking" is enabled and the user moves the mouse over ++ another application's window. } ++ LockSetForegroundWindow(LSFW_LOCK); ++ end; + SetCapture(FWnd); + SetCursor(LoadCursor(0, IDC_ARROW)); + CallNotifyWinEvent(EVENT_SYSTEM_MENUSTART, FWnd, OBJID_CLIENT, CHILDID_SELF); +@@ -5597,6 +5679,8 @@ + + destructor TTBModalHandler.Destroy; + begin ++ if Assigned(LockSetForegroundWindow) then ++ LockSetForegroundWindow(LSFW_UNLOCK); + if FWnd <> 0 then begin + if GetCapture = FWnd then + ReleaseCapture; +@@ -6021,9 +6105,10 @@ + + procedure TTBPopupView.AutoSize(AWidth, AHeight: Integer); + begin +- with FWindow do +- SetBounds(Left, Top, AWidth + (PopupMenuWindowNCSize * 2), +- AHeight + (PopupMenuWindowNCSize * 2)); ++ with TTBPopupWindow(FWindow) do ++ with GetNCSize do ++ SetBounds(Left, Top, AWidth + (X * 2), ++ AHeight + (Y * 2)); + end; + + function TTBPopupView.GetFont: TFont; +@@ -6100,6 +6185,12 @@ + inherited; + end; + ++function TTBPopupWindow.GetNCSize: TPoint; ++begin ++ Result.X := PopupMenuWindowNCSize; ++ Result.Y := PopupMenuWindowNCSize; ++end; ++ + function TTBPopupWindow.GetViewClass: TTBViewClass; + begin + Result := TTBPopupView; +@@ -6183,8 +6274,12 @@ + SystemParametersInfo(SPI_GETMENUANIMATION, 0, @Animate, 0) and Animate then begin + Blend := SystemParametersInfo(SPI_GETMENUFADE, 0, @Animate, 0) and Animate; + if Blend or (FAnimationDirection <> []) then begin +- TBStartAnimation(WindowHandle, 150, Blend, FAnimationDirection); +- Exit; ++ if SendMessage(WindowHandle, WM_TB2K_POPUPSHOWING, TPS_ANIMSTART, 0) = 0 then ++ begin ++ { Start animation only if WM_TB2K_POPUPSHOWING returns zero (or not handled) } ++ TBStartAnimation(WindowHandle, 150, Blend, FAnimationDirection); ++ Exit; ++ end; + end; + end; + {$ENDIF} +@@ -6197,6 +6292,12 @@ + TBEndAnimation(WindowHandle); + end; + SetWindowPos(WindowHandle, 0, 0, 0, 0, 0, ShowFlags[Showing]); ++ if Showing then SendNotifyMessage(WindowHandle, WM_TB2K_POPUPSHOWING, TPS_NOANIM, 0); ++end; ++ ++procedure TTBPopupWindow.WMTB2kAnimationEnded(var Message: TMessage); ++begin ++ SendNotifyMessage(WindowHandle, WM_TB2K_POPUPSHOWING, TPS_ANIMFINISHED, 0); + end; + + procedure TTBPopupWindow.WMTB2kStepAnimation(var Message: TMessage); +@@ -6266,8 +6367,8 @@ + + procedure TTBPopupWindow.WMNCCalcSize(var Message: TWMNCCalcSize); + begin +- InflateRect(Message.CalcSize_Params^.rgrc[0], +- -PopupMenuWindowNCSize, -PopupMenuWindowNCSize); ++ with GetNCSize do ++ InflateRect(Message.CalcSize_Params^.rgrc[0], -X, -Y); + inherited; + end; + +Index: TB2MRU.pas +=================================================================== +RCS file: /data/cvs/tb2k/Source/TB2MRU.pas,v +retrieving revision 1.22 +diff -u -r1.22 TB2MRU.pas +--- TB2MRU.pas 26 Feb 2004 07:05:58 -0000 1.22 ++++ TB2MRU.pas 29 May 2004 22:19:15 -0000 +@@ -53,6 +53,7 @@ + procedure SetMaxItems(Value: Integer); + protected + property Container: TTBCustomItem read FContainer; ++ function GetFirstKey: Integer; virtual; + function GetItemClass: TTBCustomItemClass; virtual; + procedure SetItemCaptions; virtual; + public +@@ -107,7 +108,7 @@ + procedure Delete(Index: Integer); override; + function Get(Index: Integer): String; override; + function GetCount: Integer; override; +- function IndexOf(const S: String): Integer; override; ++ function IndexOf(const S: String): Integer; override; + procedure Insert(Index: Integer; const S: String); override; + procedure Move(CurIndex, NewIndex: Integer); override; + procedure Put(Index: Integer; const S: String); override; +@@ -296,20 +297,21 @@ + + procedure TTBMRUList.SetItemCaptions; + var +- I, J: Integer; ++ I, J, N: Integer; + Key: Char; + S: String; + Buf: array[0..MAX_PATH-1] of Char; + begin + while FList.Count > FMaxItems do + FList.Delete(FList.Count-1); ++ N := GetFirstKey; + for I := 0 to FContainer.Count-1 do begin + Key := #0; +- if I < 9 then +- Key := Chr(Ord('1') + I) ++ if N < 9 then ++ Key := Chr(Ord('1') + N) + else begin + { No more numbers; try letters } +- J := I - 9; ++ J := N - 9; + if J < 26 then + Key := Chr(Ord('A') + J); + end; +@@ -321,6 +323,7 @@ + FContainer[I].Caption := Format('&%s %s', [Key, S]) + else + FContainer[I].Caption := S; ++ Inc(N); + end; + end; + +@@ -361,6 +364,11 @@ + Result := TTBCustomItem; + end; + ++function TTBMRUList.GetFirstKey: Integer; ++begin ++ Result := 0; ++end; ++ + + { TTBMRUListItem } + +Index: TB2Reg.pas +=================================================================== +RCS file: /data/cvs/tb2k/Source/TB2Reg.pas,v +retrieving revision 1.27 +diff -u -r1.27 TB2Reg.pas +--- TB2Reg.pas 26 Feb 2004 07:05:58 -0000 1.27 ++++ TB2Reg.pas 29 May 2004 22:19:15 -0000 +@@ -36,13 +36,6 @@ + TB2Toolbar, TB2ToolWindow, TB2Dock, TB2Item, TB2ExtItems, TB2MRU, TB2MDI, + TB2DsgnItemEditor; + +-procedure Register; +- +-implementation +- +-uses +- ImgEdit; +- + {$IFDEF JR_D5} + + { TTBImageIndexPropertyEditor } +@@ -67,6 +60,25 @@ + const ARect: TRect; ASelected: Boolean); {$IFNDEF JR_D6} override; {$ENDIF} + end; + ++{ TTBItemImageIndexPropertyEditor } ++ ++type ++ TTBItemImageIndexPropertyEditor = class(TTBImageIndexPropertyEditor) ++ public ++ function GetImageListAt (Index: Integer): TCustomImageList; override; ++ end; ++ ++{$ENDIF} ++ ++procedure Register; ++ ++implementation ++ ++uses ++ ImgEdit; ++ ++{$IFDEF JR_D5} ++ + function TTBImageIndexPropertyEditor.GetAttributes: TPropertyAttributes; + begin + Result := [paMultiSelect, paValueList, paRevertable]; +@@ -128,12 +140,6 @@ + + { TTBItemImageIndexPropertyEditor } + +-type +- TTBItemImageIndexPropertyEditor = class(TTBImageIndexPropertyEditor) +- protected +- function GetImageListAt(Index: Integer): TCustomImageList; override; +- end; +- + function TTBItemImageIndexPropertyEditor.GetImageListAt(Index: Integer): TCustomImageList; + var + C: TPersistent; +Index: TB2ToolWindow.pas +=================================================================== +RCS file: /data/cvs/tb2k/Source/TB2ToolWindow.pas,v +retrieving revision 1.17 +diff -u -r1.17 TB2ToolWindow.pas +--- TB2ToolWindow.pas 26 Feb 2004 07:05:58 -0000 1.17 ++++ TB2ToolWindow.pas 29 May 2004 22:19:15 -0000 +@@ -195,14 +195,24 @@ + begin + Result.X := FBarWidth; + Result.Y := FBarHeight; +- if Assigned(ADock) and (FullSize or Stretch) then begin +- { If docked and stretching, return the minimum size so that the toolbar +- can shrink below FBarWidth/FBarHeight } +- if not(ADock.Position in [dpLeft, dpRight]) then +- Result.X := FMinClientWidth +- else +- Result.Y := FMinClientHeight; +- end; ++ if Assigned(ADock) then ++ if FullSize then ++ begin ++ { If docked and full size, return the size corresponding to docked size } ++ if not(ADock.Position in [dpLeft, dpRight]) then ++ Result.X := ADock.ClientWidth - (Width - ClientWidth) ++ else ++ Result.Y := ADock.ClientHeight - (Height - ClientHeight); ++ end ++ else if Stretch then ++ begin ++ { If docked and stretching, return the minimum size so that the toolbar ++ can shrink below FBarWidth/FBarHeight } ++ if not(ADock.Position in [dpLeft, dpRight]) then ++ Result.X := FMinClientWidth ++ else ++ Result.Y := FMinClientHeight; ++ end; + end; + + procedure TTBToolWindow.GetBaseSize(var ASize: TPoint); +Index: TB2Toolbar.pas +=================================================================== +RCS file: /data/cvs/tb2k/Source/TB2Toolbar.pas,v +retrieving revision 1.99 +diff -u -r1.99 TB2Toolbar.pas +--- TB2Toolbar.pas 26 Feb 2004 07:05:58 -0000 1.99 ++++ TB2Toolbar.pas 29 May 2004 22:19:15 -0000 +@@ -23,7 +23,7 @@ + GPL. If you do not delete the provisions above, a recipient may use your + version of this file under either the "Toolbar2000 License" or the GPL. + +- $jrsoftware: tb2k/Source/TB2Toolbar.pas,v 1.99 2004/02/26 07:05:58 jr Exp $ ++ $jrsoftware: tb2k/Source/TB2Toolbar.pas,v 1.100 2004/04/30 21:06:18 jr Exp $ + } + + interface +@@ -327,7 +327,9 @@ + SetWindowsHookExW, Msg.wParam may either be an ANSI character or a + Unicode character, due to an apparent bug on these platforms. It is + an ANSI character when the message passes through a separate +- SetWindowsHookExA-installed WH_GETMESSAGE hook first. ++ SetWindowsHookExA-installed WH_GETMESSAGE hook first, and that hook ++ calls us via CallNextHookEx. Windows apparently "forgets" to convert ++ the character from ANSI back to Unicode in this case. + We can't convert the character code because there seems to be no way + to detect whether it is ANSI or Unicode. So we can't really do much + with Msg.wParam, apart from comparing it against character codes that +@@ -340,9 +342,12 @@ + { Redirect the message to the main form. + Note: Unfortunately, due to a bug in Windows NT 4.0 (and not + 2000/XP/9x/Me), modifications to the message don't take effect if +- another WH_GETMESSAGE hook has been installed above this one. I +- don't know of any clean workaround, other than to ensure other +- WH_GETMESSAGE hooks are installed *before* Toolbar2000's. } ++ another WH_GETMESSAGE hook has been installed above this one. ++ (The bug is that CallNextHookEx copies lParam^ to a local buffer, but ++ does not propogate the changes made by the hook back to lParam^ when ++ it returns.) I don't know of any clean workaround, other than to ++ ensure other WH_GETMESSAGE hooks are installed *before* ++ Toolbar2000's. } + Msg.hwnd := MainForm.Handle; + end; + end; +@@ -891,6 +896,11 @@ + Hint := Item.Hint + else + Hint := ''; ++ ++ with TTBItemViewerAccess(FView.Find(Item)) do ++ begin ++ MouseMove(X - BoundsRect.Left, Y - BoundsRect.Top); ++ end; + end + else + Hint := ''; + diff --git a/official/2.1.6+2.1.beta1/Source/_tb2k_2.1.6_patch.diff.txt b/official/2.1.6+2.1.beta1/Source/_tb2k_2.1.6_patch.diff.txt new file mode 100644 index 0000000..62b90df --- /dev/null +++ b/official/2.1.6+2.1.beta1/Source/_tb2k_2.1.6_patch.diff.txt @@ -0,0 +1,1748 @@ +--- TB2Common.pas 2005-06-29 15:10:10.000000000 +-0400 ++++ TB2Common.pas 2005-08-12 08:33:58.000000000 +-0400 +@@ -882,46 +882,88 @@ + Result := CreateFontIndirect(LogFont); + end; + + procedure DrawRotatedText(const DC: HDC; AText: String; const ARect: TRect; + const AFormat: Cardinal); + { Like DrawText, but draws the text at a 270 degree angle. +- The only format flag this function respects is DT_HIDEPREFIX. Text is always +- drawn centered. } ++ The format flag this function respects are ++ DT_NOPREFIX, DT_HIDEPREFIX, DT_CENTER, DT_END_ELLIPSIS, DT_NOCLIP } + var + RotatedFont, SaveFont: HFONT; + TextMetrics: TTextMetric; +- X, Y, P, I, SU, FU: Integer; ++ X, Y, P, I, SU, FU, W: Integer; + SaveAlign: UINT; + SavePen, Pen: HPEN; ++ Clip: Boolean; ++ ++ function GetSize(DC: HDC; const S: string): Integer; ++ var ++ Size: TSize; ++ begin ++ GetTextExtentPoint32(DC, PChar(S), Length(S), Size); ++ Result := Size.cx; ++ end; ++ + begin ++ if Length(AText) = 0 then Exit; ++ + RotatedFont := CreateRotatedFont(DC); + SaveFont := SelectObject(DC, RotatedFont); + + GetTextMetrics(DC, TextMetrics); + X := ARect.Left + ((ARect.Right - ARect.Left) - TextMetrics.tmHeight) div 2; +- Y := ARect.Top + ((ARect.Bottom - ARect.Top) - GetTextWidth(DC, AText, True)) div 2; ++ ++ Clip := (AFormat and DT_NOCLIP) <> DT_NOCLIP; + + { Find the index of the character that should be underlined. Delete '&' + characters from the string. Like DrawText, only the last prefixed character + will be underlined. } + P := 0; + I := 1; +- while I <= Length(AText) do begin +- if AText[I] in LeadBytes then +- Inc(I) +- else if AText[I] = '&' then begin +- Delete(AText, I, 1); +- { Note: PChar cast is so that if Delete deleted the last character in +- the string, we don't step past the end of the string (which would cause +- an AV if AText is now empty), but rather look at the null character +- and treat it as an accelerator key like DrawText. } +- if PChar(AText)[I-1] <> '&' then +- P := I; +- end; +- Inc(I); ++ if (AFormat and DT_NOPREFIX) <> DT_NOPREFIX then ++ while I <= Length(AText) do begin ++ if AText[I] in LeadBytes then ++ Inc(I) ++ else if AText[I] = '&' then begin ++ Delete(AText, I, 1); ++ { Note: PChar cast is so that if Delete deleted the last character in ++ the string, we don't step past the end of the string (which would cause ++ an AV if AText is now empty), but rather look at the null character ++ and treat it as an accelerator key like DrawText. } ++ if PChar(AText)[I-1] <> '&' then ++ P := I; ++ end; ++ Inc(I); ++ end; ++ ++ if (AFormat and DT_END_ELLIPSIS) = DT_END_ELLIPSIS then ++ begin ++ if (Length(AText) > 1) and (GetSize(DC, AText) > ARect.Bottom - ARect.Top) then ++ begin ++ W := ARect.Bottom - ARect.Top; ++ if W > 2 then ++ begin ++ Delete(AText, Length(AText), 1); ++ while (Length(AText) > 1) and (GetSize(DC, AText + '...') > W) do ++ Delete(AText, Length(AText), 1); ++ end ++ else AText := AText[1]; ++ if P > Length(AText) then P := 0; ++ AText := AText + '...'; ++ end; ++ end; ++ ++ if (AFormat and DT_CENTER) = DT_CENTER then ++ Y := ARect.Top + ((ARect.Bottom - ARect.Top) - GetSize(DC, AText)) div 2 ++ else ++ Y := ARect.Top; ++ ++ if Clip then ++ begin ++ SaveDC(DC); ++ with ARect do IntersectClipRect(DC, Left, Top, Right, Bottom); + end; + + SaveAlign := SetTextAlign(DC, TA_BOTTOM); + TextOut(DC, X, Y, PChar(AText), Length(AText)); + SetTextAlign(DC, SaveAlign); + { Underline } +@@ -933,12 +975,14 @@ + SavePen := SelectObject(DC, Pen); + MoveToEx(DC, X, Y + SU, nil); + LineTo(DC, X, Y + FU); + SelectObject(DC, SavePen); + DeleteObject(Pen); + end; ++ ++ if Clip then RestoreDC(DC, -1); + + SelectObject(DC, SaveFont); + DeleteObject(RotatedFont); + end; + + function NeedToPlaySound(const Alias: String): Boolean; +--- TB2Dock.pas 2005-07-15 14:35:04.000000000 +-0400 ++++ TB2Dock.pas 2005-08-11 10:16:22.000000000 +-0400 +@@ -76,15 +76,12 @@ + {$ENDIF} + + { Internal } + FDisableArrangeToolbars: Integer; { Increment to disable ArrangeToolbars } + FArrangeToolbarsNeeded: Boolean; + FNonClientWidth, FNonClientHeight: Integer; +- DockList: TList; { List of the toolbars docked, and those floating and have LastDock +- pointing to the dock. Items are casted in TTBCustomDockableWindow's. } +- DockVisibleList: TList; { Similar to DockList, but lists only docked and visible toolbars } + + { Property access methods } + //function GetVersion: TToolbar97Version; + procedure SetAllowDrag(Value: Boolean); + procedure SetBackground(Value: TTBBasicBackground); + procedure SetBackgroundOnToolbars(Value: Boolean); +@@ -96,20 +93,17 @@ + function GetToolbarCount: Integer; + function GetToolbars(Index: Integer): TTBCustomDockableWindow; + + { Internal } + procedure BackgroundChanged(Sender: TObject); + procedure ChangeDockList(const Insert: Boolean; const Bar: TTBCustomDockableWindow); +- procedure ChangeWidthHeight(const NewWidth, NewHeight: Integer); + procedure CommitPositions; + procedure DrawNCArea(const DrawToDC: Boolean; const ADC: HDC; + const Clip: HRGN); + function GetDesignModeRowOf(const XY: Integer): Integer; +- function HasVisibleToolbars: Boolean; + procedure RelayMsgToFloatingBars(var Message: TMessage); +- function ToolbarVisibleOnDock(const AToolbar: TTBCustomDockableWindow): Boolean; + procedure ToolbarVisibilityChanged(const Bar: TTBCustomDockableWindow; + const ForceRemove: Boolean); + + { Messages } + procedure CMDialogChar(var Message: TCMDialogChar); message CM_DIALOGCHAR; + procedure CMDialogKey(var Message: TCMDialogKey); message CM_DIALOGKEY; +@@ -122,27 +116,36 @@ + procedure WMNCCalcSize(var Message: TWMNCCalcSize); message WM_NCCALCSIZE; + procedure WMNCPaint(var Message: TMessage); message WM_NCPAINT; + procedure WMPrint(var Message: TMessage); message WM_PRINT; + procedure WMPrintClient(var Message: TMessage); message WM_PRINTCLIENT; + procedure WMSysCommand(var Message: TWMSysCommand); message WM_SYSCOMMAND; + protected ++ DockList: TList; { List of the toolbars docked, and those floating and have LastDock ++ pointing to the dock. Items are casted in TTBCustomDockableWindow's. } ++ DockVisibleList: TList; { Similar to DockList, but lists only docked and visible toolbars } ++ function Accepts(ADockableWindow: TTBCustomDockableWindow): Boolean; virtual; + procedure AlignControls(AControl: TControl; var Rect: TRect); override; ++ procedure ChangeWidthHeight(const NewWidth, NewHeight: Integer); + procedure DrawBackground(DC: HDC; const DrawRect: TRect); virtual; + function GetPalette: HPALETTE; override; ++ function HasVisibleToolbars: Boolean; + procedure InvalidateBackgrounds; + procedure Loaded; override; + procedure Notification(AComponent: TComponent; Operation: TOperation); override; + procedure SetParent(AParent: TWinControl); override; ++ function ToolbarVisibleOnDock(const AToolbar: TTBCustomDockableWindow): Boolean; + procedure Paint; override; + function UsingBackground: Boolean; virtual; ++ property ArrangeToolbarsNeeded: Boolean read FArrangeToolbarsNeeded write FArrangeToolbarsNeeded; ++ property DisableArrangeToolbars: Integer read FDisableArrangeToolbars write FDisableArrangeToolbars; + public + constructor Create(AOwner: TComponent); override; + procedure CreateParams(var Params: TCreateParams); override; + destructor Destroy; override; + +- procedure ArrangeToolbars; ++ procedure ArrangeToolbars; virtual; + procedure BeginUpdate; + procedure EndUpdate; + function GetCurrentRowSize(const Row: Integer; var AFullSize: Boolean): Integer; + function GetHighestRow(const HighestEffective: Boolean): Integer; + function GetMinRowSize(const Row: Integer; + const ExcludeControl: TTBCustomDockableWindow): Integer; +@@ -257,12 +260,13 @@ + TTBShrinkMode = (tbsmNone, tbsmWrap, tbsmChevron); + + TTBCustomDockableWindow = class(TCustomControl) + private + { Property variables } + FAutoResize: Boolean; ++ FDblClickUndock: Boolean; + FDockPos, FDockRow, FEffectiveDockPos, FEffectiveDockRow: Integer; + FDocked: Boolean; + FCurrentDock, FDefaultDock, FLastDock: TTBDock; + FCurrentSize: Integer; + FFloating: Boolean; + FOnClose, FOnDockChanged, FOnMove, FOnRecreated, +@@ -419,12 +423,13 @@ + function PaletteChanged(Foreground: Boolean): Boolean; override; + procedure SetParent(AParent: TWinControl); override; + + { Methods accessible to descendants } + procedure Arrange; + function CalcNCSizes: TPoint; virtual; ++ function CanDockTo(ADock: TTBDock): Boolean; virtual; + procedure ChangeSize(AWidth, AHeight: Integer); + function ChildControlTransparent(Ctl: TControl): Boolean; dynamic; + procedure Close; + procedure ControlExistsAtPos(const P: TPoint; var ControlExists: Boolean); virtual; + function DoArrange(CanMoveControls: Boolean; PreviousDockType: TTBDockType; + NewFloating: Boolean; NewDock: TTBDock): TPoint; virtual; abstract; +@@ -443,13 +448,16 @@ + function IsAutoResized: Boolean; + procedure ResizeBegin(SizeHandle: TTBSizeHandle); dynamic; + procedure ResizeEnd; dynamic; + procedure ResizeTrack(var Rect: TRect; const OrigRect: TRect); dynamic; + procedure ResizeTrackAccept; dynamic; + procedure SizeChanging(const AWidth, AHeight: Integer); virtual; ++ property EffectiveDockPosAccess: Integer read FEffectiveDockPos write FEffectiveDockPos; ++ property EffectiveDockRowAccess: Integer read FEffectiveDockRow write FEffectiveDockRow; + public ++ property DblClickUndock: Boolean read FDblClickUndock write FDblClickUndock default True; + property Docked: Boolean read FDocked; + property Canvas; + property CurrentDock: TTBDock read FCurrentDock write SetCurrentDock stored False; + property CurrentSize: Integer read FCurrentSize write FCurrentSize; + property DockPos: Integer read FDockPos write SetDockPos default -1; + property DockRow: Integer read FDockRow write SetDockRow default 0; +@@ -1011,12 +1019,17 @@ + SetBounds(Left, Top-NewHeight+Height, NewWidth, NewHeight); + alRight: + SetBounds(Left-NewWidth+Width, Top, NewWidth, NewHeight); + end; + end; + ++function TTBDock.Accepts(ADockableWindow: TTBCustomDockableWindow): Boolean; ++begin ++ Result := AllowDrag; ++end; ++ + procedure TTBDock.AlignControls(AControl: TControl; var Rect: TRect); + begin + ArrangeToolbars; + end; + + function CompareDockRowPos(const Item1, Item2, ExtraData: Pointer): Integer; far; +@@ -2523,12 +2536,13 @@ + [csAcceptsControls, csClickEvents, csDoubleClicks, csSetCaption] - + [csCaptureMouse{capturing is done manually}, csOpaque]; + FAutoResize := True; + FActivateParent := True; + FBorderStyle := bsSingle; + FCloseButton := True; ++ FDblClickUndock := True; + FDockableTo := [dpTop, dpBottom, dpLeft, dpRight]; + FDockableWindowStyles := [tbdsResizeEightCorner, tbdsResizeClipCursor]; + FDockPos := -1; + FDragHandleStyle := dhSingle; + FEffectiveDockRow := -1; + FHideWhenInactive := True; +@@ -3020,12 +3034,17 @@ + + procedure TTBCustomDockableWindow.RemoveDockForm(const Form: TTBCustomForm); + begin + RemoveFromList(FDockForms, Form); + end; + ++function TTBCustomDockableWindow.CanDockTo(ADock: TTBDock): Boolean; ++begin ++ Result := ADock.Position in DockableTo; ++end; ++ + function TTBCustomDockableWindow.IsAutoResized: Boolean; + begin + Result := AutoResize or Assigned(CurrentDock) or Floating; + end; + + procedure TTBCustomDockableWindow.ChangeSize(AWidth, AHeight: Integer); +@@ -3912,13 +3931,14 @@ + if FDragSplitting then + MouseOverDock := CurrentDock + else begin + { Check if it can dock } + MouseOverDock := nil; + if StartDocking and not PreventDocking then +- for I := 0 to DockList.Count-1 do begin ++ {for I := 0 to DockList.Count-1 do begin} {rl-} ++ for I := DockList.Count-1 downto 0 do begin {rl+} // Robert Lee: CurrentDock should not have the priority + Dock := DockList[I]; + if CheckIfCanDockTo(Dock, FindDockedSize(Dock).BoundsRect) then begin + MouseOverDock := Dock; + Accept := True; + if Assigned(MouseOverDock.FOnRequestDock) then + MouseOverDock.FOnRequestDock(MouseOverDock, Self, Accept); +@@ -3988,17 +4008,12 @@ + if not IsRectEmpty(MoveRect) then + Dropped; + end; + + procedure BuildDockList; + +- function AcceptableDock(const D: TTBDock): Boolean; +- begin +- Result := D.FAllowDrag and (D.Position in DockableTo); +- end; +- + procedure Recurse(const ParentCtl: TWinControl); + var + D: TTBDockPosition; + I: Integer; + begin + if ContainsControl(ParentCtl) or not ParentCtl.Showing then +@@ -4009,25 +4024,25 @@ + if (Controls[I] is TTBDock) and (TTBDock(Controls[I]).Position = D) then + Recurse(TWinControl(Controls[I])); + for I := 0 to ParentCtl.ControlCount-1 do + if (Controls[I] is TWinControl) and not(Controls[I] is TTBDock) then + Recurse(TWinControl(Controls[I])); + end; +- if (ParentCtl is TTBDock) and AcceptableDock(TTBDock(ParentCtl)) and ++ if (ParentCtl is TTBDock) and TTBDock(ParentCtl).Accepts(Self) and CanDockTo(TTBDock(ParentCtl)) and + (DockList.IndexOf(ParentCtl) = -1) then + DockList.Add(ParentCtl); + end; + + var + ParentForm: TTBCustomForm; + DockFormsList: TList; + I, J: Integer; + begin + { Manually add CurrentDock to the DockList first so that it gets priority + over other docks } +- if Assigned(CurrentDock) and AcceptableDock(CurrentDock) then ++ if Assigned(CurrentDock) and CurrentDock.Accepts(Self) and CanDockTo(CurrentDock) then + DockList.Add(CurrentDock); + ParentForm := TBGetToolWindowParentForm(Self); + DockFormsList := TList.Create; + try + if Assigned(FDockForms) then begin + for I := 0 to Screen.{$IFDEF JR_D3}CustomFormCount{$ELSE}FormCount{$ENDIF}-1 do begin +@@ -4313,25 +4328,26 @@ + end; + end; + + procedure TTBCustomDockableWindow.DoubleClick; + begin + if Docked then begin +- if DockMode = dmCanFloat then begin ++ if DblClickUndock and (DockMode = dmCanFloat) then begin + Floating := True; + MoveOnScreen(True); + end; + end +- else +- if Assigned(LastDock) then +- Parent := LastDock +- else +- if Assigned(DefaultDock) then begin +- FDockRow := ForceDockAtTopRow; +- FDockPos := ForceDockAtLeftPos; +- Parent := DefaultDock; ++ else if Floating then begin ++ if Assigned(LastDock) then ++ Parent := LastDock ++ else ++ if Assigned(DefaultDock) then begin ++ FDockRow := ForceDockAtTopRow; ++ FDockPos := ForceDockAtLeftPos; ++ Parent := DefaultDock; ++ end; + end; + end; + + function TTBCustomDockableWindow.IsMovable: Boolean; + begin + Result := (Docked and CurrentDock.FAllowDrag) or Floating; +--- TB2DsgnItemEditor.pas 2005-01-27 00:48:54.000000000 +-0400 ++++ TB2DsgnItemEditor.pas 2005-05-17 19:26:48.000000000 +-0400 +@@ -149,12 +149,18 @@ + function GetValue: String; override; + end; + + procedure TBRegisterItemClass(AClass: TTBCustomItemClass; + const ACaption: String; ResInstance: HINST); + ++type ++ TTBDsgnEditorHook = procedure(Sender: TTBItemEditForm) of object; ++ ++procedure TBRegisterDsgnEditorHook(Hook: TTBDsgnEditorHook); ++procedure TBUnregisterDsgnEditorHook(Hook: TTBDsgnEditorHook); ++ + implementation + + {$R *.DFM} + + uses + TypInfo, CommCtrl, TB2Version, TB2Common, TB2DsgnConverter; +@@ -176,12 +182,13 @@ + ImageIndex: Integer; + end; + + var + ItemClasses: TList; + ItemImageList: TImageList; ++ EditFormHooks: TList; + + {$IFNDEF JR_D6} + function CreateSelectionList: TDesignerSelectionList; + begin + Result := TDesignerSelectionList.Create; + end; +@@ -237,13 +244,24 @@ + end; + + procedure TBRegisterItemClass(AClass: TTBCustomItemClass; + const ACaption: String; ResInstance: HINST); + var + Info: PItemClassInfo; ++ I: Integer; + begin ++ if ItemClasses <> nil then ++ for I := ItemClasses.Count - 1 downto 0 do ++ begin ++ Info := ItemClasses[I]; ++ if Info.ItemClass = AClass then ++ begin ++ Dispose(Info); ++ ItemClasses.Delete(I); ++ end; ++ end; + New(Info); + Info.ItemClass := AClass; + Info.Caption := ACaption; + Info.ImageIndex := LoadItemImage(ResInstance, Uppercase(AClass.ClassName)); + ItemClasses.Add(Info); + end; +@@ -357,12 +375,17 @@ + Item.Caption := Info.Caption; + Item.ImageIndex := GetItemClassImage(Info.ItemClass); + Item.Tag := Integer(Info.ItemClass); + Item.OnClick := MoreItemClick; + MoreMenu.Add(Item); + end; ++ { Run the hooks } ++ ++ if EditFormHooks <> nil then ++ for I := 0 to EditFormHooks.Count - 1 do ++ TTBDsgnEditorHook(EditFormHooks[I]^)(Self); + end; + + destructor TTBItemEditForm.Destroy; + begin + inherited; + if Assigned(FNotifyItemList) then begin +@@ -1332,17 +1355,47 @@ + + function TTBItemsPropertyEditor.GetValue: String; + begin + Result := '(TB2000 Items)'; + end; + ++ ++procedure TBRegisterDsgnEditorHook(Hook: TTBDsgnEditorHook); ++var ++ H: ^TTBDsgnEditorHook; ++begin ++ New(H); ++ H^ := Hook; ++ EditFormHooks.Add(H); ++end; ++ ++procedure TBUnregisterDsgnEditorHook(Hook: TTBDsgnEditorHook); ++var ++ H: ^TTBDsgnEditorHook; ++ I: Integer; ++begin ++ for I := EditFormHooks.Count - 1 downto 0 do ++ begin ++ H := EditFormHooks[I]; ++ if (TMethod(H^).Code = TMethod(Hook).Code) and ++ (TMethod(H^).Data = TMethod(Hook).Data) then ++ begin ++ Dispose(H); ++ EditFormHooks.Delete(I); ++// Break; ++ end; ++ end; ++end; ++ + initialization + ItemImageList := TImageList.Create(nil); + ItemImageList.Handle := ImageList_LoadImage(HInstance, 'TB2_DSGNEDITORIMAGES', + 16, 0, clFuchsia, IMAGE_BITMAP, 0); + ItemClasses := TList.Create; ++ EditFormHooks := TList.Create; + AddModuleUnloadProc(UnregisterModuleItemClasses); + finalization + RemoveModuleUnloadProc(UnregisterModuleItemClasses); + FreeItemClasses; + FreeAndNil(ItemImageList); ++ FreeAndNil(EditFormHooks); + end. +--- TB2ExtItems.pas 2005-07-03 21:49:52.000000000 +-0400 ++++ TB2ExtItems.pas 2005-07-11 04:36:00.000000000 +-0400 +@@ -40,12 +40,17 @@ + TTBEditItemOptions = set of TTBEditItemOption; + + const + EditItemDefaultEditOptions = []; + EditItemDefaultEditWidth = 64; + ++{ Change reasons for TTBEditItem.Text property } ++ tcrSetProperty = 0; // direct assignment to TTBEditItem.Text property ++ tcrActionLink = 1; // change comes from an action link ++ tcrEditControl = 2; // change is caused by typing in edit area ++ + type + TTBEditItem = class; + TTBEditItemViewer = class; + + TTBAcceptTextEvent = procedure(Sender: TObject; var NewText: String; + var Accept: Boolean) of object; +@@ -93,12 +98,13 @@ + TTBEditItem = class(TTBCustomItem) + private + FCharCase: TEditCharCase; + FEditCaption: String; + FEditOptions: TTBEditItemOptions; + FEditWidth: Integer; ++ FExtendedAccept: Boolean; + FMaxLength: Integer; + FOnAcceptText: TTBAcceptTextEvent; + FOnBeginEdit: TTBBeginEditEvent; + FText: String; + function IsEditCaptionStored: Boolean; + function IsEditOptionsStored: Boolean; +@@ -109,16 +115,21 @@ + procedure SetEditOptions(Value: TTBEditItemOptions); + procedure SetEditWidth(Value: Integer); + procedure SetMaxLength(Value: Integer); + procedure SetText(Value: String); + protected + procedure ActionChange(Sender: TObject; CheckDefaults: Boolean); override; ++ function DoAcceptText(var NewText: string): Boolean; virtual; + procedure DoBeginEdit(Viewer: TTBEditItemViewer); virtual; ++ procedure DoTextChanging(const OldText: String; var NewText: String; Reason: Integer); virtual; ++ procedure DoTextChanged(Reason: Integer); virtual; + function GetActionLinkClass: TTBCustomItemActionLinkClass; override; + function GetItemViewerClass(AView: TTBView): TTBItemViewerClass; override; + function NeedToRecreateViewer(AViewer: TTBItemViewer): Boolean; override; ++ property ExtendedAccept: Boolean read FExtendedAccept write FExtendedAccept default False; ++ procedure SetTextEx(Value: String; Reason: Integer); + public + constructor Create(AOwner: TComponent); override; + procedure Clear; + procedure Click; override; + published + property Action; +@@ -143,12 +154,14 @@ + + property OnAcceptText: TTBAcceptTextEvent read FOnAcceptText write FOnAcceptText; + property OnBeginEdit: TTBBeginEditEvent read FOnBeginEdit write FOnBeginEdit; + property OnClick; + property OnSelect; + end; ++ ++ TEditClass = class of TEdit; + + TTBEditItemViewer = class(TTBItemViewer) + private + FEditControl: TEdit; + FEditControlStatus: set of (ecsContinueLoop, ecsAccept, ecsClose); + function EditLoop(const CapHandle: HWND): Boolean; +@@ -160,12 +173,13 @@ + function CaptionShown: Boolean; override; + function DoExecute: Boolean; override; + function GetAccRole: Integer; override; + function GetAccValue(var Value: WideString): Boolean; override; + function GetCaptionText: String; override; + procedure GetCursor(const Pt: TPoint; var ACursor: HCURSOR); override; ++ function GetEditControlClass: TEditClass; virtual; + procedure GetEditRect(var R: TRect); virtual; + procedure MouseDown(Shift: TShiftState; X, Y: Integer; + var MouseDownOnMenu: Boolean); override; + procedure MouseUp(X, Y: Integer; MouseWasDownOnMenu: Boolean); override; + procedure Paint(const Canvas: TCanvas; const ClientAreaRect: TRect; + IsSelected, IsPushed, UseDisabledShadow: Boolean); override; +@@ -363,13 +377,13 @@ + begin + if IsOnAcceptTextLinked then TTBEditItem(FClient).OnAcceptText := Value; + end; + + procedure TTBEditItemActionLink.SetText(const Value: String); + begin +- if IsTextLinked then TTBEditItem(FClient).Text := Value; ++ if IsTextLinked then TTBEditItem(FClient).SetTextEx(Value , tcrActionLink); + end; + + + { TTBEditItem } + + constructor TTBEditItem.Create(AOwner: TComponent); +@@ -387,13 +401,13 @@ + begin + if not CheckDefaults or (Self.EditCaption = '') then + Self.EditCaption := EditCaption; + if not CheckDefaults or (Self.EditOptions = []) then + Self.EditOptions := EditOptions; + if not CheckDefaults or (Self.Text = '') then +- Self.Text := Text; ++ Self.SetTextEx(Text, tcrActionLink); + if not CheckDefaults or not Assigned(Self.OnAcceptText) then + Self.OnAcceptText := OnAcceptText; + end; + end; + + function TTBEditItem.GetActionLinkClass: TTBCustomItemActionLinkClass; +@@ -494,21 +508,47 @@ + if FMaxLength <> Value then begin + FMaxLength := Value; + Change(False); + end; + end; + ++function TTBEditItem.DoAcceptText(var NewText: string): Boolean; ++begin ++ Result := True; ++ if Assigned(FOnAcceptText) then FOnAcceptText(Self, NewText, Result); ++end; ++ ++procedure TTBEditItem.DoTextChanging(const OldText: String; var NewText: String; Reason: Integer); ++begin ++ case FCharCase of ++ ecUpperCase: NewText := AnsiUpperCase(NewText); ++ ecLowerCase: NewText := AnsiLowerCase(NewText); ++ end; ++end; ++ ++procedure TTBEditItem.DoTextChanged(Reason: Integer); ++begin ++end; ++ + procedure TTBEditItem.SetText(Value: String); + begin +- case FCharCase of +- ecUpperCase: Value := AnsiUpperCase(Value); +- ecLowerCase: Value := AnsiLowerCase(Value); +- end; ++ DoTextChanging(FText, Value, tcrSetProperty); ++ if FText <> Value then begin ++ FText := Value; ++ Change(False); ++ DoTextChanged(tcrSetProperty); ++ end; ++end; ++ ++procedure TTBEditItem.SetTextEx(Value: String; Reason: Integer); ++begin ++ DoTextChanging(FText, Value, Reason); + if FText <> Value then begin + FText := Value; + Change(False); ++ DoTextChanged(Reason); + end; + end; + + + { TTBEditItemViewer } + +@@ -516,20 +556,15 @@ + var + Item: TTBEditItem; + + procedure AcceptText; + var + S: String; +- Accept: Boolean; + begin + S := FEditControl.Text; +- Accept := True; +- if Assigned(Item.FOnAcceptText) then +- Item.FOnAcceptText(Self, S, Accept); +- if Accept then +- Item.Text := S; ++ if Item.DoAcceptText(S) then Item.SetTextEx(S, tcrEditControl); + end; + + begin + Item := TTBEditItem(Self.Item); + if FEditControl = nil then + Exit; +@@ -555,12 +590,17 @@ + { Someone has stolen the focus from us, so 'cancel mode'. (We have to + handle WM_KILLFOCUS in addition to the upstream WM_CANCELMODE handling + since we don't always hold the mouse capture.) } + View.CancelMode; + FEditControlStatus := [ecsClose]; + end; ++end; ++ ++function TTBEditItemViewer.GetEditControlClass: TEditClass; ++begin ++ Result := TEdit; + end; + + procedure TTBEditItemViewer.GetEditRect(var R: TRect); + var + Item: TTBEditItem; + DC: HDC; +@@ -785,12 +825,13 @@ + end; + + var + Item: TTBEditItem; + R: TRect; + ActiveWnd, FocusWnd: HWND; ++ S: string; + begin + Item := TTBEditItem(Self.Item); + GetEditRect(R); + if IsRectEmpty(R) then begin + Result := False; + Exit; +@@ -798,14 +839,14 @@ + + ActiveWnd := GetActiveWindow; + FocusWnd := GetFocus; + + { Create the edit control } + InflateRect(R, -3, -3); +- //View.FreeNotification(Self); +- FEditControl := TEdit.Create(nil); ++ //View.FreeNotification (Self); ++ FEditControl := GetEditControlClass.Create(nil); + try + FEditControl.Name := Format('%s_edit_control_%p', [ClassName, + Pointer(FEditControl)]); + FEditControl.Visible := False; + FEditControl.BorderStyle := bsNone; + FEditControl.AutoSize := False; +@@ -826,14 +867,19 @@ + else + ActiveWnd := 0; + + FEditControlStatus := [ecsContinueLoop]; + ControlMessageLoop; + finally ++ S := FEditControl.Text; + FreeAndNil(FEditControl); + end; ++ ++ with TTBEditItem(Item) do ++ if (FEditControlStatus = [ecsContinueLoop]) and ExtendedAccept then ++ if DoAcceptText(S) then SetTextEx(S, tcrEditControl); + + { ensure the area underneath the edit control is repainted immediately } + View.Window.Update; + { If app is still active, set focus to previous control and restore capture + to CapHandle if another control hasn't taken it } + if GetActiveWindow <> 0 then begin +--- TB2Item.pas 2005-06-23 16:55:44.000000000 +-0400 ++++ TB2Item.pas 2005-08-12 08:32:48.000000000 +-0400 +@@ -38,12 +38,20 @@ + XP with themes enabled. } + + uses + Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, + StdCtrls, CommCtrl, Menus, ActnList, ImgList, TB2Anim; + ++const ++ WM_TB2K_POPUPSHOWING = WM_USER + 554; ++ ++ { Parameter in LParam of WM_TB2K_POPUPSHOWING } ++ TPS_ANIMSTART = 1; // animation query: if Result <> 0, do not animate! ++ TPS_ANIMFINISHED = 2; // only fired when animation thread is done ++ TPS_NOANIM = 3; // fired when animation is done, or if showing with no animation ++ + type + TTBCustomItem = class; + TTBCustomItemClass = class of TTBCustomItem; + TTBCustomItemActionLink = class; + TTBCustomItemActionLinkClass = class of TTBCustomItemActionLink; + TTBItemViewer = class; +@@ -79,13 +87,13 @@ + tboLongHintInMenuOnly, tboNoAutoHint, tboNoRotation, tboSameWidth, + tboShowHint, tboToolbarStyle, tboToolbarSize); + TTBItemOptions = set of TTBItemOption; + TTBItemStyle = set of (tbisSubmenu, tbisSelectable, tbisSeparator, + tbisEmbeddedGroup, tbisClicksTransparent, tbisCombo, tbisNoAutoOpen, + tbisSubitemsEditable, tbisNoLineBreak, tbisRightAlign, tbisDontSelectFirst, +- tbisRedrawOnSelChange, tbisRedrawOnMouseOverChange); ++ tbisRedrawOnSelChange, tbisRedrawOnMouseOverChange, tbisStretch); + TTBPopupAlignment = (tbpaLeft, tbpaRight, tbpaCenter); + TTBPopupEvent = procedure(Sender: TTBCustomItem; FromLink: Boolean) of object; + TTBSelectEvent = procedure(Sender: TTBCustomItem; Viewer: TTBItemViewer; + Selecting: Boolean) of object; + + ETBItemError = class(Exception); +@@ -94,12 +102,24 @@ + private + FLastWidth, FLastHeight: Integer; + end; + {$IFNDEF JR_D5} + TImageIndex = type Integer; + {$ENDIF} ++ TTBPopupPositionRec = record ++ PositionAsSubmenu: Boolean; ++ Alignment: TTBPopupAlignment; ++ Opposite: Boolean; ++ MonitorRect: TRect; ++ ParentItemRect: TRect; ++ NCSizeX: Integer; ++ NCSizeY: Integer; ++ X, Y, W, H: Integer; ++ AnimDir: TTBAnimationDirection; ++ PlaySound: Boolean; ++ end; + + TTBCustomItem = class(TComponent) + private + FActionLink: TTBCustomItemActionLink; + FAutoCheck: Boolean; + FCaption: String; +@@ -185,12 +205,14 @@ + procedure DoPopup(Sender: TTBCustomItem; FromLink: Boolean); virtual; + procedure EnabledChanged; virtual; + function GetActionLinkClass: TTBCustomItemActionLinkClass; dynamic; + function GetChevronParentView: TTBView; virtual; + procedure GetChildren(Proc: TGetChildProc; Root: TComponent); override; + function GetItemViewerClass(AView: TTBView): TTBItemViewerClass; virtual; ++ procedure GetPopupPosition(ParentView: TTBView; ++ PopupWindow: TTBPopupWindow; var PopupPositionRec: TTBPopupPositionRec); virtual; + function GetPopupWindowClass: TTBPopupWindowClass; virtual; + procedure IndexError; + procedure Loaded; override; + function NeedToRecreateViewer(AViewer: TTBItemViewer): Boolean; virtual; + procedure Notification(AComponent: TComponent; Operation: TOperation); override; + function OpenPopup(const SelectFirstItem, TrackRightButton: Boolean; +@@ -317,21 +339,21 @@ + procedure CalcSize(const Canvas: TCanvas; var AWidth, AHeight: Integer); + virtual; + function CaptionShown: Boolean; dynamic; + function DoExecute: Boolean; virtual; + procedure DrawItemCaption(const Canvas: TCanvas; ARect: TRect; + const ACaption: String; ADrawDisabledShadow: Boolean; AFormat: UINT); virtual; +- procedure Entering; virtual; ++ procedure Entering(OldSelected: TTBItemViewer); virtual; + function GetAccRole: Integer; virtual; + function GetAccValue(var Value: WideString): Boolean; virtual; + function GetCaptionText: String; virtual; + procedure GetCursor(const Pt: TPoint; var ACursor: HCURSOR); virtual; + function GetImageList: TCustomImageList; + function ImageShown: Boolean; + function IsRotated: Boolean; +- function IsToolbarSize: Boolean; ++ function IsToolbarSize: Boolean; virtual; + function IsPtInButtonPart(X, Y: Integer): Boolean; virtual; + procedure KeyDown(var Key: Word; Shift: TShiftState); virtual; + procedure Leaving; virtual; + procedure LosingCapture; virtual; + procedure MouseDown(Shift: TShiftState; X, Y: Integer; + var MouseDownOnMenu: Boolean); virtual; +@@ -354,13 +376,13 @@ + constructor Create(AView: TTBView; AItem: TTBCustomItem; AGroupLevel: Integer); virtual; + destructor Destroy; override; + procedure Execute(AGivePriority: Boolean); + function GetAccObject: IDispatch; + function GetHintText: String; + function IsAccessible: Boolean; +- function IsToolbarStyle: Boolean; ++ function IsToolbarStyle: Boolean; virtual; + function ScreenToClient(const P: TPoint): TPoint; + end; + PTBItemViewerArray = ^TTBItemViewerArray; + TTBItemViewerArray = array[0..$7FFFFFFF div SizeOf(TTBItemViewer)-1] of TTBItemViewer; + TTBViewOrientation = (tbvoHorizontal, tbvoVertical, tbvoFloating); + TTBEnterToolbarLoopOptions = set of (tbetMouseDown, tbetExecuteSelected, +@@ -452,12 +474,16 @@ + function GetRootView: TTBView; + function HandleWMGetObject(var Message: TMessage): Boolean; + procedure InitiateActions; + procedure KeyDown(var Key: Word; Shift: TShiftState); virtual; + procedure Notification(AComponent: TComponent; Operation: TOperation); override; + procedure SetAccelsVisibility(AShowAccels: Boolean); ++ procedure SetState(AState: TTBViewState); ++ property DoneActionData: TTBDoneActionData read FDoneActionData write FDoneActionData; ++ property ShowDownArrow: Boolean read FShowDownArrow; {vb+} ++ property ShowUpArrow: Boolean read FShowUpArrow; {vb+} + public + constructor CreateView(AOwner: TComponent; AParentView: TTBView; + AParentItem: TTBCustomItem; AWindow: TWinControl; + AIsToolbar, ACustomizing, AUsePriorityList: Boolean); virtual; + destructor Destroy; override; + procedure BeginUpdate; +@@ -663,19 +689,22 @@ + procedure WMNCCalcSize(var Message: TWMNCCalcSize); message WM_NCCALCSIZE; + procedure WMNCPaint(var Message: TMessage); message WM_NCPAINT; + procedure WMPaint(var Message: TWMPaint); message WM_PAINT; + procedure WMPrint(var Message: TMessage); message WM_PRINT; + procedure WMPrintClient(var Message: TMessage); message WM_PRINTCLIENT; + procedure WMTB2kStepAnimation(var Message: TMessage); message WM_TB2K_STEPANIMATION; ++ procedure WMTB2kAnimationEnded (var Message: TMessage); message WM_TB2K_ANIMATIONENDED; + protected + procedure CreateParams(var Params: TCreateParams); override; + procedure CreateWnd; override; + procedure DestroyWindowHandle; override; ++ function GetNCSize: TPoint; dynamic; + function GetViewClass: TTBViewClass; dynamic; + procedure Paint; override; + procedure PaintScrollArrows; virtual; ++ property AnimationDirection: TTBAnimationDirection read FAnimationDirection; + public + constructor CreatePopupWindow(AOwner: TComponent; const AParentView: TTBView; + const AItem: TTBCustomItem; const ACustomizing: Boolean); virtual; + destructor Destroy; override; + procedure BeforeDestruction; override; + +@@ -811,26 +840,12 @@ + + procedure TBInitToolbarSystemFont; + + var + ToolbarFont: TFont; + +- +-implementation +- +-uses +- MMSYSTEM, TB2Consts, TB2Common, IMM, TB2Acc; +- +-var +- LastPos: TPoint; +- +-threadvar +- ClickWndRefCount: Integer; +- ClickWnd: HWND; +- ClickList: TList; +- + type + TTBModalHandler = class + private + FCreatedWnd: Boolean; + FInited: Boolean; + FWnd: HWND; +@@ -842,12 +857,29 @@ + procedure Loop(const RootView: TTBView; const AMouseDown, AExecuteSelected, + AFromMSAA, TrackRightButton: Boolean); + property RootPopup: TTBPopupWindow read FRootPopup write FRootPopup; + property Wnd: HWND read FWnd; + end; + ++function ProcessDoneAction(const DoneActionData: TTBDoneActionData; ++ const ReturnClickedItemOnly: Boolean): TTBCustomItem; ++ ++implementation ++ ++uses ++ MMSYSTEM, TB2Consts, TB2Common, IMM, TB2Acc; ++ ++var ++ LastPos: TPoint; ++ ++threadvar ++ ClickWndRefCount: Integer; ++ ClickWnd: HWND; ++ ClickList: TList; ++ ++type + PItemChangedNotificationData = ^TItemChangedNotificationData; + TItemChangedNotificationData = record + Proc: TTBItemChangedProc; + RefCount: Integer; + end; + +@@ -1678,16 +1710,17 @@ + Click; + end; + + var + PlayedSound: Boolean = False; + +-function TTBCustomItem.CreatePopup(const ParentView: TTBView; +- const ParentViewer: TTBItemViewer; const PositionAsSubmenu, SelectFirstItem, +- Customizing: Boolean; const APopupPoint: TPoint; +- const Alignment: TTBPopupAlignment): TTBPopupWindow; ++procedure TTBCustomItem.GetPopupPosition(ParentView: TTBView; ++ PopupWindow: TTBPopupWindow; var PopupPositionRec: TTBPopupPositionRec); ++var ++ X2, Y2: Integer; ++ RepeatCalcX: Boolean; + + function CountObscured(X, Y, W, H: Integer): Integer; + var + I: Integer; + P: TPoint; + V: TTBItemViewer; +@@ -1705,129 +1738,24 @@ + if V.Show and (V.BoundsRect.Left >= X) and (V.BoundsRect.Right <= W) and + (V.BoundsRect.Top >= Y) and (V.BoundsRect.Bottom <= H) then + Inc(Result); + end; + end; + +-var +- EventItem, ParentItem: TTBCustomItem; +- Opposite: Boolean; +- ChevronParentView: TTBView; +- X, X2, Y, Y2, W, H: Integer; +- P: TPoint; +- RepeatCalcX: Boolean; +- ParentItemRect: TRect; +- MonitorRect: TRect; +- AnimDir: TTBAnimationDirection; + begin +- EventItem := ItemContainingItems(Self); +- if EventItem <> Self then +- EventItem.DoPopup(Self, True); +- DoPopup(Self, False); +- +- ChevronParentView := GetChevronParentView; +- if ChevronParentView = nil then +- ParentItem := Self +- else +- ParentItem := ChevronParentView.FParentItem; +- +- Opposite := Assigned(ParentView) and (vsOppositePopup in ParentView.FState); +- Result := GetPopupWindowClass.CreatePopupWindow(nil, ParentView, ParentItem, +- Customizing); +- try +- if Assigned(ChevronParentView) then begin +- ChevronParentView.FreeNotification(Result.View); +- Result.View.FChevronParentView := ChevronParentView; +- Result.View.FIsToolbar := True; +- Result.View.Style := Result.View.Style + +- (ChevronParentView.Style * [vsAlwaysShowHints]); +- Result.Color := clBtnFace; +- end; +- +- { Calculate ParentItemRect, and MonitorRect (the rectangle of the monitor +- that the popup window will be confined to) } +- if Assigned(ParentView) then begin +- ParentView.ValidatePositions; +- ParentItemRect := ParentViewer.BoundsRect; +- P := ParentView.FWindow.ClientToScreen(Point(0, 0)); +- OffsetRect(ParentItemRect, P.X, P.Y); +- if not IsRectEmpty(ParentView.FMonitorRect) then +- MonitorRect := ParentView.FMonitorRect +- else +- MonitorRect := GetRectOfMonitorContainingRect(ParentItemRect, False); +- end +- else begin +- ParentItemRect.TopLeft := APopupPoint; +- ParentItemRect.BottomRight := APopupPoint; +- MonitorRect := GetRectOfMonitorContainingPoint(APopupPoint, False); +- end; +- Result.View.FMonitorRect := MonitorRect; +- +- { Initialize item positions and size of the popup window } +- if ChevronParentView = nil then +- Result.View.FMaxHeight := (MonitorRect.Bottom - MonitorRect.Top) - +- (PopupMenuWindowNCSize * 2) +- else +- Result.View.WrapOffset := (MonitorRect.Right - MonitorRect.Left) - +- (PopupMenuWindowNCSize * 2); +- if SelectFirstItem then +- Result.View.Selected := Result.View.FirstSelectable; +- Result.View.UpdatePositions; +- W := Result.Width; +- H := Result.Height; +- +- { Calculate initial X,Y position of the popup window } +- if Assigned(ParentView) then begin +- if not PositionAsSubmenu then begin +- if ChevronParentView = nil then begin +- if (ParentView = nil) or (ParentView.FOrientation <> tbvoVertical) then begin +- if GetSystemMetrics(SM_MENUDROPALIGNMENT) = 0 then +- X := ParentItemRect.Left +- else +- X := ParentItemRect.Right - W; +- Y := ParentItemRect.Bottom; +- end +- else begin +- X := ParentItemRect.Left - W; +- Y := ParentItemRect.Top; +- end; +- end +- else begin +- if ChevronParentView.FOrientation <> tbvoVertical then begin +- X := ParentItemRect.Right - W; +- Y := ParentItemRect.Bottom; +- end +- else begin +- X := ParentItemRect.Left - W; +- Y := ParentItemRect.Top; +- end; +- end; +- end +- else begin +- X := ParentItemRect.Right - PopupMenuWindowNCSize; +- Y := ParentItemRect.Top - PopupMenuWindowNCSize; +- end; +- end +- else begin +- X := APopupPoint.X; +- Y := APopupPoint.Y; +- case Alignment of +- tbpaRight: Dec(X, W); +- tbpaCenter: Dec(X, W div 2); +- end; +- end; +- ++ with PopupPositionRec do ++ begin + { Adjust the Y position of the popup window } + { If the window is going off the bottom of the monitor, try placing it + above the parent item } + if (Y + H > MonitorRect.Bottom) and + ((ParentView = nil) or (ParentView.FOrientation <> tbvoVertical)) then begin + if not PositionAsSubmenu then + Y2 := ParentItemRect.Top + else +- Y2 := ParentItemRect.Bottom + PopupMenuWindowNCSize; ++ Y2 := ParentItemRect.Bottom + NCSizeY; + Dec(Y2, H); + { Only place it above the parent item if it isn't going to go off the + top of the monitor } + if Y2 >= MonitorRect.Top then + Y := Y2; + end; +@@ -1897,23 +1825,23 @@ + runs out of space on the screen, switch directions } + repeat + RepeatCalcX := False; + X2 := X; + if Opposite or (X2 + W > MonitorRect.Right) then begin + if Assigned(ParentView) then +- X2 := ParentItemRect.Left + PopupMenuWindowNCSize; ++ X2 := ParentItemRect.Left + NCSizeX; + Dec(X2, W); + if not Opposite then +- Include(Result.View.FState, vsOppositePopup) ++ Include(PopupWindow.View.FState, vsOppositePopup) + else begin + if X2 < MonitorRect.Left then begin + Opposite := False; + RepeatCalcX := True; + end + else +- Include(Result.View.FState, vsOppositePopup); ++ Include(PopupWindow.View.FState, vsOppositePopup); + end; + end; + until not RepeatCalcX; + X := X2; + if X < MonitorRect.Left then + X := MonitorRect.Left; +@@ -1934,14 +1862,149 @@ + else begin + if X + W div 2 >= ParentItemRect.Left + (ParentItemRect.Right - ParentItemRect.Left) div 2 then + Include(AnimDir, tbadRight) + else + Include(AnimDir, tbadLeft); + end; +- Result.FAnimationDirection := AnimDir; ++ end; ++end; ++ ++function TTBCustomItem.CreatePopup(const ParentView: TTBView; ++ const ParentViewer: TTBItemViewer; const PositionAsSubmenu, SelectFirstItem, ++ Customizing: Boolean; const APopupPoint: TPoint; ++ const Alignment: TTBPopupAlignment): TTBPopupWindow; ++var ++ EventItem, ParentItem: TTBCustomItem; ++ Opposite: Boolean; ++ ChevronParentView: TTBView; ++ X, Y, W, H: Integer; ++ P: TPoint; ++ ParentItemRect: TRect; ++ MonitorRect: TRect; ++ PopupRec: TTBPopupPositionRec; ++ NCSize: TPoint; ++begin ++ EventItem := ItemContainingItems(Self); ++ if EventItem <> Self then ++ EventItem.DoPopup(Self, True); ++ DoPopup(Self, False); ++ ++ ChevronParentView := GetChevronParentView; ++ if ChevronParentView = nil then ++ ParentItem := Self ++ else ++ ParentItem := ChevronParentView.FParentItem; ++ ++ Opposite := Assigned(ParentView) and (vsOppositePopup in ParentView.FState); ++ Result := GetPopupWindowClass.CreatePopupWindow(nil, ParentView, ParentItem, ++ Customizing); ++ try ++ if Assigned(ChevronParentView) then begin ++ ChevronParentView.FreeNotification(Result.View); ++ Result.View.FChevronParentView := ChevronParentView; ++ Result.View.FIsToolbar := True; ++ Result.View.Style := Result.View.Style + ++ (ChevronParentView.Style * [vsAlwaysShowHints]); ++ Result.Color := clBtnFace; ++ end; + ++ { Calculate ParentItemRect, and MonitorRect (the rectangle of the monitor ++ that the popup window will be confined to) } ++ if Assigned(ParentView) then begin ++ ParentView.ValidatePositions; ++ ParentItemRect := ParentViewer.BoundsRect; ++ P := ParentView.FWindow.ClientToScreen(Point(0, 0)); ++ OffsetRect(ParentItemRect, P.X, P.Y); ++ if not IsRectEmpty(ParentView.FMonitorRect) then ++ MonitorRect := ParentView.FMonitorRect ++ else ++ {MonitorRect := GetRectOfMonitorContainingPoint(APopupPoint, False);} {vb-} ++ MonitorRect := GetRectOfMonitorContainingPoint(APopupPoint, True); {vb+} ++ end ++ else begin ++ ParentItemRect.TopLeft := APopupPoint; ++ ParentItemRect.BottomRight := APopupPoint; ++ {MonitorRect := GetRectOfMonitorContainingPoint(APopupPoint, False);} {vb-} ++ MonitorRect := GetRectOfMonitorContainingPoint(APopupPoint, True); {vb+} ++ end; ++ Result.View.FMonitorRect := MonitorRect; ++ ++ { Initialize item positions and size of the popup window } ++ NCSize := Result.GetNCSize; ++ if ChevronParentView = nil then ++ Result.View.FMaxHeight := (MonitorRect.Bottom - MonitorRect.Top) - ++ (NCSize.Y * 2) ++ else ++ Result.View.WrapOffset := (MonitorRect.Right - MonitorRect.Left) - ++ (NCSize.X * 2); ++ if SelectFirstItem then ++ Result.View.Selected := Result.View.FirstSelectable; ++ Result.View.UpdatePositions; ++ W := Result.Width; ++ H := Result.Height; ++ ++ { Calculate initial X,Y position of the popup window } ++ if Assigned(ParentView) then begin ++ if not PositionAsSubmenu then begin ++ if ChevronParentView = nil then begin ++ if (ParentView = nil) or (ParentView.FOrientation <> tbvoVertical) then begin ++ if GetSystemMetrics(SM_MENUDROPALIGNMENT) = 0 then ++ X := ParentItemRect.Left ++ else ++ X := ParentItemRect.Right - W; ++ Y := ParentItemRect.Bottom; ++ end ++ else begin ++ X := ParentItemRect.Left - W; ++ Y := ParentItemRect.Top; ++ end; ++ end ++ else begin ++ if ChevronParentView.FOrientation <> tbvoVertical then begin ++ X := ParentItemRect.Right - W; ++ Y := ParentItemRect.Bottom; ++ end ++ else begin ++ X := ParentItemRect.Left - W; ++ Y := ParentItemRect.Top; ++ end; ++ end; ++ end ++ else begin ++ X := ParentItemRect.Right - NCSize.X; ++ Y := ParentItemRect.Top - NCSize.Y; ++ end; ++ end ++ else begin ++ X := APopupPoint.X; ++ Y := APopupPoint.Y; ++ case Alignment of ++ tbpaRight: Dec(X, W); ++ tbpaCenter: Dec(X, W div 2); ++ end; ++ end; ++ ++ PopupRec.PositionAsSubmenu := PositionAsSubmenu; ++ PopupRec.Alignment := Alignment; ++ PopupRec.Opposite := Opposite; ++ PopupRec.MonitorRect := MonitorRect; ++ PopupRec.ParentItemRect := ParentItemRect; ++ PopupRec.NCSizeX := NCSize.X; ++ PopupRec.NCSizeY := NCSize.Y; ++ PopupRec.X := X; ++ PopupRec.Y := Y; ++ PopupRec.W := W; ++ PopupRec.H := H; ++ PopupRec.AnimDir := []; ++ PopupRec.PlaySound := True; ++ GetPopupPosition(ParentView, Result, PopupRec); ++ X := PopupRec.X; ++ Y := PopupRec.Y; ++ W := PopupRec.W; ++ H := PopupRec.H; ++ Result.FAnimationDirection := PopupRec.AnimDir; + Result.SetBounds(X, Y, W, H); + if Assigned(ParentView) then begin + Result.FreeNotification(ParentView); + ParentView.FOpenViewerWindow := Result; + ParentView.FOpenViewerView := Result.View; + ParentView.FOpenViewer := ParentViewer; +@@ -1949,13 +2012,13 @@ + Include(ParentView.FState, vsDropDownMenus); + ParentView.Invalidate(ParentViewer); + ParentView.FWindow.Update; + end; + end; + Include(Result.View.FState, vsDrawInOrder); +- if not NeedToPlaySound('MenuPopup') then begin ++ if not PopupRec.PlaySound or not NeedToPlaySound('MenuPopup') then begin + { Don't call PlaySound if we don't have to } + Result.Visible := True; + end + else begin + if not PlayedSound then begin + { Work around Windows 2000 "bug" where there's a 1/3 second delay upon the +@@ -2626,12 +2689,13 @@ + P := Pos(#9, Result); + if P <> 0 then + SetLength(Result, P-1); + end; + + function TTBItemViewer.GetHintText: String; ++var P: Integer; + begin + Result := GetShortHint(Item.Hint); + { If there is no short hint, use the caption for the hint. Like Office, + strip any trailing colon or ellipsis. } + if (Result = '') and not(tboNoAutoHint in Item.EffectiveOptions) and + (not(tbisSubmenu in Item.ItemStyle) or (tbisCombo in Item.ItemStyle) or +@@ -2643,15 +2707,22 @@ + if not TCustomAction(Item.ActionLink.Action).DoHint(Result) then + Result := ''; + { Note: TControlActionLink.DoShowHint actually misinterprets the result + of DoHint, but we get it right... } + end; + { Add shortcut text } +- if (Result <> '') and Application.HintShortCuts and +- (Item.ShortCut <> scNone) then +- Result := Format('%s (%s)', [Result, ShortCutToText(Item.ShortCut)]); ++ if (Result <> '') and Application.HintShortCuts then ++ begin ++ { Custom shortcut } ++ P := Pos(#9, Item.Caption); ++ if (P <> 0) and (P < Length(Item.Caption)) then ++ Result := Format('%s (%s)', [Result, Copy(Item.Caption, P+ 1, MaxInt)]) ++ else ++ if (Item.ShortCut <> scNone) then ++ Result := Format('%s (%s)', [Result, ShortCutToText(Item.ShortCut)]); ++ end; + end; + + function TTBItemViewer.CaptionShown: Boolean; + begin + Result := (GetCaptionText <> '') and (not IsToolbarSize or + (Item.ImageIndex < 0) or (Item.DisplayMode in [nbdmTextOnly, nbdmImageAndText])) or +@@ -3283,13 +3354,13 @@ + + procedure TTBItemViewer.LosingCapture; + begin + View.Invalidate(Self); + end; + +-procedure TTBItemViewer.Entering; ++procedure TTBItemViewer.Entering(OldSelected: TTBItemViewer); + begin + if Assigned(Item.FOnSelect) then + Item.FOnSelect(Item, Self, True); + end; + + procedure TTBItemViewer.Leaving; +@@ -4086,13 +4157,13 @@ + FMouseOverSelected := NewMouseOverSelected; + if Assigned(OldSelected) and (tbisRedrawOnSelChange in OldSelected.Item.ItemStyle) then + Invalidate(OldSelected); + if Assigned(Value) then begin + if tbisRedrawOnSelChange in Value.Item.ItemStyle then + Invalidate(Value); +- Value.Entering; ++ Value.Entering(OldSelected); + end; + NotifyFocusEvent; + + { Handle automatic opening of a child popup } + if vsModal in FState then begin + { If the view is a toolbar, immediately open any child popup } +@@ -4379,13 +4450,13 @@ + if LastLine and not DidWrap and (AOrientation <> tbvoFloating) then begin + { In case the toolbar is docked next to a taller/wider toolbar... } + HighestWidthOnLine := TotalSize.X; + HighestHeightOnLine := TotalSize.Y; + end; + { Make separators on toolbars as tall/wide as the tallest/widest item } +- if tbisSeparator in Item.ItemStyle then begin ++ if [tbisSeparator, tbisStretch] * Item.ItemStyle <> [] then begin + if AOrientation <> tbvoVertical then + Pos.BoundsRect.Bottom := Pos.BoundsRect.Top + HighestHeightOnLine + else + Pos.BoundsRect.Right := Pos.BoundsRect.Left + HighestWidthOnLine; + end + else begin +@@ -5692,12 +5763,16 @@ + + { Note: This doesn't remove the selection from a top-level toolbar item. + Unfortunately, we can't do 'Selected := nil' because it would destroy + child popups and that must'nt happen for the reason stated above. } + end; + ++procedure TTBView.SetState(AState: TTBViewState); ++begin ++ FState := AState; ++end; + + { TTBModalHandler } + + const + LSFW_LOCK = 1; + LSFW_UNLOCK = 2; +@@ -6181,15 +6256,16 @@ + + + { TTBPopupView } + + procedure TTBPopupView.AutoSize(AWidth, AHeight: Integer); + begin +- with FWindow do +- SetBounds(Left, Top, AWidth + (PopupMenuWindowNCSize * 2), +- AHeight + (PopupMenuWindowNCSize * 2)); ++ with TTBPopupWindow(FWindow) do ++ with GetNCSize do ++ SetBounds(Left, Top, AWidth + (X * 2), ++ AHeight + (Y * 2)); + end; + + function TTBPopupView.GetFont: TFont; + begin + Result := (Owner as TTBPopupWindow).Font; + end; +@@ -6260,12 +6336,18 @@ + restored without generating a WM_PAINT message. } + if Assigned(FView) then + FView.CloseChildPopups; + inherited; + end; + ++function TTBPopupWindow.GetNCSize: TPoint; ++begin ++ Result.X := PopupMenuWindowNCSize; ++ Result.Y := PopupMenuWindowNCSize; ++end; ++ + function TTBPopupWindow.GetViewClass: TTBViewClass; + begin + Result := TTBPopupView; + end; + + procedure TTBPopupWindow.CreateParams(var Params: TCreateParams); +@@ -6343,26 +6425,36 @@ + {$IFNDEF TB2K_NO_ANIMATION} + if ((FView.ParentView = nil) or not(vsNoAnimation in FView.FParentView.FState)) and + Showing and (FView.Selected = nil) and not IsWindowVisible(WindowHandle) and + SystemParametersInfo(SPI_GETMENUANIMATION, 0, @Animate, 0) and Animate then begin + Blend := SystemParametersInfo(SPI_GETMENUFADE, 0, @Animate, 0) and Animate; + if Blend or (FAnimationDirection <> []) then begin +- TBStartAnimation(WindowHandle, Blend, FAnimationDirection); +- Exit; ++ if SendMessage(WindowHandle, WM_TB2K_POPUPSHOWING, TPS_ANIMSTART, 0) = 0 then ++ begin ++ { Start animation only if WM_TB2K_POPUPSHOWING returns zero (or not handled) } ++ TBStartAnimation(WindowHandle, Blend, FAnimationDirection); ++ Exit; ++ end; + end; + end; + {$ENDIF} + + { No animation... } + if not Showing then begin + { Call TBEndAnimation to ensure WS_EX_LAYERED style is removed before + hiding, otherwise windows under the popup window aren't repainted + properly. } + TBEndAnimation(WindowHandle); + end; + SetWindowPos(WindowHandle, 0, 0, 0, 0, 0, ShowFlags[Showing]); ++ if Showing then SendNotifyMessage(WindowHandle, WM_TB2K_POPUPSHOWING, TPS_NOANIM, 0); ++end; ++ ++procedure TTBPopupWindow.WMTB2kAnimationEnded(var Message: TMessage); ++begin ++ SendNotifyMessage(WindowHandle, WM_TB2K_POPUPSHOWING, TPS_ANIMFINISHED, 0); + end; + + procedure TTBPopupWindow.WMTB2kStepAnimation(var Message: TMessage); + begin + TBStepAnimation(Message); + end; +@@ -6426,14 +6518,14 @@ + begin + { do nothing -- ignore Alt+F4 keypresses } + end; + + procedure TTBPopupWindow.WMNCCalcSize(var Message: TWMNCCalcSize); + begin +- InflateRect(Message.CalcSize_Params^.rgrc[0], +- -PopupMenuWindowNCSize, -PopupMenuWindowNCSize); ++ with GetNCSize do ++ InflateRect(Message.CalcSize_Params^.rgrc[0], -X, -Y); + inherited; + end; + + procedure PopupWindowNCPaintProc(Wnd: HWND; DC: HDC; AppData: Longint); + var + R: TRect; +--- TB2MRU.pas 2005-01-05 21:56:50.000000000 +-0400 ++++ TB2MRU.pas 2005-08-02 18:38:34.000000000 +-0400 +@@ -50,12 +50,13 @@ + procedure ClickHandler(Sender: TObject); + procedure SetHidePathExtension(Value: Boolean); + procedure SetList(Value: TStrings); + procedure SetMaxItems(Value: Integer); + protected + property Container: TTBCustomItem read FContainer; ++ function GetFirstKey: Integer; virtual; + function GetItemClass: TTBCustomItemClass; virtual; + procedure SetItemCaptions; virtual; + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + procedure Add(Filename: String); +@@ -293,37 +294,39 @@ + Ini.DeleteKey(Section, FPrefix + IntToStr(I)); + end; + end; + + procedure TTBMRUList.SetItemCaptions; + var +- I, J: Integer; ++ I, J, N: Integer; + Key: Char; + S: String; + Buf: array[0..MAX_PATH-1] of Char; + begin + while FList.Count > FMaxItems do + FList.Delete(FList.Count-1); ++ N := GetFirstKey; + for I := 0 to FContainer.Count-1 do begin + Key := #0; +- if I < 9 then +- Key := Chr(Ord('1') + I) ++ if N < 9 then ++ Key := Chr(Ord('1') + N) + else begin + { No more numbers; try letters } +- J := I - 9; ++ J := N - 9; + if J < 26 then + Key := Chr(Ord('A') + J); + end; + S := FList[I]; + if HidePathExtension and (GetFileTitle(PChar(S), Buf, SizeOf(Buf)) = 0) then + S := Buf; + S := EscapeAmpersands(S); + if Key <> #0 then + FContainer[I].Caption := Format('&%s %s', [Key, S]) + else + FContainer[I].Caption := S; ++ Inc(N); + end; + end; + + procedure TTBMRUList.ClickHandler(Sender: TObject); + var + I: Integer; +@@ -358,12 +361,17 @@ + + function TTBMRUList.GetItemClass: TTBCustomItemClass; + begin + Result := TTBCustomItem; + end; + ++function TTBMRUList.GetFirstKey: Integer; ++begin ++ Result := 0; ++end; ++ + + { TTBMRUListItem } + + constructor TTBMRUListItem.Create(AOwner: TComponent); + begin + inherited; +--- TB2Reg.pas 2005-01-05 21:56:50.000000000 +-0400 ++++ TB2Reg.pas 2005-06-07 04:59:48.000000000 +-0400 +@@ -33,19 +33,12 @@ + uses + Windows, SysUtils, Classes, Graphics, Controls, Dialogs, ActnList, ImgList, + {$IFDEF JR_D6} DesignIntf, DesignEditors, VCLEditors, {$ELSE} DsgnIntf, {$ENDIF} + TB2Toolbar, TB2ToolWindow, TB2Dock, TB2Item, TB2ExtItems, TB2MRU, TB2MDI, + TB2DsgnItemEditor; + +-procedure Register; +- +-implementation +- +-uses +- ImgEdit; +- + {$IFDEF JR_D5} + + { TTBImageIndexPropertyEditor } + + { Unfortunately TComponentImageIndexPropertyEditor seems to be gone in + Delphi 6, so we have to use our own image index property editor class } +@@ -64,12 +57,31 @@ + procedure ListMeasureWidth(const Value: string; ACanvas: TCanvas; + var AWidth: Integer); {$IFNDEF JR_D6} override; {$ENDIF} + procedure ListDrawValue(const Value: string; ACanvas: TCanvas; + const ARect: TRect; ASelected: Boolean); {$IFNDEF JR_D6} override; {$ENDIF} + end; + ++{ TTBItemImageIndexPropertyEditor } ++ ++type ++ TTBItemImageIndexPropertyEditor = class(TTBImageIndexPropertyEditor) ++ public ++ function GetImageListAt (Index: Integer): TCustomImageList; override; ++ end; ++ ++{$ENDIF} ++ ++procedure Register; ++ ++implementation ++ ++uses ++ ImgEdit; ++ ++{$IFDEF JR_D5} ++ + function TTBImageIndexPropertyEditor.GetAttributes: TPropertyAttributes; + begin + Result := [paMultiSelect, paValueList, paRevertable]; + end; + + function TTBImageIndexPropertyEditor.GetImageListAt(Index: Integer): TCustomImageList; +@@ -125,18 +137,12 @@ + if Assigned(ImgList) then + Inc(AWidth, ImgList.Width); + end; + + { TTBItemImageIndexPropertyEditor } + +-type +- TTBItemImageIndexPropertyEditor = class(TTBImageIndexPropertyEditor) +- protected +- function GetImageListAt(Index: Integer): TCustomImageList; override; +- end; +- + function TTBItemImageIndexPropertyEditor.GetImageListAt(Index: Integer): TCustomImageList; + var + C: TPersistent; + Item: TTBCustomItem; + begin + Result := nil; +--- TB2Toolbar.pas 2005-07-30 13:17:20.000000000 +-0400 ++++ TB2Toolbar.pas 2005-08-01 11:16:18.000000000 +-0400 +@@ -891,12 +891,17 @@ + if Assigned(FView.Selected) then begin + Item := FView.Selected.Item; + if not(tboLongHintInMenuOnly in Item.EffectiveOptions) then + Hint := Item.Hint + else + Hint := ''; ++ ++ with TTBItemViewerAccess(FView.Find(Item)) do ++ begin ++ MouseMove(X - BoundsRect.Left, Y - BoundsRect.Top); ++ end; + end + else + Hint := ''; + end; + { Call TrackMouseEvent to be sure that we are notified when the mouse leaves + the window. We won't get a CM_MOUSELEAVE message if the mouse moves +--- TB2ToolWindow.pas 2005-01-05 21:56:50.000000000 +-0400 ++++ TB2ToolWindow.pas 2005-02-23 04:57:58.000000000 +-0400 +@@ -192,20 +192,30 @@ + end; + + function TTBToolWindow.CalcSize(ADock: TTBDock): TPoint; + begin + Result.X := FBarWidth; + Result.Y := FBarHeight; +- if Assigned(ADock) and (FullSize or Stretch) then begin +- { If docked and stretching, return the minimum size so that the toolbar +- can shrink below FBarWidth/FBarHeight } +- if not(ADock.Position in [dpLeft, dpRight]) then +- Result.X := FMinClientWidth +- else +- Result.Y := FMinClientHeight; +- end; ++ if Assigned(ADock) then ++ if FullSize then ++ begin ++ { If docked and full size, return the size corresponding to docked size } ++ if not(ADock.Position in [dpLeft, dpRight]) then ++ Result.X := ADock.ClientWidth - (Width - ClientWidth) ++ else ++ Result.Y := ADock.ClientHeight - (Height - ClientHeight); ++ end ++ else if Stretch then ++ begin ++ { If docked and stretching, return the minimum size so that the toolbar ++ can shrink below FBarWidth/FBarHeight } ++ if not(ADock.Position in [dpLeft, dpRight]) then ++ Result.X := FMinClientWidth ++ else ++ Result.Y := FMinClientHeight; ++ end; + end; + + procedure TTBToolWindow.GetBaseSize(var ASize: TPoint); + begin + ASize := CalcSize(CurrentDock); + end; diff --git a/official/2.1.6+2.1.beta1/Source/patch.bat b/official/2.1.6+2.1.beta1/Source/patch.bat new file mode 100644 index 0000000..7a5a5af --- /dev/null +++ b/official/2.1.6+2.1.beta1/Source/patch.bat @@ -0,0 +1,3 @@ +@if not %2 == "" %2 +@if not %3 == "" cd %3 +patch -p0 --backup --batch < %1 \ No newline at end of file diff --git a/official/2.1.6+2.1.beta1/Source/patch.exe b/official/2.1.6+2.1.beta1/Source/patch.exe new file mode 100644 index 0000000..cc0bdb0 Binary files /dev/null and b/official/2.1.6+2.1.beta1/Source/patch.exe differ diff --git a/official/2.1.6+2.1.beta1/TB2k-LICENSE.txt b/official/2.1.6+2.1.beta1/TB2k-LICENSE.txt new file mode 100644 index 0000000..540e8dc --- /dev/null +++ b/official/2.1.6+2.1.beta1/TB2k-LICENSE.txt @@ -0,0 +1,61 @@ +Toolbar2000 License v3.2 +======================== + +"Author" herein refers to Jordan Russell (the creator of the Toolbar2000 +components). +"Software" refers to all files bearing this notice, as well as any other +files and source code included with Toolbar2000 (typically extracted from a +.zip archive), and all content in them, regardless of whether any +modifications have been made. + +Except where otherwise noted, all of the documentation and Software included +in the Toolbar2000 package is copyrighted by Jordan Russell (the Author). + +Copyright (C) 1998-2005 Jordan Russell. All rights reserved. + +Use and distribution of the software is permitted provided that all of the +following terms are accepted: + +1. The Software is provided "as-is," without any express or implied + warranty. In no event shall the Author be held liable for any damages + arising from the use of the Software. + +2. All redistributions of the Software's files must be in their original, + unmodified form. Distributions of modified versions of the files is not + permitted without express written permission of the Author. + +3. All redistributions of the Software's files must retain all copyright + notices and web site addresses that are currently in place, and must + include this list of conditions without modification. + +4. None of the Software's files may be redistributed for profit or as part + of another software package without express written permission of the + Author. + +5. You are permitted to Compile the Software into any kind of applications. + ("Compile" here refers to the automatic process of translating the + Software's source code into executable machine code by a compiler such + as the one included with Borland's Delphi or C++Builder.) + However, compilation into commercial or shareware applications, or any + applications that you or your organization are profiting from, requires + registration (payment) of the software. Such payment is made to the Author + of the Software (Jordan Russell). + For information on registering, see the Toolbar2000 documentation or this + web page: + http://www.jrsoftware.org/tb2kreg.php + +6. Redistribution of any of the Software's files in object form (including + but not limited to .DCU and .OBJ formats) is strictly prohibited without + express written permission of the Author. + +7. Full backward compatibility in future versions of the Software is not + guaranteed. In no event shall the Author be held liable for any + inconvenience or damages arising from lack of backward compatibility. + +If you do not agree to all of the above terms, you are not permitted to +use the Software in any way, and all copies of it must be deleted from your +system(s). + +Jordan Russell +jr-2005 AT jrsoftware.org +http://www.jrsoftware.org/ diff --git a/official/2.1.6+2.1.beta1/TBX/Converter/Converter.ico b/official/2.1.6+2.1.beta1/TBX/Converter/Converter.ico new file mode 100644 index 0000000..05cac5a Binary files /dev/null and b/official/2.1.6+2.1.beta1/TBX/Converter/Converter.ico differ diff --git a/official/2.1.6+2.1.beta1/TBX/Converter/MainUnit.dfm b/official/2.1.6+2.1.beta1/TBX/Converter/MainUnit.dfm new file mode 100644 index 0000000..9923b5d --- /dev/null +++ b/official/2.1.6+2.1.beta1/TBX/Converter/MainUnit.dfm @@ -0,0 +1,501 @@ +object ConverterForm: TConverterForm + Left = 191 + Top = 108 + AutoScroll = False + Caption = 'TBX Converter' + ClientHeight = 474 + ClientWidth = 783 + Color = clBtnFace + Font.Charset = DEFAULT_CHARSET + Font.Color = clWindowText + Font.Height = -11 + Font.Name = 'Tahoma' + Font.Style = [] + OldCreateOrder = False + Position = poScreenCenter + OnCreate = FormCreate + OnDestroy = FormDestroy + PixelsPerInch = 96 + TextHeight = 13 + object TBDock1: TTBDock + Left = 0 + Top = 0 + Width = 783 + Height = 26 + object TBXToolbar2: TTBXToolbar + Left = 0 + Top = 0 + Align = alLeft + Caption = 'TBXToolbar' + DockableTo = [dpTop, dpBottom] + FullSize = True + Images = ImageList1 + TabOrder = 0 + object TBXVisibilityToggleItem2: TTBXVisibilityToggleItem + Caption = 'Files' + Control = FilePanel + DisplayMode = nbdmImageAndText + ImageIndex = 0 + OnClick = TBXVisibilityToggleItem2Click + end + object TBXVisibilityToggleItem1: TTBXVisibilityToggleItem + Caption = 'Settings' + Control = Panel1 + DisplayMode = nbdmImageAndText + ImageIndex = 1 + end + object TBXSeparatorItem3: TTBXSeparatorItem + end + object TBXLabelItem1: TTBXLabelItem + Caption = ' Conversion type: ' + end + object ConversionCombo: TTBXComboBoxItem + EditWidth = 220 + OnChange = ConversionComboChange + DropDownList = True + MinListWidth = 220 + Strings.Strings = ( + 'Convert TB2K>TBX & Upgrade TBX') + OnPopup = ConversionComboPopup + end + end + end + object TBDock2: TTBDock + Left = 0 + Top = 465 + Width = 783 + Height = 9 + Position = dpBottom + end + object TBDock3: TTBDock + Left = 0 + Top = 26 + Width = 197 + Height = 439 + Position = dpLeft + object FilePanel: TTBXDockablePanel + Left = 0 + Top = 0 + Caption = 'Files' + DockedWidth = 193 + SupportedDocks = [dkStandardDock, dkMultiDock] + TabOrder = 0 + Visible = False + object ShellTreeView: TShellTreeView + Left = 0 + Top = 0 + Width = 193 + Height = 417 + AutoContextMenus = False + ObjectTypes = [otFolders, otNonFolders] + Root = 'rfDesktop' + UseShellImages = True + OnAddFolder = ShellTreeViewAddFolder + Align = alClient + AutoRefresh = False + DragMode = dmAutomatic + Indent = 19 + ParentColor = False + ParentShowHint = False + RightClickSelect = True + ShowHint = True + ShowRoot = False + TabOrder = 0 + OnDblClick = ShellTreeViewDblClick + OnEditing = ShellTreeViewEditing + end + end + end + object TBDock4: TTBDock + Left = 577 + Top = 26 + Width = 206 + Height = 439 + Position = dpRight + object Panel1: TTBXDockablePanel + Left = 0 + Top = 0 + Caption = 'Settings' + DockedWidth = 202 + SupportedDocks = [dkStandardDock, dkMultiDock] + TabOrder = 0 + object TBXPageScroller1: TTBXPageScroller + Left = 0 + Top = 0 + Width = 202 + Height = 417 + Align = alClient + AutoRange = True + DoubleBuffered = False + TabOrder = 0 + object TBXLabel1: TTBXLabel + Left = 0 + Top = 0 + Width = 202 + Height = 22 + Align = alTop + Caption = 'Convert components:' + Font.Charset = DEFAULT_CHARSET + Font.Color = clWindowText + Font.Height = -11 + Font.Name = 'Tahoma' + Font.Style = [fsBold] + Margins.Left = 8 + Margins.Top = 8 + Margins.Right = 8 + ParentFont = False + Underline = True + end + object ConversionsPanel: TTBXAlignmentPanel + Left = 0 + Top = 22 + Width = 202 + Height = 33 + Align = alTop + AutoSize = True + Constraints.MinHeight = 8 + Font.Charset = DEFAULT_CHARSET + Font.Color = clWindowText + Font.Height = -9 + Font.Name = 'Tahoma' + Font.Style = [] + Margins.Left = 16 + Margins.Top = 8 + Margins.Right = 8 + Margins.Bottom = 8 + ParentFont = False + TabOrder = 1 + end + object TBXLabel2: TTBXLabel + Left = 0 + Top = 82 + Width = 202 + Height = 22 + Align = alTop + Caption = 'File filter:' + Font.Charset = DEFAULT_CHARSET + Font.Color = clWindowText + Font.Height = -11 + Font.Name = 'Tahoma' + Font.Style = [fsBold] + Margins.Left = 8 + Margins.Top = 8 + Margins.Right = 8 + ParentFont = False + Underline = True + end + object TBXAlignmentPanel1: TTBXAlignmentPanel + Left = 0 + Top = 104 + Width = 202 + Height = 101 + Align = alTop + AutoSize = True + Margins.Left = 16 + Margins.Top = 8 + Margins.Right = 16 + Margins.Bottom = 8 + TabOrder = 3 + object FilterPas: TTBXCheckBox + Left = 16 + Top = 8 + Width = 170 + Height = 17 + Align = alTop + Caption = 'Pascal source (*.pas)' + State = cbChecked + TabOrder = 0 + Wrapping = twEndEllipsis + OnChange = FilterChange + end + object FilterHpp: TTBXCheckBox + Left = 16 + Top = 25 + Width = 170 + Height = 17 + Align = alTop + Caption = 'C++ header files (*.h; *.hpp)' + State = cbChecked + TabOrder = 1 + Wrapping = twEndEllipsis + OnChange = FilterChange + end + object FilterCPP: TTBXCheckBox + Left = 16 + Top = 42 + Width = 170 + Height = 17 + Align = alTop + Caption = 'C++ source (*.cpp)' + State = cbChecked + TabOrder = 2 + Wrapping = twEndEllipsis + OnChange = FilterChange + end + object FilterDFM: TTBXCheckBox + Left = 16 + Top = 59 + Width = 170 + Height = 17 + Align = alTop + Caption = 'Text form files (*.dfm)' + State = cbChecked + TabOrder = 3 + Wrapping = twEndEllipsis + OnChange = FilterChange + end + object FilterBinaryDFM: TTBXCheckBox + Left = 16 + Top = 76 + Width = 170 + Height = 17 + Align = alTop + Caption = 'Binary form files (*.dfm)' + State = cbChecked + TabOrder = 4 + Wrapping = twEndEllipsis + OnChange = FilterChange + end + end + object TBXAlignmentPanel3: TTBXAlignmentPanel + Left = 0 + Top = 55 + Width = 202 + Height = 27 + Align = alTop + AutoSize = True + Margins.Left = 8 + Margins.Right = 8 + Margins.Bottom = 8 + TabOrder = 4 + object TBXToolbar1: TTBXToolbar + Left = 8 + Top = 0 + Width = 186 + Height = 19 + Align = alTop + Caption = 'TBXToolbar1' + ShrinkMode = tbsmWrap + TabOrder = 0 + object TBXItem1: TTBXItem + Caption = 'Select &All' + OnClick = TBXItem1Click + end + object TBXSeparatorItem1: TTBXSeparatorItem + Blank = True + end + object TBXItem2: TTBXItem + Caption = 'Select &None' + OnClick = TBXItem2Click + end + end + end + end + end + end + object Panel2: TPanel + Left = 197 + Top = 26 + Width = 380 + Height = 439 + Align = alClient + TabOrder = 4 + object Memo: TMemo + Left = 1 + Top = 1 + Width = 378 + Height = 326 + Align = alClient + Ctl3D = True + Lines.Strings = ( + 'Waiting for files to convert') + ParentCtl3D = False + TabOrder = 0 + OnDragDrop = MemoDragDrop + OnDragOver = MemoDragOver + end + object Memo1: TMemo + Left = 1 + Top = 327 + Width = 378 + Height = 111 + Align = alBottom + BorderStyle = bsNone + Font.Charset = DEFAULT_CHARSET + Font.Color = clWindowText + Font.Height = -9 + Font.Name = 'Tahoma' + Font.Style = [] + Lines.Strings = ( + 'Usage info:' + ' 1. Choose conversion type, components and file filer' + ' 2. Select files to convert using either of two methods' + + ' 2.1. Drag and drop files with source code and DFM files fr' + + 'om Windows Explorer' + + ' 2.2. Open the Files panel and double click the file to con' + + 'vert' + + ' 3. Original files are automatically saved with extensions ##00' + + '1, ##002, etc.' + ' 4. Manually update '#39'uses'#39' clause in source files') + ParentColor = True + ParentFont = False + TabOrder = 1 + end + end + object TBXSwitcher1: TTBXSwitcher + Theme = 'OfficeXP' + FlatMenuStyle = fmsDisable + Left = 164 + Top = 64 + end + object ImageList1: TImageList + Left = 476 + Top = 8 + Bitmap = { + 494C010102000400040010001000FFFFFFFFFF10FFFFFFFFFFFFFFFF424D3600 + 0000000000003600000028000000400000001000000001002000000000000010 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000080808000800000008080800000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 000000000000000000000000000000000000000000000000000080808000C0C0 + C000808080000000000080000000FFFFFF008000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 00000000000000000000000000000000000000000000FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000C0C0C0000000 + 0000000000000000000080808000800000008080800000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 000000000000000000000000000000000000FFFFFF0000000000FFFFFF00FFFF + FF00C0C0C000FFFFFF0000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000808080000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 00000000000000000000000000008080800000000000FFFFFF0000000000FFFF + FF0000000000FFFFFF0000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000C0C0C0000000 + 0000000000000000000080808000800000008080800000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 00000000000000000000C0C0C000FFFFFF008080800000000000FFFFFF000000 + 0000FFFFFF00FFFFFF0000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 000000000000000000000000000000000000000000000000000080808000C0C0 + C000808080000000000080000000FFFFFF008000000000000000000000000000 + 000000000000000000000000000000000000000000000000000000000000FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF008080800000000000FFFF + FF00000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000C0C0C0000000 + 0000000000000000000080808000800000008080800000000000000000000000 + 000000000000000000000000000000000000000000000000000000000000FFFF + FF0000000000FFFFFF00C0C0C000C0C0C000C0C0C00000000000FFFFFF000000 + 0000FFFFFF00C0C0C00000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000808080000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 000000000000000000000000000000000000000000000000000000000000FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF0000000000FFFFFF0000000000FFFF + FF00FFFFFF000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000C0C0C0000000 + 0000000000000000000080808000800000008080800000000000000000000000 + 000000000000000000000000000000000000000000000000000000000000FFFF + FF0000000000FFFFFF00C0C0C00000000000FFFFFF0000000000C0C0C000C0C0 + C000FFFFFF000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 000000000000000000000000000000000000000000000000000080808000C0C0 + C000808080000000000080000000FFFFFF008000000000000000000000000000 + 000000000000000000000000000000000000000000000000000000000000FFFF + FF00FFFFFF00FFFFFF00FFFFFF008080800000000000FFFFFF00FFFFFF00FFFF + FF00FFFFFF000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000C0C0C0000000 + 0000000000000000000080808000800000008080800000000000000000000000 + 000000000000000000000000000000000000000000000000000000000000FFFF + FF0000000000FFFFFF00C0C0C000C0C0C000C0C0C000C0C0C000C0C0C000C0C0 + C000FFFFFF000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000808080000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 000000000000000000000000000000000000000000000000000000000000FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000080808000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 000000000000000000000000000000000000000000000000000000000000FFFF + FF0000000000FFFFFF00C0C0C000C0C0C000C0C0C000C0C0C000C0C0C000C0C0 + C000FFFFFF000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000080808000C0C0C000C0C0 + C000C0C0C000C0C0C000C0C0C000C0C0C0000000000000000000000000000000 + 000000000000000000000000000000000000000000000000000000000000FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000080808000C0C0C000C0C0 + C000C0C0C000C0C0C000C0C0C000C0C0C0000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000080808000808080008080 + 8000808080008080800080808000808080008080800000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 000000000000000000000000000000000000424D3E000000000000003E000000 + 2800000040000000100000000100010000000000800000000000000000000000 + 000000000000000000000000FFFFFF00FC7FFF8000000000C441FF0000000000 + DC7FFE0100000000DFFFFE0100000000DC7FC00100000000C441C00300000000 + DC7FC00300000000DFFFC00300000000DC7FC00300000000C441C00300000000 + DC7FC00300000000DFFFC00300000000807FC00300000000807FC00300000000 + 807FC00300000000807FFFFF0000000000000000000000000000000000000000 + 000000000000} + end + object XPManifest1: TXPManifest + Left = 520 + Top = 8 + end +end diff --git a/official/2.1.6+2.1.beta1/TBX/Converter/MainUnit.pas b/official/2.1.6+2.1.beta1/TBX/Converter/MainUnit.pas new file mode 100644 index 0000000..4513026 --- /dev/null +++ b/official/2.1.6+2.1.beta1/TBX/Converter/MainUnit.pas @@ -0,0 +1,527 @@ +unit MainUnit; + +interface + +uses + Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, + Dialogs, Contnrs, TBX, TBXDkPanels, TB2Dock, ExtCtrls, TB2Item, + TB2Toolbar, StdCtrls, ComCtrls, TBXOfficeXPTheme, TBXSwitcher, + TB2ToolWindow, TB2ExtItems, TBXExtItems, ShellCtrls, ImgList, XPMan; + + +const + CM_INIT = WM_USER + 229; + CDatFile = 'conversions.ini'; + +type + TConversion = class + OldClassName: string; + NewClassName: string; + CheckBox: TTBXCheckBox; + end; + + { TConverterForm } + TConverterForm = class(TForm) + TBDock1: TTBDock; + TBDock2: TTBDock; + TBDock3: TTBDock; + TBDock4: TTBDock; + Panel1: TTBXDockablePanel; + ConversionsPanel: TTBXAlignmentPanel; + TBXLabel1: TTBXLabel; + TBXLabel2: TTBXLabel; + TBXAlignmentPanel1: TTBXAlignmentPanel; + FilterPas: TTBXCheckBox; + FilterHpp: TTBXCheckBox; + FilterCPP: TTBXCheckBox; + FilterDFM: TTBXCheckBox; + FilterBinaryDFM: TTBXCheckBox; + TBXToolbar1: TTBXToolbar; + TBXItem1: TTBXItem; + TBXItem2: TTBXItem; + TBXSeparatorItem1: TTBXSeparatorItem; + TBXToolbar2: TTBXToolbar; + TBXVisibilityToggleItem1: TTBXVisibilityToggleItem; + Memo: TMemo; + TBXSwitcher1: TTBXSwitcher; + TBXPageScroller1: TTBXPageScroller; + TBXAlignmentPanel3: TTBXAlignmentPanel; + ConversionCombo: TTBXComboBoxItem; + TBXLabelItem1: TTBXLabelItem; + Panel2: TPanel; + Memo1: TMemo; + FilePanel: TTBXDockablePanel; + ShellTreeView: TShellTreeView; + TBXVisibilityToggleItem2: TTBXVisibilityToggleItem; + ImageList1: TImageList; + TBXSeparatorItem3: TTBXSeparatorItem; + XPManifest1: TXPManifest; + procedure FormCreate(Sender: TObject); + procedure FormDestroy(Sender: TObject); + procedure TBXItem1Click(Sender: TObject); + procedure TBXItem2Click(Sender: TObject); + procedure ConversionComboPopup(Sender: TTBCustomItem; FromLink: Boolean); + procedure ConversionComboChange(Sender: TObject; const Text: String); + procedure ShellTreeViewAddFolder(Sender: TObject; AFolder: TShellFolder; var CanAdd: Boolean); + procedure FilterChange(Sender: TObject); + procedure ShellTreeViewDblClick(Sender: TObject); + procedure TBXVisibilityToggleItem2Click(Sender: TObject); + procedure MemoDragDrop(Sender, Source: TObject; X, Y: Integer); + procedure MemoDragOver(Sender, Source: TObject; X, Y: Integer; + State: TDragState; var Accept: Boolean); + procedure ShellTreeViewEditing(Sender: TObject; Node: TTreeNode; + var AllowEdit: Boolean); + private + FConversions: TObjectList; + procedure CMInit(var Message: TMessage); message CM_INIT; + procedure WMDropFiles(var Message: TWMDropFiles); message WM_DROPFILES; + protected + procedure ShowConversions; + procedure GetConversionTypes(L: TStrings); + procedure GetConversions(const ConvType: string); + public + procedure ProcessFiles(FileNames: TStringList); + end; + +var + ConverterForm: TConverterForm; + +implementation + +uses + ShellApi; + +const + CNameFirst = ['a'..'z', 'A'..'Z', '_']; + CNameChar = ['a'..'z', 'A'..'Z', '_', '0'..'9']; + +type + TTreeViewAccess = class(TCustomTreeView); + +function WordReplace(const Src, OldWord, NewWord: string): string; +var + P, PStart: PChar; + S: string; +begin + Result := ''; + P := PChar(Src); + PStart := P; + while P^ <> #0 do + begin + if P^ in CNameFirst then + begin + SetString(S, PStart, P - PStart); + Result := Result + S; + PStart := P; + Inc(P); + while P^ in CNameChar do Inc(P); + SetString(S, PStart, P - PStart); + if SameText(S, OldWord) then S := NewWord; + Result := Result + S; + PStart := P; + end + else Inc(P); + end; + if P <> PStart then + begin + SetString(S, PStart, P - PStart); + Result := Result + S; + end; +end; + +{$R *.dfm} + +{ TConverterForm } + +procedure TConverterForm.CMInit(var Message: TMessage); +begin + DragAcceptFiles(Handle, True); + ShowConversions; + TTreeViewAccess(ShellTreeView).MultiSelect := True; + TTreeViewAccess(ShellTreeView).MultiSelectStyle := [msControlSelect, msShiftSelect, msSiblingOnly]; +end; + +procedure TConverterForm.FormCreate(Sender: TObject); +begin + FConversions := TObjectList.Create; + GetConversionTypes(ConversionCombo.Strings); + if ConversionCombo.Strings.Count = 0 then raise Exception.Create('Invalid conversion settings'); + ConversionCombo.ItemIndex := 0; + GetConversions(ConversionCombo.Strings[0]); + PostMessage(Handle, CM_INIT, 0, 0); +end; + +procedure TConverterForm.FormDestroy(Sender: TObject); +begin + FConversions.Free; +end; + +procedure TConverterForm.ProcessFiles(FileNames: TStringList); +var + I, J: Integer; + S, E: string; + BinaryStream: TFileStream; + StringStream: TStringStream; + S1, S2: string; + DFM, BinaryDFM: Boolean; + + function IsTextDFM(const FN: string): Boolean; + var + Stream: TFileStream; + Buffer: array [0..7] of Char; + begin + Stream := TFileStream.Create(FN, fmOpenRead); + FillChar(Buffer[0], 8, 0); + Stream.Read(Buffer[0], 7); + Result := SameText(Buffer, 'object '); + Stream.Free; + end; + + function IsBinaryDFM(const FN: string): Boolean; + var + Stream: TFileStream; + TS: TStream; + begin + Result := True; Exit; + Stream := TFileStream.Create(FN, fmOpenRead); + try + TS := TMemoryStream.Create; + try + try + Result := True; + ObjectResourceToText(Stream, TS); + except + Result := False; + end; + finally + TS.Free; + end; + finally + Stream.Free; + end; + end; + + function GetBackupFileName(F: string): string; + var + I: Integer; + begin + I := 0; + repeat + Inc(I); + Result := Format('%s.###%.3d', [F, I]); + until not FileExists(Result); + end; + +begin + { Filter files } + for I := FileNames.Count - 1 downto 0 do + begin + S := FileNames[I]; + E := ExtractFileExt(S); + if (SameText(E, '.pas') and FilterPAS.Checked) or + ((SameText(E, '.h') or SameText(E, '.hpp')) and FilterHPP.Checked) or + (SameText(E, '.cpp') and FilterCPP.Checked) or + (SameText(E, '.dfm') and FilterDFM.Checked and IsTextDFM(S)) or + (SameText(E, '.dfm') and FilterBinaryDFM.Checked and IsBinaryDFM(S)) then + Continue + else + FileNames.Delete(I); + end; + if FileNames.Count = 0 then Memo.Lines.Add('No files to process'); + + { Get each file as string } + for I := FileNames.Count - 1 downto 0 do + begin + DFM := SameText(ExtractFileExt(FileNames[I]), '.dfm'); + if DFM then BinaryDFM := not IsTextDFM(FileNames[I]) else BinaryDFM := False; + if DFM and BinaryDFM then + begin + BinaryStream := TFileStream.Create(FileNames[I], fmOpenRead); + try + StringStream := TStringStream.Create(''); + try + ObjectResourceToText(BinaryStream, StringStream); + S := StringStream.DataString; + finally + StringStream.Free; + end; + finally + BinaryStream.Free; + end; + end + else + begin + with TFileStream.Create(FileNames[I], fmOpenRead) do + try + SetLength(S, Size); + ReadBuffer(S[1], Size); + finally + Free; + end; + end; + + Memo.Lines.Add('Converting ' + FileNames[I]); + { Now S contains text representation of the file } + for J := 0 to FConversions.Count - 1 do + with TConversion(FConversions[J]) do + if CheckBox.Checked then + if DFM then + begin + S1 := ': ' + OldClassName + #13; + S2 := ': ' + NewClassName + #13; + S := StringReplace(S, S1, S2, [rfReplaceAll, rfIgnoreCase]); + end + else + begin + S := WordReplace(S, OldClassName, NewClassName); + end; + + E := GetBackupFileName(FileNames[I]); + Memo.Lines.Add('Saving original file to ' + E); + RenameFile(FileNames[I], E); + + if DFM and BinaryDFM then + begin + BinaryStream := TFileStream.Create(FileNames[I], fmCreate); + try + StringStream := TStringStream.Create(S); + try + ObjectTextToResource(StringStream, BinaryStream); + finally + StringStream.Free; + end; + finally + BinaryStream.Free; + end; + end + else + begin + with TFileStream.Create(FileNames[I], fmCreate) do + try + WriteBuffer(S[1], Length(S)); + finally + Free; + end; + end; + end; +end; + +procedure TConverterForm.ShowConversions; +var + I: Integer; + C: TConversion; + CB: TTBXCheckBox; +begin + ConversionsPanel.DisableAlign; + for I := ConversionsPanel.ControlCount - 1 downto 0 do + ConversionsPanel.Controls[I].Free; + for I := 0 to FConversions.Count - 1 do + begin + C := TConversion(FConversions[I]); + CB := TTBXCheckBox.Create(Self); + CB.Caption := C.OldClassName + ' > ' + C.NewClassName; + CB.Wrapping := twEndEllipsis; + CB.Top := 10000; + CB.Parent := ConversionsPanel; + CB.Align := alTop; + CB.Checked := True; + C.CheckBox := CB; + end; + ConversionsPanel.EnableAlign; + ConversionsPanel.Realign; +end; + +procedure TConverterForm.WMDropFiles(var Message: TWMDropFiles); +var + SL: TStringList; + Buffer: array [0..1024] of Char; + NumFiles, I: Integer; + S: string; +begin + SL := TStringList.Create; + try + NumFiles := DragQueryFile(Message.Drop, $FFFFFFFF, nil, 0); + for I := 0 to NumFiles - 1 do + begin + DragQueryFile(Message.Drop,I, Buffer, SizeOf(Buffer)); + S := StrPas(Buffer); + if FileExists(S) then SL.Add(S); + end; + if SL.Count > 0 then ProcessFiles(SL); + finally + SL.Free; + end; +end; + +procedure TConverterForm.TBXItem1Click(Sender: TObject); +var + I: Integer; +begin + for I := 0 to FConversions.Count - 1 do + TConversion(FConversions[I]).CheckBox.Checked := True; +end; + +procedure TConverterForm.TBXItem2Click(Sender: TObject); +var + I: Integer; +begin + for I := 0 to FConversions.Count - 1 do + TConversion(FConversions[I]).CheckBox.Checked := False; +end; + +procedure TConverterForm.ConversionComboPopup(Sender: TTBCustomItem; FromLink: Boolean); +begin + GetConversionTypes(ConversionCombo.Strings); +end; + +procedure TConverterForm.GetConversionTypes(L: TStrings); +var + SL: TStringList; + S: string; + I, J: Integer; +begin + SL := TStringList.Create; + try + SL.LoadFromFile(CDatFile); + L.Clear; + for I := 0 to SL.Count - 1 do + begin + S := Trim(SL[I]); + if (Length(S) > 3) and (S[1] = '[') and (S[Length(S)] = ']') then + begin + S := Copy(S, 2, Length(S) - 2); + L.Add(S); + end; + end; + finally + SL.Free; + end; +end; + +procedure TConverterForm.ConversionComboChange(Sender: TObject; const Text: String); +begin + GetConversions(Text); + ShowConversions; +end; + +procedure TConverterForm.GetConversions(const ConvType: string); +var + SL: TStringList; + S, S1, S2: string; + P: Integer; + C: TConversion; + I: Integer; +begin + SL := TStringList.Create; + try + SL.LoadFromFile(CDatFile); + I := 0; + while I < SL.Count - 1 do + begin + S := Trim(SL[I]); + if (Length(S) > 3) and (S[1] = '[') and (S[Length(S)] = ']') and + SameText(Copy(S, 2, Length(S) - 2), ConvType) then Break + else Inc(I); + end; + + FConversions.Clear; + Inc(I); + while I < SL.Count do + begin + S := Trim(SL[I]); + Inc(I); + if (Length(S) = 0) or (S[1] in [';', '''', '/', '%']) then Continue; + if S[1] = '[' then Break; + P := Pos('->', S); + if P < 2 then raise Exception.Create('Invalid conversion settings'); + S1 := Trim(Copy(S, 1, P - 1)); + S2 := Trim(Copy(S, P + 2, Length(S))); + if (Length(S1) = 0) or (Length(S2) = 0) then raise Exception.Create('Invalid conversion settings'); + C := TConversion.Create; + FConversions.Add(C); + C.OldClassName := S1; + C.NewClassName := S2; + end; + finally + SL.Free; + end; +end; + +procedure TConverterForm.ShellTreeViewAddFolder(Sender: TObject; + AFolder: TShellFolder; var CanAdd: Boolean); +var + Ext: string; +begin + if not AFolder.IsFolder then + begin + Ext := LowerCase(ExtractFileExt(AFolder.DisplayName)); + CanAdd := + (FilterPas.Checked and (Ext = '.pas')) or + (FilterHpp.Checked and ((Ext = '.h') or (Ext = '.hpp'))) or + (FilterCpp.Checked and (Ext = '.cpp')) or + ((FilterDfm.Checked or FilterBinaryDfm.Checked) and (Ext = '.dfm')); + end; +end; + +procedure TConverterForm.FilterChange(Sender: TObject); +begin + if FilePanel.Visible then + ShellTreeView.Refresh(ShellTreeView.Items[0]); +end; + +procedure TConverterForm.ShellTreeViewDblClick(Sender: TObject); +var + SL: TStringList; +begin + SL := TStringList.Create; + try + SL.Add(ShellTreeView.SelectedFolder.PathName); + if FileExists(SL[0]) then ProcessFiles(SL); + finally + SL.Free; + end; +end; + +procedure TConverterForm.TBXVisibilityToggleItem2Click(Sender: TObject); +begin + if FilePanel.Visible then + ShellTreeView.Refresh(ShellTreeView.Items[0]); +end; + +procedure TConverterForm.MemoDragDrop(Sender, Source: TObject; X, Y: Integer); +var + I: Integer; + SL: TStringList; +begin + if Source <> ShellTreeView then Exit; + SL := TStringList.Create; + try + for I := 0 to ShellTreeView.SelectionCount - 1 do + SL.Add(TShellFolder(ShellTreeView.Selections[I].Data).PathName); + ProcessFiles(SL); + finally + SL.Free; + end; +end; + +procedure TConverterForm.MemoDragOver(Sender, Source: TObject; X, Y: Integer; + State: TDragState; var Accept: Boolean); +var + I: Integer; +begin + if Source <> ShellTreeView then Exit; + for I := 0 to ShellTreeView.SelectionCount - 1 do + if not FileExists(TShellFolder(ShellTreeView.Selections[I].Data).PathName) then + begin + Accept := False; + Break; + end; +end; + +procedure TConverterForm.ShellTreeViewEditing(Sender: TObject; + Node: TTreeNode; var AllowEdit: Boolean); +begin + AllowEdit := False; +end; + +end. diff --git a/official/2.1.6+2.1.beta1/TBX/Converter/TBXConverter.dpr b/official/2.1.6+2.1.beta1/TBX/Converter/TBXConverter.dpr new file mode 100644 index 0000000..4099734 --- /dev/null +++ b/official/2.1.6+2.1.beta1/TBX/Converter/TBXConverter.dpr @@ -0,0 +1,14 @@ +program TBXConverter; + +uses + Forms, + MainUnit in 'MainUnit.pas' {ConverterForm}; + +{$R *.res} + +begin + Application.Initialize; + Application.Title := 'TBX Converter'; + Application.CreateForm(TConverterForm, ConverterForm); + Application.Run; +end. diff --git a/official/2.1.6+2.1.beta1/TBX/Converter/TBXConverter.exe b/official/2.1.6+2.1.beta1/TBX/Converter/TBXConverter.exe new file mode 100644 index 0000000..e8b01b7 Binary files /dev/null and b/official/2.1.6+2.1.beta1/TBX/Converter/TBXConverter.exe differ diff --git a/official/2.1.6+2.1.beta1/TBX/Converter/TBXConverter.res b/official/2.1.6+2.1.beta1/TBX/Converter/TBXConverter.res new file mode 100644 index 0000000..e9d41d0 Binary files /dev/null and b/official/2.1.6+2.1.beta1/TBX/Converter/TBXConverter.res differ diff --git a/official/2.1.6+2.1.beta1/TBX/Converter/conversions.ini b/official/2.1.6+2.1.beta1/TBX/Converter/conversions.ini new file mode 100644 index 0000000..cbc975e --- /dev/null +++ b/official/2.1.6+2.1.beta1/TBX/Converter/conversions.ini @@ -0,0 +1,69 @@ +[Upgrade TBX] +'Upgrade TBX components: +TTBXList -> TTBXStringList +TTBXComboItem -> TTBXDropDownItem +TTBXComboList -> TTBXComboBoxItem +TDPDockPosition -> TTBDockPosition +TDPDockableTo -> TTBDockableTo +tdpLeft -> dpLeft +tdpRight -> dpRight + + +[Convert TB2K>TBX + Upgrade TBX] +'Updgrade TBX components: +TTBXList -> TTBXStringList +TTBXComboItem -> TTBXDropDownItem +TTBXComboList -> TTBXComboBoxItem +TDPDockPosition -> TTBDockPosition +TDPDockableTo -> TTBDockableTo +tdpLeft -> dpLeft +tdpRight -> dpRight +'Convert TB2K controls: +TTBDock -> TTBXDock +TTBToolbar -> TTBXToolbar +TTBToolWindow -> TTBXToolWindow +TTBPopupMenu -> TTBXPopupMenu +TTBMRUList -> TTBXMRUList +TTBMDIHandler -> TTBXMDIHandler +'Convert TB2K items: +TTBItem -> TTBXItem +TTBSeparatorItem -> TTBXSeparatorItem +TTBSubmenuItem -> TTBXSubmenuItem +TTBVisibilityToggleItem -> TTBXVisibilityToggleItem +TTBMRUListItem -> TTBXMRUListItem +TTBMDIWindowItem -> TTBXMDIWindowItem + + +[Convert TB2K>TBX] +'Convert TB2K controls: +TTBDock -> TTBXDock +TTBToolbar -> TTBXToolbar +TTBToolWindow -> TTBXToolWindow +TTBPopupMenu -> TTBXPopupMenu +TTBMRUList -> TTBXMRUList +TTBMDIHandler -> TTBXMDIHandler +'Convert TB2K items: +TTBItem -> TTBXItem +TTBSeparatorItem -> TTBXSeparatorItem +TTBSubmenuItem -> TTBXSubmenuItem +TTBVisibilityToggleItem -> TTBXVisibilityToggleItem +TTBMRUListItem -> TTBXMRUListItem +TTBMDIWindowItem -> TTBXMDIWindowItem + + +[Convert TBX>TB2K] +'Convert TBX controls: +TTBXDock -> TTBDock +TTBXToolbar -> TTBToolbar +TTBXToolWindow -> TTBToolWindow +TTBXPopupMenu -> TTBPopupMenu +TTBXMRUList -> TTBMRUList +TTBXMDIHandler -> TTBMDIHandler +'Convert TBX items: +TTBXItem -> TTBItem +TTBXSeparatorItem -> TTBSeparatorItem +TTBXSubmenuItem -> TTBSubmenuItem +TTBXVisibilityToggleItem -> TTBVisibilityToggleItem +TTBXMRUListItem -> TTBMRUListItem +TTBXMDIWindowItem -> TTBMDIWindowItem + diff --git a/official/2.1.6+2.1.beta1/TBX/DTM/Project1.exe b/official/2.1.6+2.1.beta1/TBX/DTM/Project1.exe new file mode 100644 index 0000000..c240153 Binary files /dev/null and b/official/2.1.6+2.1.beta1/TBX/DTM/Project1.exe differ diff --git a/official/2.1.6+2.1.beta1/TBX/DTM/Themes/TBXAluminum_d7.tbxt b/official/2.1.6+2.1.beta1/TBX/DTM/Themes/TBXAluminum_d7.tbxt new file mode 100644 index 0000000..723944a Binary files /dev/null and b/official/2.1.6+2.1.beta1/TBX/DTM/Themes/TBXAluminum_d7.tbxt differ diff --git a/official/2.1.6+2.1.beta1/TBX/DTM/Themes/TBXAthen_d7.tbxt b/official/2.1.6+2.1.beta1/TBX/DTM/Themes/TBXAthen_d7.tbxt new file mode 100644 index 0000000..4785407 Binary files /dev/null and b/official/2.1.6+2.1.beta1/TBX/DTM/Themes/TBXAthen_d7.tbxt differ diff --git a/official/2.1.6+2.1.beta1/TBX/DTM/Themes/TBXDream_d7.tbxt b/official/2.1.6+2.1.beta1/TBX/DTM/Themes/TBXDream_d7.tbxt new file mode 100644 index 0000000..6b9cf75 Binary files /dev/null and b/official/2.1.6+2.1.beta1/TBX/DTM/Themes/TBXDream_d7.tbxt differ diff --git a/official/2.1.6+2.1.beta1/TBX/DTM/Themes/TBXEos_d7.tbxt b/official/2.1.6+2.1.beta1/TBX/DTM/Themes/TBXEos_d7.tbxt new file mode 100644 index 0000000..a01415f Binary files /dev/null and b/official/2.1.6+2.1.beta1/TBX/DTM/Themes/TBXEos_d7.tbxt differ diff --git a/official/2.1.6+2.1.beta1/TBX/DTM/Themes/TBXMacOSX_d7.tbxt b/official/2.1.6+2.1.beta1/TBX/DTM/Themes/TBXMacOSX_d7.tbxt new file mode 100644 index 0000000..b34c654 Binary files /dev/null and b/official/2.1.6+2.1.beta1/TBX/DTM/Themes/TBXMacOSX_d7.tbxt differ diff --git a/official/2.1.6+2.1.beta1/TBX/DTM/Themes/TBXMonaiXP_d7.tbxt b/official/2.1.6+2.1.beta1/TBX/DTM/Themes/TBXMonaiXP_d7.tbxt new file mode 100644 index 0000000..77ed1d2 Binary files /dev/null and b/official/2.1.6+2.1.beta1/TBX/DTM/Themes/TBXMonaiXP_d7.tbxt differ diff --git a/official/2.1.6+2.1.beta1/TBX/DTM/Themes/TBXMonai_d7.tbxt b/official/2.1.6+2.1.beta1/TBX/DTM/Themes/TBXMonai_d7.tbxt new file mode 100644 index 0000000..f35f740 Binary files /dev/null and b/official/2.1.6+2.1.beta1/TBX/DTM/Themes/TBXMonai_d7.tbxt differ diff --git a/official/2.1.6+2.1.beta1/TBX/DTM/Themes/TBXNexos2_d7.tbxt b/official/2.1.6+2.1.beta1/TBX/DTM/Themes/TBXNexos2_d7.tbxt new file mode 100644 index 0000000..6b16bcd Binary files /dev/null and b/official/2.1.6+2.1.beta1/TBX/DTM/Themes/TBXNexos2_d7.tbxt differ diff --git a/official/2.1.6+2.1.beta1/TBX/DTM/Themes/TBXNexos3_d7.tbxt b/official/2.1.6+2.1.beta1/TBX/DTM/Themes/TBXNexos3_d7.tbxt new file mode 100644 index 0000000..284e5d9 Binary files /dev/null and b/official/2.1.6+2.1.beta1/TBX/DTM/Themes/TBXNexos3_d7.tbxt differ diff --git a/official/2.1.6+2.1.beta1/TBX/DTM/Themes/TBXNexos4_d7.tbxt b/official/2.1.6+2.1.beta1/TBX/DTM/Themes/TBXNexos4_d7.tbxt new file mode 100644 index 0000000..169894b Binary files /dev/null and b/official/2.1.6+2.1.beta1/TBX/DTM/Themes/TBXNexos4_d7.tbxt differ diff --git a/official/2.1.6+2.1.beta1/TBX/DTM/Themes/TBXNexos5_d7.tbxt b/official/2.1.6+2.1.beta1/TBX/DTM/Themes/TBXNexos5_d7.tbxt new file mode 100644 index 0000000..9587af9 Binary files /dev/null and b/official/2.1.6+2.1.beta1/TBX/DTM/Themes/TBXNexos5_d7.tbxt differ diff --git a/official/2.1.6+2.1.beta1/TBX/DTM/Themes/TBXNexosX_d7.tbxt b/official/2.1.6+2.1.beta1/TBX/DTM/Themes/TBXNexosX_d7.tbxt new file mode 100644 index 0000000..32f61b5 Binary files /dev/null and b/official/2.1.6+2.1.beta1/TBX/DTM/Themes/TBXNexosX_d7.tbxt differ diff --git a/official/2.1.6+2.1.beta1/TBX/DTM/Themes/TBXOffice11Adaptive_d7.tbxt b/official/2.1.6+2.1.beta1/TBX/DTM/Themes/TBXOffice11Adaptive_d7.tbxt new file mode 100644 index 0000000..1aad83c Binary files /dev/null and b/official/2.1.6+2.1.beta1/TBX/DTM/Themes/TBXOffice11Adaptive_d7.tbxt differ diff --git a/official/2.1.6+2.1.beta1/TBX/DTM/Themes/TBXOffice11XP_d7.tbxt b/official/2.1.6+2.1.beta1/TBX/DTM/Themes/TBXOffice11XP_d7.tbxt new file mode 100644 index 0000000..ca0b849 Binary files /dev/null and b/official/2.1.6+2.1.beta1/TBX/DTM/Themes/TBXOffice11XP_d7.tbxt differ diff --git a/official/2.1.6+2.1.beta1/TBX/DTM/Themes/TBXOfficeC_d7.tbxt b/official/2.1.6+2.1.beta1/TBX/DTM/Themes/TBXOfficeC_d7.tbxt new file mode 100644 index 0000000..c467e1e Binary files /dev/null and b/official/2.1.6+2.1.beta1/TBX/DTM/Themes/TBXOfficeC_d7.tbxt differ diff --git a/official/2.1.6+2.1.beta1/TBX/DTM/Themes/TBXOfficeK_d7.tbxt b/official/2.1.6+2.1.beta1/TBX/DTM/Themes/TBXOfficeK_d7.tbxt new file mode 100644 index 0000000..be19ae9 Binary files /dev/null and b/official/2.1.6+2.1.beta1/TBX/DTM/Themes/TBXOfficeK_d7.tbxt differ diff --git a/official/2.1.6+2.1.beta1/TBX/DTM/Themes/TBXRelifer_d7.tbxt b/official/2.1.6+2.1.beta1/TBX/DTM/Themes/TBXRelifer_d7.tbxt new file mode 100644 index 0000000..cdb2da4 Binary files /dev/null and b/official/2.1.6+2.1.beta1/TBX/DTM/Themes/TBXRelifer_d7.tbxt differ diff --git a/official/2.1.6+2.1.beta1/TBX/DTM/Themes/TBXRoma_d7.tbxt b/official/2.1.6+2.1.beta1/TBX/DTM/Themes/TBXRoma_d7.tbxt new file mode 100644 index 0000000..49cdf78 Binary files /dev/null and b/official/2.1.6+2.1.beta1/TBX/DTM/Themes/TBXRoma_d7.tbxt differ diff --git a/official/2.1.6+2.1.beta1/TBX/DTM/Themes/TBXSentimoX_d7.tbxt b/official/2.1.6+2.1.beta1/TBX/DTM/Themes/TBXSentimoX_d7.tbxt new file mode 100644 index 0000000..b9666fe Binary files /dev/null and b/official/2.1.6+2.1.beta1/TBX/DTM/Themes/TBXSentimoX_d7.tbxt differ diff --git a/official/2.1.6+2.1.beta1/TBX/DTM/Themes/TBXStripes_d7.tbxt b/official/2.1.6+2.1.beta1/TBX/DTM/Themes/TBXStripes_d7.tbxt new file mode 100644 index 0000000..8edbdf5 Binary files /dev/null and b/official/2.1.6+2.1.beta1/TBX/DTM/Themes/TBXStripes_d7.tbxt differ diff --git a/official/2.1.6+2.1.beta1/TBX/DTM/Themes/TBXTristan2_d7.tbxt b/official/2.1.6+2.1.beta1/TBX/DTM/Themes/TBXTristan2_d7.tbxt new file mode 100644 index 0000000..2a9a044 Binary files /dev/null and b/official/2.1.6+2.1.beta1/TBX/DTM/Themes/TBXTristan2_d7.tbxt differ diff --git a/official/2.1.6+2.1.beta1/TBX/DTM/Themes/TBXTristan_d7.tbxt b/official/2.1.6+2.1.beta1/TBX/DTM/Themes/TBXTristan_d7.tbxt new file mode 100644 index 0000000..35d3a4c Binary files /dev/null and b/official/2.1.6+2.1.beta1/TBX/DTM/Themes/TBXTristan_d7.tbxt differ diff --git a/official/2.1.6+2.1.beta1/TBX/DTM/Themes/TBXXito_d7.tbxt b/official/2.1.6+2.1.beta1/TBX/DTM/Themes/TBXXito_d7.tbxt new file mode 100644 index 0000000..bf86278 Binary files /dev/null and b/official/2.1.6+2.1.beta1/TBX/DTM/Themes/TBXXito_d7.tbxt differ diff --git a/official/2.1.6+2.1.beta1/TBX/DTM/Themes/Theme.ini b/official/2.1.6+2.1.beta1/TBX/DTM/Themes/Theme.ini new file mode 100644 index 0000000..9b76c68 --- /dev/null +++ b/official/2.1.6+2.1.beta1/TBX/DTM/Themes/Theme.ini @@ -0,0 +1,3 @@ +[ActiveTheme] +FileName=D:\Source\Database Apps\rmDMS\Application\Themes\TBXTristan_d7.tbxt +ThemeName=Tristan diff --git a/official/2.1.6+2.1.beta1/TBX/DTM/tbx_d7.bpl b/official/2.1.6+2.1.beta1/TBX/DTM/tbx_d7.bpl new file mode 100644 index 0000000..5b6ba8e Binary files /dev/null and b/official/2.1.6+2.1.beta1/TBX/DTM/tbx_d7.bpl differ diff --git a/official/2.1.6+2.1.beta1/TBX/DTMCtrl/TBXDTMCtrl_d6.dpk b/official/2.1.6+2.1.beta1/TBX/DTMCtrl/TBXDTMCtrl_d6.dpk new file mode 100644 index 0000000..461abfe --- /dev/null +++ b/official/2.1.6+2.1.beta1/TBX/DTMCtrl/TBXDTMCtrl_d6.dpk @@ -0,0 +1,38 @@ +package TBXDTMCtrl_d6; + +{$R *.res} +{$R 'TBX_DTM.dcr'} +{$ALIGN 8} +{$ASSERTIONS ON} +{$BOOLEVAL OFF} +{$DEBUGINFO ON} +{$EXTENDEDSYNTAX ON} +{$IMPORTEDDATA ON} +{$IOCHECKS ON} +{$LOCALSYMBOLS ON} +{$LONGSTRINGS ON} +{$OPENSTRINGS ON} +{$OPTIMIZATION ON} +{$OVERFLOWCHECKS OFF} +{$RANGECHECKS OFF} +{$REFERENCEINFO ON} +{$SAFEDIVIDE OFF} +{$STACKFRAMES OFF} +{$TYPEDADDRESS OFF} +{$VARSTRINGCHECKS ON} +{$WRITEABLECONST OFF} +{$MINENUMSIZE 1} +{$IMAGEBASE $400000} +{$IMPLICITBUILD OFF} + +requires + rtl, + vcl, + tbx_d6, + tb2k_d6; + +contains + TBXDTMForm in 'TBXDTMForm.pas' {frmTBXDTM}, + TBX_DTM in 'TBX_DTM.pas'; + +end. diff --git a/official/2.1.6+2.1.beta1/TBX/DTMCtrl/TBXDTMCtrl_d6.res b/official/2.1.6+2.1.beta1/TBX/DTMCtrl/TBXDTMCtrl_d6.res new file mode 100644 index 0000000..4e695e9 Binary files /dev/null and b/official/2.1.6+2.1.beta1/TBX/DTMCtrl/TBXDTMCtrl_d6.res differ diff --git a/official/2.1.6+2.1.beta1/TBX/DTMCtrl/TBXDTMCtrl_d7.cfg b/official/2.1.6+2.1.beta1/TBX/DTMCtrl/TBXDTMCtrl_d7.cfg new file mode 100644 index 0000000..4d4b4ea --- /dev/null +++ b/official/2.1.6+2.1.beta1/TBX/DTMCtrl/TBXDTMCtrl_d7.cfg @@ -0,0 +1,42 @@ +-$A8 +-$B- +-$C+ +-$D+ +-$E- +-$F- +-$G+ +-$H+ +-$I+ +-$J- +-$K- +-$L+ +-$M- +-$N+ +-$O+ +-$P+ +-$Q- +-$R- +-$S- +-$T- +-$U- +-$V+ +-$W- +-$X+ +-$YD +-$Z1 +-cg +-AWinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE; +-H+ +-W+ +-M +-$M16384,1048576 +-K$00400000 +-LE"c:\archivos de programa\borland\delphi7\Projects\Bpl" +-LN"c:\archivos de programa\borland\delphi7\Projects\Bpl" +-U"..\..\Lib\D7" +-O"..\..\Lib\D7" +-I"..\..\Lib\D7" +-R"..\..\Lib\D7" +-w-UNSAFE_TYPE +-w-UNSAFE_CODE +-w-UNSAFE_CAST diff --git a/official/2.1.6+2.1.beta1/TBX/DTMCtrl/TBXDTMCtrl_d7.dof b/official/2.1.6+2.1.beta1/TBX/DTMCtrl/TBXDTMCtrl_d7.dof new file mode 100644 index 0000000..12c6f6d --- /dev/null +++ b/official/2.1.6+2.1.beta1/TBX/DTMCtrl/TBXDTMCtrl_d7.dof @@ -0,0 +1,150 @@ +[FileVersion] +Version=7.0 +[Compiler] +A=8 +B=0 +C=1 +D=1 +E=0 +F=0 +G=1 +H=1 +I=1 +J=0 +K=0 +L=1 +M=0 +N=1 +O=1 +P=1 +Q=0 +R=0 +S=0 +T=0 +U=0 +V=1 +W=0 +X=1 +Y=1 +Z=1 +ShowHints=1 +ShowWarnings=1 +UnitAliases=WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE; +NamespacePrefix= +SymbolDeprecated=1 +SymbolLibrary=1 +SymbolPlatform=1 +UnitLibrary=1 +UnitPlatform=1 +UnitDeprecated=1 +HResultCompat=1 +HidingMember=1 +HiddenVirtual=1 +Garbage=1 +BoundsError=1 +ZeroNilCompat=1 +StringConstTruncated=1 +ForLoopVarVarPar=1 +TypedConstVarPar=1 +AsgToTypedConst=1 +CaseLabelRange=1 +ForVariable=1 +ConstructingAbstract=1 +ComparisonFalse=1 +ComparisonTrue=1 +ComparingSignedUnsigned=1 +CombiningSignedUnsigned=1 +UnsupportedConstruct=1 +FileOpen=1 +FileOpenUnitSrc=1 +BadGlobalSymbol=1 +DuplicateConstructorDestructor=1 +InvalidDirective=1 +PackageNoLink=1 +PackageThreadVar=1 +ImplicitImport=1 +HPPEMITIgnored=1 +NoRetVal=1 +UseBeforeDef=1 +ForLoopVarUndef=1 +UnitNameMismatch=1 +NoCFGFileFound=1 +MessageDirective=1 +ImplicitVariants=1 +UnicodeToLocale=1 +LocaleToUnicode=1 +ImagebaseMultiple=1 +SuspiciousTypecast=1 +PrivatePropAccessor=1 +UnsafeType=0 +UnsafeCode=0 +UnsafeCast=0 +[Linker] +MapFile=0 +OutputObjs=0 +ConsoleApp=1 +DebugInfo=0 +RemoteSymbols=0 +MinStackSize=16384 +MaxStackSize=1048576 +ImageBase=4194304 +ExeDescription= +[Directories] +OutputDir= +UnitOutputDir= +PackageDLLOutputDir= +PackageDCPOutputDir= +SearchPath=..\..\Lib\D7 +Packages=vcl;rtl;vclx;indy;inet;xmlrtl;vclie;inetdbbde;inetdbxpress;dbrtl;dsnap;dsnapcon;vcldb;soaprtl;VclSmp;dbexpress;dbxcds;inetdb;bdertl;vcldbx;webdsnap;websnap;adortl;ibxpress;teeui;teedb;tee;dss;visualclx;visualdbclx;vclactnband;vclshlctrls;dclOfficeXP;CEToolsPkgd7;FR7;FRIBX7;Hydra_Core_D7;Hydra_RO_D7;fqb70;frx7;frxADO7;frxBDE7;frxDB7;frxDBX7;frxe7;frxIBX7;fs7;fsADO7;fsBDE7;fsDB7;fsIBX7;DataAbstract_Core_D7;DataAbstract_IDE_D7;dxComnD7;dxsbD7;dxBarD7;dxBarDBNavD7;dxBarExtDBItemsD7;dxBarExtItemsD7;dxDockingD7;cxEditorsVCLD7;cxLibraryVCLD7;dxThemeD7;cxDataD7;cxExtEditorsVCLD7;cxGridVCLD7;cxPageControlVCLD7;cxSchedulerVCLD7;cxTreeListVCLD7;dxPSCoreD7 +Conditionals= +DebugSourceDirs= +UsePackages=0 +[Parameters] +RunParams= +HostApplication= +Launcher= +UseLauncher=0 +DebugCWD= +[Language] +ActiveLang= +ProjectLang= +RootDir=C:\Archivos de programa\Borland\Delphi7\Bin\ +[Version Info] +IncludeVerInfo=1 +AutoIncBuild=0 +MajorVer=1 +MinorVer=0 +Release=0 +Build=0 +Debug=0 +PreRelease=0 +Special=0 +Private=0 +DLL=0 +Locale=1033 +CodePage=1252 +[Version Info Keys] +CompanyName= +FileDescription= +FileVersion=1.0.0.0 +InternalName= +LegalCopyright= +LegalTrademarks= +OriginalFilename= +ProductName= +ProductVersion=1.0.0.0 +Comments= +[Excluded Packages] +C:\Archivos de programa\Borland\Delphi7\Projects\Bpl\DJclVcl70.bpl=JEDI Code Library VCL package for Delphi 7 +C:\Archivos de programa\Borland\Delphi7\Projects\Bpl\DJcl70.bpl=JEDI Code Library RTL package for Delphi 7 +C:\WINDOWS\system32\fqb70.bpl=FastQueryBuilder 1.01 +C:\Archivos de programa\Borland\Delphi7\Projects\Bpl\dxPSCoreD7.bpl=ExpressPrinting System (core 3.1) by Developer Express Inc. +C:\Archivos de programa\Borland\Delphi7\Projects\Bpl\dxComnD7.bpl=ExpressCommonLibrary by Developer Express Inc. +c:\archivos de programa\borland\delphi7\Projects\Bpl\EasyResizeD7.bpl=EasyResize for Delphi 7 +c:\archivos de programa\borland\delphi7\Projects\Bpl\RodaxFrameD7.bpl=Frames Acana (D7) +[HistoryLists\hlUnitAliases] +Count=1 +Item0=WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE; +[HistoryLists\hlSearchPath] +Count=1 +Item0=..\..\Lib\D7 diff --git a/official/2.1.6+2.1.beta1/TBX/DTMCtrl/TBXDTMCtrl_d7.dpk b/official/2.1.6+2.1.beta1/TBX/DTMCtrl/TBXDTMCtrl_d7.dpk new file mode 100644 index 0000000..58791fe --- /dev/null +++ b/official/2.1.6+2.1.beta1/TBX/DTMCtrl/TBXDTMCtrl_d7.dpk @@ -0,0 +1,38 @@ +package TBXDTMCtrl_d7; + +{$R *.res} +{$R 'TBX_DTM.dcr'} +{$ALIGN 8} +{$ASSERTIONS ON} +{$BOOLEVAL OFF} +{$DEBUGINFO ON} +{$EXTENDEDSYNTAX ON} +{$IMPORTEDDATA ON} +{$IOCHECKS ON} +{$LOCALSYMBOLS ON} +{$LONGSTRINGS ON} +{$OPENSTRINGS ON} +{$OPTIMIZATION ON} +{$OVERFLOWCHECKS OFF} +{$RANGECHECKS OFF} +{$REFERENCEINFO ON} +{$SAFEDIVIDE OFF} +{$STACKFRAMES OFF} +{$TYPEDADDRESS OFF} +{$VARSTRINGCHECKS ON} +{$WRITEABLECONST OFF} +{$MINENUMSIZE 1} +{$IMAGEBASE $400000} +{$IMPLICITBUILD ON} + +requires + rtl, + vcl, + tbx_d7, + tb2k_d7; + +contains + TBXDTMForm in 'TBXDTMForm.pas' {frmTBXDTM}, + TBX_DTM in 'TBX_DTM.pas'; + +end. diff --git a/official/2.1.6+2.1.beta1/TBX/DTMCtrl/TBXDTMCtrl_d7.res b/official/2.1.6+2.1.beta1/TBX/DTMCtrl/TBXDTMCtrl_d7.res new file mode 100644 index 0000000..52f9f95 Binary files /dev/null and b/official/2.1.6+2.1.beta1/TBX/DTMCtrl/TBXDTMCtrl_d7.res differ diff --git a/official/2.1.6+2.1.beta1/TBX/DTMCtrl/TBXDTMForm.dfm b/official/2.1.6+2.1.beta1/TBX/DTMCtrl/TBXDTMForm.dfm new file mode 100644 index 0000000..b9ce3f3 --- /dev/null +++ b/official/2.1.6+2.1.beta1/TBX/DTMCtrl/TBXDTMForm.dfm @@ -0,0 +1,116 @@ +object frmTBXDTM: TfrmTBXDTM + Left = 328 + Top = 290 + BorderStyle = bsDialog + Caption = 'TBX Theme Manager' + ClientHeight = 263 + ClientWidth = 351 + Color = clBtnFace + Font.Charset = DEFAULT_CHARSET + Font.Color = clWindowText + Font.Height = -11 + Font.Name = 'Tahoma' + Font.Style = [] + OldCreateOrder = False + Position = poScreenCenter + OnActivate = FormActivate + PixelsPerInch = 96 + TextHeight = 13 + object Label1: TLabel + Left = 9 + Top = 6 + Width = 75 + Height = 13 + Caption = 'Loaded Themes' + end + object Label2: TLabel + Left = 8 + Top = 239 + Width = 76 + Height = 13 + Caption = 'Current Theme:' + end + object Label3: TLabel + Left = 89 + Top = 239 + Width = 3 + Height = 13 + end + object ListBox1: TListBox + Left = 7 + Top = 21 + Width = 254 + Height = 209 + ItemHeight = 13 + TabOrder = 0 + OnDblClick = ListBox1DblClick + end + object Button1: TButton + Left = 265 + Top = 21 + Width = 82 + Height = 25 + Action = actadd + TabOrder = 1 + end + object Button2: TButton + Left = 265 + Top = 48 + Width = 82 + Height = 25 + Action = actremove + TabOrder = 2 + end + object Button4: TButton + Left = 266 + Top = 233 + Width = 82 + Height = 25 + Caption = 'Close' + ModalResult = 1 + TabOrder = 3 + end + object Button3: TButton + Left = 265 + Top = 91 + Width = 82 + Height = 25 + Action = actActivate + TabOrder = 4 + end + object Button5: TButton + Left = 266 + Top = 118 + Width = 82 + Height = 25 + Caption = 'Default' + TabOrder = 5 + OnClick = Button5Click + end + object ActionList1: TActionList + Left = 170 + Top = 128 + object actadd: TAction + Caption = 'Load' + OnExecute = actaddExecute + end + object actremove: TAction + Caption = 'Unload' + OnExecute = actremoveExecute + OnUpdate = actremoveUpdate + end + object actActivate: TAction + Caption = 'Activate' + OnExecute = actActivateExecute + OnUpdate = actActivateUpdate + end + end + object OpenDialog1: TOpenDialog + DefaultExt = 'tbxt' + Filter = 'TBX Theme Package|*.tbxt|All Files|*.*' + Options = [ofReadOnly, ofHideReadOnly, ofAllowMultiSelect, ofEnableSizing] + Title = 'Load TBX Theme Package' + Left = 94 + Top = 95 + end +end diff --git a/official/2.1.6+2.1.beta1/TBX/DTMCtrl/TBXDTMForm.pas b/official/2.1.6+2.1.beta1/TBX/DTMCtrl/TBXDTMForm.pas new file mode 100644 index 0000000..c9c7d42 --- /dev/null +++ b/official/2.1.6+2.1.beta1/TBX/DTMCtrl/TBXDTMForm.pas @@ -0,0 +1,156 @@ +unit TBXDTMForm; + +interface + +uses + Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, + Dialogs, ActnList, StdCtrls, TBX, TBXThemes; + +type + TThemeRefreshEvent = Procedure(Sender:TObject; ThemeList:TStrings) of object; + TThemeLoadEvent = Procedure(Sender:TObject; ThemeFiles:TStrings) of object; + TThemeUnloadEvent = Procedure(Sender:TObject; ThemeIndex: Integer) of object; + TThemeActivateEvent = procedure (Sender:TObject; ThemeIndex:integer) of object; + + TfrmTBXDTM = class(TForm) + ListBox1: TListBox; + Label1: TLabel; + Label2: TLabel; + Label3: TLabel; + Button1: TButton; + Button2: TButton; + Button4: TButton; + ActionList1: TActionList; + actadd: TAction; + actremove: TAction; + actActivate: TAction; + Button3: TButton; + OpenDialog1: TOpenDialog; + Button5: TButton; + procedure actremoveUpdate(Sender: TObject); + procedure actaddExecute(Sender: TObject); + procedure actActivateUpdate(Sender: TObject); + procedure actremoveExecute(Sender: TObject); + procedure Button5Click(Sender: TObject); + procedure actActivateExecute(Sender: TObject); + procedure FormActivate(Sender: TObject); + procedure ListBox1DblClick(Sender: TObject); + private + fOnLoad: TThemeLoadEvent; + fOnRefresh: TThemeRefreshEvent; + fOnUnload: TThemeUnloadEvent; + fOnActivate: TThemeActivateEvent; + { Private declarations } + procedure RefreshThemeList; + procedure LoadNewTheme; + procedure UnloadTheme; + procedure RefreshCurrentTheme; + procedure ActivateTheme; + public + { Public declarations } + property OnRefreshThemes:TThemeRefreshEvent read fOnRefresh write fOnRefresh; + property OnLoadNewTheme:TThemeLoadEvent read fOnLoad write fOnLoad; + property OnUnloadTheme:TThemeUnloadEvent read fOnUnload write fOnUnload; + property OnActivateTheme:TThemeActivateEvent read fOnActivate write fOnActivate; + end; + +var + frmTBXDTM: TfrmTBXDTM; + +implementation + +{$R *.dfm} + +procedure TfrmTBXDTM.actremoveUpdate(Sender: TObject); +begin + actremove.enabled := (listbox1.ItemIndex > -1) and (listbox1.Items[ListBox1.ItemIndex] <> CurrentTheme.Name); +end; + +procedure TfrmTBXDTM.actaddExecute(Sender: TObject); +begin + LoadNewTheme; + RefreshThemeList; + RefreshCurrentTheme; +end; + +procedure TfrmTBXDTM.RefreshThemeList; +begin + ListBox1.Items.BeginUpdate; + try + if assigned(fOnRefresh) then + fOnRefresh(self, ListBox1.Items); + finally + listbox1.items.EndUpdate; + end; +end; + +procedure TfrmTBXDTM.actActivateUpdate(Sender: TObject); +begin + actactivate.enabled := (ListBox1.ItemIndex > -1) and (listbox1.Items[ListBox1.ItemIndex] <> CurrentTheme.Name); +end; + +procedure TfrmTBXDTM.LoadNewTheme; +begin + if OpenDialog1.Execute then + begin + if assigned(fOnLoad) then + begin + fOnLoad(self, opendialog1.Files); + RefreshThemeList; + end; + end; +end; + +procedure TfrmTBXDTM.UnloadTheme; +begin + if assigned(fOnLoad) then + begin + fOnUnload(self, listbox1.itemindex); + RefreshThemeList; + end; +end; + + +procedure TfrmTBXDTM.actremoveExecute(Sender: TObject); +begin + UnloadTheme; +end; + +procedure TfrmTBXDTM.Button5Click(Sender: TObject); +begin + listbox1.ItemIndex := -1; + ActivateTheme; +end; + +procedure TfrmTBXDTM.actActivateExecute(Sender: TObject); +begin + ActivateTheme; +end; + +procedure TfrmTBXDTM.RefreshCurrentTheme; +begin + label3.Caption := CurrentTheme.Name; +end; + +procedure TfrmTBXDTM.FormActivate(Sender: TObject); +begin + RefreshThemeList; + RefreshCurrentTheme; +end; + +procedure TfrmTBXDTM.ListBox1DblClick(Sender: TObject); +begin + if listbox1.ItemIndex <> -1 then + ActivateTheme; +end; + +procedure TfrmTBXDTM.ActivateTheme; +begin + if assigned(fOnActivate) then + begin + fOnActivate(self, ListBox1.ItemIndex); + RefreshCurrentTheme; + end; +end; + +end. diff --git a/official/2.1.6+2.1.beta1/TBX/DTMCtrl/TBX_DTM.dcr b/official/2.1.6+2.1.beta1/TBX/DTMCtrl/TBX_DTM.dcr new file mode 100644 index 0000000..583d777 Binary files /dev/null and b/official/2.1.6+2.1.beta1/TBX/DTMCtrl/TBX_DTM.dcr differ diff --git a/official/2.1.6+2.1.beta1/TBX/DTMCtrl/TBX_DTM.pas b/official/2.1.6+2.1.beta1/TBX/DTMCtrl/TBX_DTM.pas new file mode 100644 index 0000000..9ba26b4 --- /dev/null +++ b/official/2.1.6+2.1.beta1/TBX/DTMCtrl/TBX_DTM.pas @@ -0,0 +1,372 @@ +unit TBX_DTM; + +interface + +uses classes, TBXDTMForm; + +{$Warn symbol_Platform off} + +type + TThemeFolderLocation = (flRelative, flAbsolute); + TThemeSettingsLocation = (slRegistry, slIniFile); + TTBXDynamicThemeManager = class(TComponent) + private + fPersistLast: boolean; + fAutoLoad: boolean; + fThemeFolder: string; + fFolderLocation: TThemeFolderLocation; + FFilterIndex: Integer; + FFilter: string; + fTitle: string; + fDefaultExt: string; + procedure LoadThemes(Sender:TObject; ThemeFiles:TStrings); + procedure UnloadTheme(Sender:TObject; ThemeIndex: Integer); + procedure RefreshThemes(Sender:TObject; ThemeList:TStrings); + procedure ActivateTheme(Sender:TObject; ThemeIndex:integer); + protected + procedure Loaded; override; + function ThemePath:string; + procedure AutoLoad; + procedure LoadLastTheme; + public + procedure Execute; + constructor Create(AOwner: TComponent); override; + published + property ThemeFolderLocation : TThemeFolderLocation read fFolderLocation write fFolderLocation default flRelative; + property ThemesFolder : string read fThemeFolder write fThemeFolder; + property Filter: string read FFilter write FFilter; + property FilterIndex: Integer read fFilterIndex write FFilterIndex default 1; + property DefaultExt : string read fDefaultExt write fDefaultExt; + property Title : string read fTitle write fTitle; + property AutoLoadThemes : boolean read fAutoLoad write fAutoLoad default false; + property PersistLastTheme : boolean read fPersistLast write fPersistLast default true; + end; + +procedure UnloadThemes; + +procedure Register; + +implementation + +uses Windows, dialogs, sysutils, IniFiles, TBX, TBXThemes, Math; + +procedure Register; +begin + RegisterComponents('Toolbar2000', [TTBXDynamicThemeManager]); +end; + +type + TThemeObj = class(TObject) + PackageHandle : THandle; + FileName : String; + ThemeName : ShortString; + end; + TThemeName = function : ShortString; stdcall; + TRegisterTheme = Procedure(RegisterTheme:boolean); stdcall; + +var + gLoadedThemes : TList; + +procedure UnloadThemes; +var + wTheme : TThemeObj; + P2 : TRegisterTheme; +begin + If CurrentTheme.Name <> 'Default' then + TBXSetTheme('Default'); + while gLoadedThemes.Count > 0 do + begin + wTheme := gLoadedThemes[0]; + P2 := GetProcAddress(wTheme.PackageHandle, 'TBXRegisterTheme'); + P2(False); + gLoadedThemes.Delete(0); + UnloadPackage(wTheme.PackageHandle); + wTheme.free; + end; +end; + +{ TTBXDynamicThemeManager } + +procedure TTBXDynamicThemeManager.ActivateTheme(Sender:TObject; ThemeIndex:integer); +var + wFileName : string; + wThemeName : string; + wTheme : TThemeObj; + wIni : TIniFile; +begin + if fPersistLast then + begin + if ThemeIndex > -1 then + begin + wTheme := gLoadedThemes[ThemeIndex]; + wFileName := wTheme.FileName; + wThemeName := wTheme.ThemeName; + end + else + begin + wThemeName := ''; + wFileName := ''; + end; + + wIni := TIniFile.Create(ThemePath+'Theme.ini'); + try + wIni.WriteString('ActiveTheme','FileName',wFileName); + wIni.WriteString('ActiveTheme','ThemeName',wThemeName); + finally + wIni.free; + end; + end; + + if ThemeIndex > -1 then + TBXSetTheme(wThemeName) + else + TBXSetTheme('Default'); +end; + +procedure TTBXDynamicThemeManager.AutoLoad; +var + wFileList : TStringList; + dirinfo : TSearchRec; + ds : integer; +begin + if fAutoLoad then + begin + wFileList := TStringList.create; + try + ds := findfirst(ThemePath+'*.'+defaultext, $3f, dirinfo); + while ds = 0 do + begin + if dirinfo.Attr and fadirectory = 0 then + wFileList.add(ThemePath+dirinfo.Name); + ds := findnext(dirinfo); + end; + FindClose(dirinfo); + + LoadThemes(self, wFileList); + finally + wFileList.free; + end; + end; +end; + +constructor TTBXDynamicThemeManager.Create(AOwner: TComponent); +begin + inherited; + fFilter := 'TBX Theme Package|*.tbxt|All Files|*.*'; + FFilterIndex := 1; + fTitle := 'TBX Theme Manager'; + fFolderLocation := flRelative; + fThemeFolder := 'Themes'; + fDefaultExt := 'tbxt'; + fPersistLast := true; + fAutoLoad := false; +end; + +procedure TTBXDynamicThemeManager.Execute; +var + wFrm : TfrmTBXDTM; +begin + wFrm := TfrmTBXDTM.create(self); + try + wFrm.OnRefreshThemes := RefreshThemes; + wFrm.OnLoadNewTheme := LoadThemes; + wFrm.OnUnloadTheme := UnloadTheme; + wFrm.OnActivateTheme := ActivateTheme; + wFrm.Caption := fTitle; + wFrm.OpenDialog1.InitialDir := ThemePath; + wFrm.OpenDialog1.Title := fTitle; + wFrm.OpenDialog1.Filter := FFilter; + wFrm.OpenDialog1.FilterIndex := FFilterIndex; + wFrm.ShowModal; + finally + wFrm.free; + end; +end; + +procedure TTBXDynamicThemeManager.Loaded; +begin + inherited; + if not (csdesigning in componentstate) then + begin + AutoLoad; + LoadLastTheme; + end; +end; + +procedure TTBXDynamicThemeManager.LoadLastTheme; +var + wIni : TIniFile; + wFile : TStringList; + wFileName : string; + wThemeName : string; + wFound : boolean; + loop : integer; + wTheme : TThemeObj; +begin + if fPersistLast and fileexists(ThemePath+'Theme.ini') then + begin + wIni := TIniFile.Create(ThemePath+'Theme.ini'); + try + wFileName := trim(wIni.ReadString('ActiveTheme','FileName','')); + wThemeName := trim(wIni.ReadString('ActiveTheme','ThemeName','')); + finally + wIni.free; + end; + + loop := 0; + wFound := false; + + while not wFound and (loop < gLoadedThemes.count) do + begin + wTheme := gLoadedThemes[loop]; + wFound := AnsiCompareText(wTheme.ThemeName, wThemeName) = 0; + if not wFound then + inc(loop); + end; + + if not wFound and fileexists(wfilename) then + begin + wFile := TStringList.create; + try + wFile.add(wFileName); + LoadThemes(self, wFile); + finally + wFile.free; + end; + end; + + if Trim(wThemeName) <> '' then + TBXSetTheme(wThemeName); + end; +end; + +procedure TTBXDynamicThemeManager.LoadThemes(Sender: TObject; ThemeFiles: TStrings); +var + wTheme : TThemeObj; + loop : integer; + wFound : boolean; + wFoundName : string; + P1 : TThemeName; + P2 : TRegisterTheme; +begin + while ThemeFiles.Count > 0 do + begin + wFound := false; + loop := 0; + while not wFound and (loop < gLoadedThemes.Count) do + begin + wTheme := gLoadedThemes[loop]; + wFound := AnsiCompareText(extractfilename(wTheme.FileName), extractfilename(ThemeFiles[0])) = 0; + if not wFound then + inc(loop) + else + wFoundName := wTheme.ThemeName; + end; + + if wFound then + begin + messagedlg(wFoundName+' is already loaded', mtError, [mbok], 0); + end + else + begin + wTheme := TThemeObj.create; + try + wTheme.FileName := ThemeFiles[0]; + wTheme.PackageHandle := LoadPackage(ThemeFiles[0]); + + if wTheme.PackageHandle > 0 then + begin + P2 := GetProcAddress(wTheme.PackageHandle, 'TBXRegisterTheme'); + P1 := GetProcAddress(wTheme.PackageHandle, 'TBXThemeName'); + if Assigned(P1) and Assigned(P2) then + begin + Try + P2(true); + except + messagedlg('An unknown error has occured while trying to register the theme file:'#13#10#13#10+ThemeFiles[0], mterror, [mbok], 0); + abort; + end; + + if IsTBXThemeAvailable(P1) then + begin + wTheme.ThemeName := P1; + gLoadedThemes.Add(wTheme); + end + else + begin + messagedlg('An unknown error has occured while trying to load the theme file:'#13#10#13#10+ThemeFiles[0], mterror, [mbok], 0); + Abort; + end; + end + else + begin + messagedlg('Unable to load the specified TBX Theme file.'#13#10#13#10+ThemeFiles[0], mterror, [mbok], 0); + Abort; + end; + end + else + begin + messagedlg('Unable to load the specified TBX Theme file.'#13#10#13#10+ThemeFiles[0], mterror, [mbok], 0); + Abort; + end; + except + if wTheme.PackageHandle > 0 then + UnloadPackage(wTheme.PackageHandle); + freeandnil(wTheme); + end; + end; + ThemeFiles.delete(0); + end; +end; + +procedure TTBXDynamicThemeManager.RefreshThemes(Sender: TObject; + ThemeList: TStrings); +var + loop : integer; + wTheme : TThemeObj; +begin + ThemeList.Clear; + for loop := 0 to gLoadedThemes.Count-1 do + begin + wTheme := gLoadedThemes[loop]; + ThemeList.Add(wTheme.ThemeName); + end; +end; + +function TTBXDynamicThemeManager.ThemePath: string; +begin + if fFolderLocation = flRelative then + result := extractfilepath(ParamStr(0))+fThemeFolder + else + result := fThemeFolder; + + result := IncludeTrailingBackslash(result); + if not DirectoryExists(result) then + ForceDirectories(result); +end; + +procedure TTBXDynamicThemeManager.UnloadTheme(Sender: TObject; ThemeIndex: Integer); +var + wTheme : TThemeObj; + P2 : TRegisterTheme; +begin + try + wTheme := gLoadedThemes[ThemeIndex]; + P2 := GetProcAddress(wTheme.PackageHandle, 'TBXRegisterTheme'); + P2(False); + UnloadPackage(wTheme.PackageHandle); + gLoadedThemes.Delete(ThemeIndex); + freeandnil(wTheme); + except + messagedlg('Unable to remove the theme at this time.', mtinformation, [mbok], 0); + end +end; + +initialization + gLoadedThemes := TList.create; + +finalization + UnloadThemes; + gLoadedThemes.free; + +end. diff --git a/official/2.1.6+2.1.beta1/TBX/DTMCtrl/rmkThemes_Modified.zip b/official/2.1.6+2.1.beta1/TBX/DTMCtrl/rmkThemes_Modified.zip new file mode 100644 index 0000000..3edb1c7 Binary files /dev/null and b/official/2.1.6+2.1.beta1/TBX/DTMCtrl/rmkThemes_Modified.zip differ diff --git a/official/2.1.6+2.1.beta1/TBX/Demo/Project1.bpr b/official/2.1.6+2.1.beta1/TBX/Demo/Project1.bpr new file mode 100644 index 0000000..5837dfe --- /dev/null +++ b/official/2.1.6+2.1.beta1/TBX/Demo/Project1.bpr @@ -0,0 +1,93 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +[Version Info] +IncludeVerInfo=0 +AutoIncBuild=0 +MajorVer=1 +MinorVer=0 +Release=0 +Build=0 +Debug=0 +PreRelease=0 +Special=0 +Private=0 +DLL=0 +Locale=1033 +CodePage=1252 + +[Version Info Keys] +CompanyName= +FileDescription= +FileVersion=1.0.0.0 +InternalName= +LegalCopyright= +LegalTrademarks= +OriginalFilename= +ProductName= +ProductVersion=1.0.0.0 +Comments= + +[Debugging] +DebugSourceDirs=$(BCB)\source\vcl + +[Parameters] +RunParams= +HostApplication= +RemoteHost= +RemotePath= +RemoteDebug=0 + +[Compiler] +ShowInfoMsgs=0 +LinkDebugVcl=0 +LinkCGLIB=0 + +[CORBA] +AddServerUnit=1 +AddClientUnit=1 +PrecompiledHeaders=1 + + \ No newline at end of file diff --git a/official/2.1.6+2.1.beta1/TBX/Demo/Project1.cfg b/official/2.1.6+2.1.beta1/TBX/Demo/Project1.cfg new file mode 100644 index 0000000..d9ef69f --- /dev/null +++ b/official/2.1.6+2.1.beta1/TBX/Demo/Project1.cfg @@ -0,0 +1,44 @@ +-$A8 +-$B- +-$C+ +-$D+ +-$E- +-$F- +-$G+ +-$H+ +-$I+ +-$J- +-$K- +-$L+ +-$M- +-$N+ +-$O+ +-$P+ +-$Q- +-$R- +-$S- +-$T- +-$U- +-$V+ +-$W- +-$X+ +-$YD +-$Z1 +-GD +-cg +-AWinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE; +-H+ +-W+ +-M +-$M16384,1048576 +-K$00400000 +-LE"T:\Bpl_D7" +-LN"T:\Bpl_D7" +-U"T:\Componentes\Tb2k\Lib\D7" +-O"T:\Componentes\Tb2k\Lib\D7" +-I"T:\Componentes\Tb2k\Lib\D7" +-R"T:\Componentes\Tb2k\Lib\D7" +-DEUREKALOG;EUREKALOG_VER5 +-w-UNSAFE_TYPE +-w-UNSAFE_CODE +-w-UNSAFE_CAST diff --git a/official/2.1.6+2.1.beta1/TBX/Demo/Project1.cpp b/official/2.1.6+2.1.beta1/TBX/Demo/Project1.cpp new file mode 100644 index 0000000..cce7527 --- /dev/null +++ b/official/2.1.6+2.1.beta1/TBX/Demo/Project1.cpp @@ -0,0 +1,23 @@ +//--------------------------------------------------------------------------- + +#include +#pragma hdrstop +USEFORMNS("Unit1.pas", Unit1, Form1); +USEFORMNS("Unit2.pas", Unit2, Form2); +//--------------------------------------------------------------------------- +WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) +{ + try + { + Application->Initialize(); + Application->CreateForm(__classid(TForm1), &Form1); + Application->CreateForm(__classid(TForm2), &Form2); + Application->Run(); + } + catch (Exception &exception) + { + Application->ShowException(&exception); + } + return 0; +} +//--------------------------------------------------------------------------- diff --git a/official/2.1.6+2.1.beta1/TBX/Demo/Project1.dof b/official/2.1.6+2.1.beta1/TBX/Demo/Project1.dof new file mode 100644 index 0000000..e11661b --- /dev/null +++ b/official/2.1.6+2.1.beta1/TBX/Demo/Project1.dof @@ -0,0 +1,462 @@ +[FileVersion] +Version=7.0 +[Compiler] +A=8 +B=0 +C=1 +D=1 +E=0 +F=0 +G=1 +H=1 +I=1 +J=0 +K=0 +L=1 +M=0 +N=1 +O=1 +P=1 +Q=0 +R=0 +S=0 +T=0 +U=0 +V=1 +W=0 +X=1 +Y=1 +Z=1 +ShowHints=1 +ShowWarnings=1 +UnitAliases=WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE; +NamespacePrefix= +SymbolDeprecated=1 +SymbolLibrary=1 +SymbolPlatform=1 +UnitLibrary=1 +UnitPlatform=1 +UnitDeprecated=1 +HResultCompat=1 +HidingMember=1 +HiddenVirtual=1 +Garbage=1 +BoundsError=1 +ZeroNilCompat=1 +StringConstTruncated=1 +ForLoopVarVarPar=1 +TypedConstVarPar=1 +AsgToTypedConst=1 +CaseLabelRange=1 +ForVariable=1 +ConstructingAbstract=1 +ComparisonFalse=1 +ComparisonTrue=1 +ComparingSignedUnsigned=1 +CombiningSignedUnsigned=1 +UnsupportedConstruct=1 +FileOpen=1 +FileOpenUnitSrc=1 +BadGlobalSymbol=1 +DuplicateConstructorDestructor=1 +InvalidDirective=1 +PackageNoLink=1 +PackageThreadVar=1 +ImplicitImport=1 +HPPEMITIgnored=1 +NoRetVal=1 +UseBeforeDef=1 +ForLoopVarUndef=1 +UnitNameMismatch=1 +NoCFGFileFound=1 +MessageDirective=1 +ImplicitVariants=1 +UnicodeToLocale=1 +LocaleToUnicode=1 +ImagebaseMultiple=1 +SuspiciousTypecast=1 +PrivatePropAccessor=1 +UnsafeType=0 +UnsafeCode=0 +UnsafeCast=0 +[Linker] +MapFile=3 +OutputObjs=0 +ConsoleApp=1 +DebugInfo=0 +RemoteSymbols=0 +MinStackSize=16384 +MaxStackSize=1048576 +ImageBase=4194304 +ExeDescription= +[Directories] +OutputDir= +UnitOutputDir= +PackageDLLOutputDir= +PackageDCPOutputDir= +SearchPath=T:\Componentes\Tb2k\Lib\D7 +Packages=vcl;rtl;vclx;indy;inet;xmlrtl;vclie;inetdbbde;inetdbxpress;dbrtl;dsnap;dsnapcon;vcldb;soaprtl;VclSmp;dbexpress;dbxcds;inetdb;bdertl;vcldbx;webdsnap;websnap;adortl;ibxpress;teeui;teedb;tee;dss;visualclx;visualdbclx;vclactnband;vclshlctrls;dclOfficeXP;CEToolsPkgd7;FR7;FRIBX7;Hydra_Core_D7;Hydra_RO_D7;fqb70;frx7;frxADO7;frxBDE7;frxDB7;frxDBX7;frxe7;frxIBX7;fs7;fsADO7;fsBDE7;fsDB7;fsIBX7;DataAbstract_Core_D7;DataAbstract_IDE_D7;dxComnD7;dxsbD7;dxBarD7;dxBarDBNavD7;dxBarExtDBItemsD7;dxBarExtItemsD7;dxDockingD7;cxEditorsVCLD7;cxLibraryVCLD7;dxThemeD7;cxDataD7;cxExtEditorsVCLD7;cxGridVCLD7;cxPageControlVCLD7;cxSchedulerVCLD7;cxTreeListVCLD7;dxPSCoreD7 +Conditionals=EUREKALOG;EUREKALOG_VER5 +DebugSourceDirs= +UsePackages=0 +[Parameters] +RunParams= +HostApplication= +Launcher= +UseLauncher=0 +DebugCWD= +[Language] +ActiveLang= +ProjectLang= +RootDir=C:\Archivos de programa\Borland\Delphi7\Bin\ +[Version Info] +IncludeVerInfo=0 +AutoIncBuild=0 +MajorVer=1 +MinorVer=0 +Release=0 +Build=0 +Debug=0 +PreRelease=0 +Special=0 +Private=0 +DLL=0 +Locale=3082 +CodePage=1252 +[Version Info Keys] +CompanyName= +FileDescription= +FileVersion=1.0.0.0 +InternalName= +LegalCopyright= +LegalTrademarks= +OriginalFilename= +ProductName= +ProductVersion=1.0.0.0 +Comments= +[Excluded Packages] +c:\archivos de programa\borland\delphi7\Bin\designdgm70.bpl=Borland Module Diagram Editview +T:\BPL_D7\dxPSCoreD7.bpl=ExpressPrinting System by Developer Express Inc. +[HistoryLists\hlUnitAliases] +Count=1 +Item0=WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE; +[HistoryLists\hlSearchPath] +Count=1 +Item0=T:\Componentes\Tb2k\Lib\D7 +[Exception Log] +EurekaLog Version=519 +Activate=1 +Activate Handle=1 +Save Log File=1 +Foreground Tab=0 +Freeze Activate=0 +Freeze Timeout=0 +Freeze Message=The application seems to be frozen. +SMTP From=eurekalog@email.com +SMTP Host= +SMTP Port=25 +SMTP UserID= +SMTP Password= +Append to Log=0 +Show TerminateBtn=1 +TerminateBtn Operation=1 +Errors Number=32 +Errors Terminate=3 +Email Address= +Email Object= +Email Send Options=0 +Output Path= +Encrypt Password= +AutoCloseDialogSecs=0 +WebSendMode=0 +SupportULR= +HTMLLayout Count=15 +HTMLLine0="%3Chtml%3E" +HTMLLine1=" %3Chead%3E" +HTMLLine2=" %3C/head%3E" +HTMLLine3=" %3Cbody TopMargin=10 LeftMargin=10%3E" +HTMLLine4=" %3Ctable width="100%%" border="0"%3E" +HTMLLine5=" %3Ctr%3E" +HTMLLine6=" %3Ctd nowrap%3E" +HTMLLine7=" %3Cfont face="Lucida Console, Courier" size="2"%3E" +HTMLLine8=" %3C%%HTML_TAG%%%3E" +HTMLLine9=" %3C/font%3E" +HTMLLine10=" %3C/td%3E" +HTMLLine11=" %3C/tr%3E" +HTMLLine12=" %3C/table%3E" +HTMLLine13=" %3C/body%3E" +HTMLLine14="%3C/html%3E" +AutoCrashOperation=1 +AutoCrashNumber=10 +AutoCrashMinutes=1 +WebURL= +WebUserID= +WebPassword= +WebPort=0 +AttachedFiles= +Count=0 +EMail Message Line Count=0 +loNoDuplicateErrors=0 +loAppendReproduceText=0 +loDeleteLogAtVersionChange=0 +loAddComputerNameInLogFileName=0 +loSaveModulesSection=1 +loSaveCPUSection=1 +soAppStartDate=1 +soAppName=1 +soAppVersionNumber=1 +soAppParameters=1 +soAppCompilationDate=1 +soExcDate=1 +soExcAddress=1 +soExcModule=1 +soExcType=1 +soExcMessage=1 +soActCtlsFormClass=1 +soActCtlsFormText=1 +soActCtlsControlClass=1 +soActCtlsControlText=1 +soCmpName=1 +soCmpUser=1 +soCmpTotalMemory=1 +soCmpFreeMemory=1 +soCmpTotalDisk=1 +soCmpFreeDisk=1 +soCmpSysUpTime=1 +soCmpProcessor=1 +soCmpDisplayMode=1 +soOSType=1 +soOSBuildN=1 +soOSUpdate=1 +soOSLanguage=1 +soNetIP=1 +soNetSubmask=1 +soNetGateway=1 +soNetDNS1=1 +soNetDNS2=1 +soNetDHCP=1 +sndShowSendDialog=1 +sndShowSuccessFailureMsg=0 +sndSendEntireLog=0 +sndSendXMLLogCopy=0 +sndSendScreenshot=0 +sndUseOnlyActiveWindow=0 +sndSendLastHTMLPage=1 +sndSendInSeparatedThread=0 +sndAddDateInFileName=0 +sndCompressAllFiles=0 +edoShowExceptionDialog=1 +edoSendEmailChecked=1 +edoAttachScreenshotChecked=1 +edoShowCopyToClipOption=1 +edoShowDetailsButton=1 +edoShowInDetailedMode=0 +edoShowInTopMostMode=0 +edoUseEurekaLogLookAndFeel=1 +csoShowDLLs=1 +csoShowBPLs=1 +csoShowBorlandThreads=1 +csoShowWindowsThreads=1 +csoShowProcedureOffset=0 +boActivateCrashDetection=0 +boPauseBorlandThreads=0 +boDoNotPauseMainThread=0 +boPauseWindowsThreads=0 +boUseMainModuleOptions=1 +boCopyLogInCaseOfError=1 +boSaveCompressedCopyInCaseOfError=0 +Count mtInformationMsgCaption=1 +mtInformationMsgCaption0="Information." +Count mtQuestionMsgCaption=1 +mtQuestionMsgCaption0="Question." +Count mtDialog_Caption=1 +mtDialog_Caption0="Error." +Count mtDialog_ErrorMsgCaption=2 +mtDialog_ErrorMsgCaption0="An error has occurred during program execution." +mtDialog_ErrorMsgCaption1="Please read the following information for further details." +Count mtDialog_GeneralCaption=1 +mtDialog_GeneralCaption0="General" +Count mtDialog_GeneralHeader=1 +mtDialog_GeneralHeader0="General Information" +Count mtDialog_CallStackCaption=1 +mtDialog_CallStackCaption0="Call Stack" +Count mtDialog_CallStackHeader=1 +mtDialog_CallStackHeader0="Call Stack Information" +Count mtDialog_ModulesCaption=1 +mtDialog_ModulesCaption0="Modules" +Count mtDialog_ModulesHeader=1 +mtDialog_ModulesHeader0="Modules Information" +Count mtDialog_CPUCaption=1 +mtDialog_CPUCaption0="CPU" +Count mtDialog_CPUHeader=1 +mtDialog_CPUHeader0="CPU Information" +Count mtDialog_CustomDataCaption=1 +mtDialog_CustomDataCaption0="Other" +Count mtDialog_CustomDataHeader=1 +mtDialog_CustomDataHeader0="Other Information" +Count mtDialog_OKButtonCaption=1 +mtDialog_OKButtonCaption0="%26OK" +Count mtDialog_TerminateButtonCaption=1 +mtDialog_TerminateButtonCaption0="%26Terminate" +Count mtDialog_RestartButtonCaption=1 +mtDialog_RestartButtonCaption0="%26Restart" +Count mtDialog_DetailsButtonCaption=1 +mtDialog_DetailsButtonCaption0="%26Details" +Count mtDialog_SendMessage=1 +mtDialog_SendMessage0="%26Send this error via Internet" +Count mtDialog_ScreenshotMessage=1 +mtDialog_ScreenshotMessage0="%26Attach a Screenshot image" +Count mtDialog_CopyMessage=1 +mtDialog_CopyMessage0="%26Copy to Clipboard" +Count mtDialog_SupportMessage=1 +mtDialog_SupportMessage0="Go to the Support Page" +Count mtLog_AppHeader=1 +mtLog_AppHeader0="Application" +Count mtLog_AppStartDate=1 +mtLog_AppStartDate0="Start Date" +Count mtLog_AppName=1 +mtLog_AppName0="Name/Description" +Count mtLog_AppVersionNumber=1 +mtLog_AppVersionNumber0="Version Number" +Count mtLog_AppParameters=1 +mtLog_AppParameters0="Parameters" +Count mtLog_AppCompilationDate=1 +mtLog_AppCompilationDate0="Compilation Date" +Count mtLog_ExcHeader=1 +mtLog_ExcHeader0="Exception" +Count mtLog_ExcDate=1 +mtLog_ExcDate0="Date" +Count mtLog_ExcAddress=1 +mtLog_ExcAddress0="Address" +Count mtLog_ExcModule=1 +mtLog_ExcModule0="Module" +Count mtLog_ExcType=1 +mtLog_ExcType0="Type" +Count mtLog_ExcMessage=1 +mtLog_ExcMessage0="Message" +Count mtLog_ActCtrlsHeader=1 +mtLog_ActCtrlsHeader0="Active Controls" +Count mtLog_ActCtrlsFormClass=1 +mtLog_ActCtrlsFormClass0="Form Class" +Count mtLog_ActCtrlsFormText=1 +mtLog_ActCtrlsFormText0="Form Text" +Count mtLog_ActCtrlsControlClass=1 +mtLog_ActCtrlsControlClass0="Control Class" +Count mtLog_ActCtrlsControlText=1 +mtLog_ActCtrlsControlText0="Control Text" +Count mtLog_CmpHeader=1 +mtLog_CmpHeader0="Computer" +Count mtLog_CmpName=1 +mtLog_CmpName0="Name" +Count mtLog_CmpUser=1 +mtLog_CmpUser0="User" +Count mtLog_CmpTotalMemory=1 +mtLog_CmpTotalMemory0="Total Memory" +Count mtLog_CmpFreeMemory=1 +mtLog_CmpFreeMemory0="Free Memory" +Count mtLog_CmpTotalDisk=1 +mtLog_CmpTotalDisk0="Total Disk" +Count mtLog_CmpFreeDisk=1 +mtLog_CmpFreeDisk0="Free Disk" +Count mtLog_CmpSystemUpTime=1 +mtLog_CmpSystemUpTime0="System Up Time" +Count mtLog_CmpProcessor=1 +mtLog_CmpProcessor0="Processor" +Count mtLog_CmpDisplayMode=1 +mtLog_CmpDisplayMode0="Display Mode" +Count mtLog_OSHeader=1 +mtLog_OSHeader0="Operating System" +Count mtLog_OSType=1 +mtLog_OSType0="Type" +Count mtLog_OSBuildN=1 +mtLog_OSBuildN0="Build #" +Count mtLog_OSUpdate=1 +mtLog_OSUpdate0="Update" +Count mtLog_OSLanguage=1 +mtLog_OSLanguage0="Language" +Count mtLog_NetHeader=1 +mtLog_NetHeader0="Network" +Count mtLog_NetIP=1 +mtLog_NetIP0="IP Address" +Count mtLog_NetSubmask=1 +mtLog_NetSubmask0="Submask" +Count mtLog_NetGateway=1 +mtLog_NetGateway0="Gateway" +Count mtLog_NetDNS1=1 +mtLog_NetDNS10="DNS 1" +Count mtLog_NetDNS2=1 +mtLog_NetDNS20="DNS 2" +Count mtLog_NetDHCP=1 +mtLog_NetDHCP0="DHCP" +Count mtLog_CustInfoHeader=1 +mtLog_CustInfoHeader0="Custom Information" +Count mtCallStack_Address=1 +mtCallStack_Address0="Address" +Count mtCallStack_Name=1 +mtCallStack_Name0="Module" +Count mtCallStack_Unit=1 +mtCallStack_Unit0="Unit" +Count mtCallStack_Class=1 +mtCallStack_Class0="Class" +Count mtCallStack_Procedure=1 +mtCallStack_Procedure0="Procedure/Method" +Count mtCallStack_Line=1 +mtCallStack_Line0="Line" +Count mtCallStack_MainThread=1 +mtCallStack_MainThread0="Main" +Count mtCallStack_ExceptionThread=1 +mtCallStack_ExceptionThread0="Exception Thread" +Count mtCallStack_RunningThread=1 +mtCallStack_RunningThread0="Running Thread" +Count mtCallStack_CallingThread=1 +mtCallStack_CallingThread0="Calling Thread" +Count mtCallStack_ThreadID=1 +mtCallStack_ThreadID0="ID" +Count mtCallStack_ThreadPriority=1 +mtCallStack_ThreadPriority0="Priority" +Count mtCallStack_ThreadClass=1 +mtCallStack_ThreadClass0="Class" +Count mtSendDialog_Caption=1 +mtSendDialog_Caption0="Send." +Count mtSendDialog_Message=1 +mtSendDialog_Message0="Message" +Count mtSendDialog_Resolving=1 +mtSendDialog_Resolving0="Resolving DNS..." +Count mtSendDialog_Connecting=1 +mtSendDialog_Connecting0="Connecting with server..." +Count mtSendDialog_Connected=1 +mtSendDialog_Connected0="Connected with server." +Count mtSendDialog_Sending=1 +mtSendDialog_Sending0="Sending message..." +Count mtReproduceDialog_Caption=1 +mtReproduceDialog_Caption0="Request" +Count mtReproduceDialog_Request=1 +mtReproduceDialog_Request0="Please describe the steps to reproduce the error:" +Count mtReproduceDialog_OKButtonCaption=1 +mtReproduceDialog_OKButtonCaption0="%26OK" +Count mtModules_Handle=1 +mtModules_Handle0="Handle" +Count mtModules_Name=1 +mtModules_Name0="Name" +Count mtModules_Description=1 +mtModules_Description0="Description" +Count mtModules_Version=1 +mtModules_Version0="Version" +Count mtModules_Size=1 +mtModules_Size0="Size" +Count mtModules_LastModified=1 +mtModules_LastModified0="Modified" +Count mtModules_Path=1 +mtModules_Path0="Path" +Count mtCPU_Registers=1 +mtCPU_Registers0="Registers" +Count mtCPU_Stack=1 +mtCPU_Stack0="Stack" +Count mtCPU_MemoryDump=1 +mtCPU_MemoryDump0="Memory Dump" +Count mtSend_SuccessMsg=1 +mtSend_SuccessMsg0="The message was sent successfully." +Count mtSend_FailureMsg=1 +mtSend_FailureMsg0="Sorry, sending the message didn't work." + + diff --git a/official/2.1.6+2.1.beta1/TBX/Demo/Project1.dpr b/official/2.1.6+2.1.beta1/TBX/Demo/Project1.dpr new file mode 100644 index 0000000..d165631 --- /dev/null +++ b/official/2.1.6+2.1.beta1/TBX/Demo/Project1.dpr @@ -0,0 +1,16 @@ +program Project1; + +uses + ExceptionLog, + Forms, + Unit1 in 'Unit1.pas' {Form1}, + Unit2 in 'Unit2.pas' {Form2}; + +{$R *.RES} + +begin + Application.Initialize; + Application.CreateForm(TForm1, Form1); + Application.CreateForm(TForm2, Form2); + Application.Run; +end. diff --git a/official/2.1.6+2.1.beta1/TBX/Demo/Project1.drc b/official/2.1.6+2.1.beta1/TBX/Demo/Project1.drc new file mode 100644 index 0000000..6eda834 --- /dev/null +++ b/official/2.1.6+2.1.beta1/TBX/Demo/Project1.drc @@ -0,0 +1,552 @@ +/* VER150 + Generated by the Borland Delphi Pascal Compiler + because -GD or --drc was supplied to the compiler. + + This file contains compiler-generated resources that + were bound to the executable. + If this file is empty, then no compiler-generated + resources were bound to the produced executable. +*/ + +#define ExtCtrls_clName3DDkShadow 65264 +#define ExtCtrls_clName3DLight 65265 +#define ExtCtrls_clNameWindow 65266 +#define ExtCtrls_clNameWindowFrame 65267 +#define ExtCtrls_clNameWindowText 65268 +#define WinHelpViewer_hNoKeyword 65269 +#define TB2Consts_STBToolbarIndexOutOfBounds 65270 +#define TB2Consts_STBToolbarItemReinserted 65271 +#define TB2Consts_STBViewerNotFound 65272 +#define TB2Consts_STBChevronItemMoreButtonsHint 65273 +#define TB2Consts_STBMDIWindowItemDefCaption 65274 +#define TB2Consts_STBDockParentNotAllowed 65275 +#define TB2Consts_STBDockCannotChangePosition 65276 +#define ExtCtrls_clNameBtnShadow 65280 +#define ExtCtrls_clNameBtnText 65281 +#define ExtCtrls_clNameCaptionText 65282 +#define ExtCtrls_clNameDefault 65283 +#define ExtCtrls_clNameGrayText 65284 +#define ExtCtrls_clNameHighlight 65285 +#define ExtCtrls_clNameHighlightText 65286 +#define ExtCtrls_clNameInactiveBorder 65287 +#define ExtCtrls_clNameInactiveCaption 65288 +#define ExtCtrls_clNameInactiveCaptionText 65289 +#define ExtCtrls_clNameInfoBk 65290 +#define ExtCtrls_clNameInfoText 65291 +#define ExtCtrls_clNameMenu 65292 +#define ExtCtrls_clNameMenuText 65293 +#define ExtCtrls_clNameNone 65294 +#define ExtCtrls_clNameScrollBar 65295 +#define ExtCtrls_clNameLime 65296 +#define ExtCtrls_clNameYellow 65297 +#define ExtCtrls_clNameBlue 65298 +#define ExtCtrls_clNameFuchsia 65299 +#define ExtCtrls_clNameAqua 65300 +#define ExtCtrls_clNameWhite 65301 +#define ExtCtrls_clNameMoneyGreen 65302 +#define ExtCtrls_clNameSkyBlue 65303 +#define ExtCtrls_clNameCream 65304 +#define ExtCtrls_clNameMedGray 65305 +#define ExtCtrls_clNameActiveBorder 65306 +#define ExtCtrls_clNameActiveCaption 65307 +#define ExtCtrls_clNameAppWorkSpace 65308 +#define ExtCtrls_clNameBackground 65309 +#define ExtCtrls_clNameBtnFace 65310 +#define ExtCtrls_clNameBtnHighlight 65311 +#define Consts_SErrorSettingCount 65312 +#define Consts_SListBoxMustBeVirtual 65313 +#define HelpIntfs_hNoTableOfContents 65314 +#define HelpIntfs_hNothingFound 65315 +#define HelpIntfs_hNoContext 65316 +#define HelpIntfs_hNoTopics 65317 +#define ExtCtrls_clNameBlack 65318 +#define ExtCtrls_clNameMaroon 65319 +#define ExtCtrls_clNameGreen 65320 +#define ExtCtrls_clNameOlive 65321 +#define ExtCtrls_clNameNavy 65322 +#define ExtCtrls_clNamePurple 65323 +#define ExtCtrls_clNameTeal 65324 +#define ExtCtrls_clNameGray 65325 +#define ExtCtrls_clNameSilver 65326 +#define ExtCtrls_clNameRed 65327 +#define Consts_SmkcUp 65328 +#define Consts_SmkcRight 65329 +#define Consts_SmkcDown 65330 +#define Consts_SmkcIns 65331 +#define Consts_SmkcDel 65332 +#define Consts_SmkcShift 65333 +#define Consts_SmkcCtrl 65334 +#define Consts_SmkcAlt 65335 +#define Consts_SInsertLineError 65336 +#define Consts_SIconToClipboard 65337 +#define Consts_SInvalidMemoSize 65338 +#define Consts_SDuplicateMenus 65339 +#define Consts_SDockedCtlNeedsName 65340 +#define Consts_SDockTreeRemoveError 65341 +#define Consts_SDockZoneNotFound 65342 +#define Consts_SDockZoneHasNoCtl 65343 +#define Consts_SMsgDlgAbort 65344 +#define Consts_SMsgDlgRetry 65345 +#define Consts_SMsgDlgIgnore 65346 +#define Consts_SMsgDlgAll 65347 +#define Consts_SMsgDlgNoToAll 65348 +#define Consts_SMsgDlgYesToAll 65349 +#define Consts_SmkcBkSp 65350 +#define Consts_SmkcTab 65351 +#define Consts_SmkcEsc 65352 +#define Consts_SmkcEnter 65353 +#define Consts_SmkcSpace 65354 +#define Consts_SmkcPgUp 65355 +#define Consts_SmkcPgDn 65356 +#define Consts_SmkcEnd 65357 +#define Consts_SmkcHome 65358 +#define Consts_SmkcLeft 65359 +#define Consts_SHelpButton 65360 +#define Consts_SCloseButton 65361 +#define Consts_SIgnoreButton 65362 +#define Consts_SRetryButton 65363 +#define Consts_SAbortButton 65364 +#define Consts_SAllButton 65365 +#define Consts_SCannotDragForm 65366 +#define Consts_SMsgDlgWarning 65367 +#define Consts_SMsgDlgError 65368 +#define Consts_SMsgDlgInformation 65369 +#define Consts_SMsgDlgConfirm 65370 +#define Consts_SMsgDlgYes 65371 +#define Consts_SMsgDlgNo 65372 +#define Consts_SMsgDlgOK 65373 +#define Consts_SMsgDlgCancel 65374 +#define Consts_SMsgDlgHelp 65375 +#define Consts_SCannotFocus 65376 +#define Consts_SParentRequired 65377 +#define Consts_SMDIChildNotVisible 65378 +#define Consts_SVisibleChanged 65379 +#define Consts_SCannotShowModal 65380 +#define Consts_SMenuIndexError 65381 +#define Consts_SMenuReinserted 65382 +#define Consts_SMenuNotFound 65383 +#define Consts_SNoTimers 65384 +#define Consts_SGroupIndexTooLow 65385 +#define Consts_SNoMDIForm 65386 +#define Consts_SControlParentSetToSelf 65387 +#define Consts_SOKButton 65388 +#define Consts_SCancelButton 65389 +#define Consts_SYesButton 65390 +#define Consts_SNoButton 65391 +#define RTLConsts_SThreadError 65392 +#define Consts_SInvalidBitmap 65393 +#define Consts_SInvalidIcon 65394 +#define Consts_SInvalidPixelFormat 65395 +#define Consts_SScanLine 65396 +#define Consts_SChangeIconSize 65397 +#define Consts_SUnknownClipboardFormat 65398 +#define Consts_SOutOfResources 65399 +#define Consts_SNoCanvasHandle 65400 +#define Consts_SInvalidImageSize 65401 +#define Consts_SInvalidImageList 65402 +#define Consts_SImageIndexError 65403 +#define Consts_SImageReadFail 65404 +#define Consts_SImageWriteFail 65405 +#define Consts_SWindowDCError 65406 +#define Consts_SWindowClass 65407 +#define RTLConsts_SInvalidPropertyPath 65408 +#define RTLConsts_SInvalidPropertyValue 65409 +#define RTLConsts_SListCapacityError 65410 +#define RTLConsts_SListCountError 65411 +#define RTLConsts_SListIndexError 65412 +#define RTLConsts_SMemoryStreamError 65413 +#define RTLConsts_SPropertyException 65414 +#define RTLConsts_SReadError 65415 +#define RTLConsts_SReadOnlyProperty 65416 +#define RTLConsts_SResNotFound 65417 +#define RTLConsts_SSeekNotImplemented 65418 +#define RTLConsts_SSortedListError 65419 +#define RTLConsts_SUnknownGroup 65420 +#define RTLConsts_SUnknownProperty 65421 +#define RTLConsts_SWriteError 65422 +#define RTLConsts_SThreadCreateError 65423 +#define SysConst_SLongDayNameSat 65424 +#define RTLConsts_SAncestorNotFound 65425 +#define RTLConsts_SAssignError 65426 +#define RTLConsts_SBitsIndexError 65427 +#define RTLConsts_SCantWriteResourceStreamError 65428 +#define RTLConsts_SCheckSynchronizeError 65429 +#define RTLConsts_SClassNotFound 65430 +#define RTLConsts_SDuplicateClass 65431 +#define RTLConsts_SDuplicateItem 65432 +#define RTLConsts_SDuplicateName 65433 +#define RTLConsts_SDuplicateString 65434 +#define RTLConsts_SFCreateErrorEx 65435 +#define RTLConsts_SFOpenErrorEx 65436 +#define RTLConsts_SInvalidImage 65437 +#define RTLConsts_SInvalidName 65438 +#define RTLConsts_SInvalidProperty 65439 +#define SysConst_SLongMonthNameOct 65440 +#define SysConst_SLongMonthNameNov 65441 +#define SysConst_SLongMonthNameDec 65442 +#define SysConst_SShortDayNameSun 65443 +#define SysConst_SShortDayNameMon 65444 +#define SysConst_SShortDayNameTue 65445 +#define SysConst_SShortDayNameWed 65446 +#define SysConst_SShortDayNameThu 65447 +#define SysConst_SShortDayNameFri 65448 +#define SysConst_SShortDayNameSat 65449 +#define SysConst_SLongDayNameSun 65450 +#define SysConst_SLongDayNameMon 65451 +#define SysConst_SLongDayNameTue 65452 +#define SysConst_SLongDayNameWed 65453 +#define SysConst_SLongDayNameThu 65454 +#define SysConst_SLongDayNameFri 65455 +#define SysConst_SShortMonthNameJun 65456 +#define SysConst_SShortMonthNameJul 65457 +#define SysConst_SShortMonthNameAug 65458 +#define SysConst_SShortMonthNameSep 65459 +#define SysConst_SShortMonthNameOct 65460 +#define SysConst_SShortMonthNameNov 65461 +#define SysConst_SShortMonthNameDec 65462 +#define SysConst_SLongMonthNameJan 65463 +#define SysConst_SLongMonthNameFeb 65464 +#define SysConst_SLongMonthNameMar 65465 +#define SysConst_SLongMonthNameApr 65466 +#define SysConst_SLongMonthNameMay 65467 +#define SysConst_SLongMonthNameJun 65468 +#define SysConst_SLongMonthNameJul 65469 +#define SysConst_SLongMonthNameAug 65470 +#define SysConst_SLongMonthNameSep 65471 +#define SysConst_SVarNotImplemented 65472 +#define SysConst_SVarUnexpected 65473 +#define SysConst_SExternalException 65474 +#define SysConst_SAssertionFailed 65475 +#define SysConst_SIntfCastError 65476 +#define SysConst_SSafecallException 65477 +#define SysConst_SAssertError 65478 +#define SysConst_SAbstractError 65479 +#define SysConst_SModuleAccessViolation 65480 +#define SysConst_SOSError 65481 +#define SysConst_SUnkOSError 65482 +#define SysConst_SShortMonthNameJan 65483 +#define SysConst_SShortMonthNameFeb 65484 +#define SysConst_SShortMonthNameMar 65485 +#define SysConst_SShortMonthNameApr 65486 +#define SysConst_SShortMonthNameMay 65487 +#define SysConst_SDispatchError 65488 +#define SysConst_SReadAccess 65489 +#define SysConst_SWriteAccess 65490 +#define SysConst_SFormatTooLong 65491 +#define SysConst_SVarArrayCreate 65492 +#define SysConst_SVarArrayBounds 65493 +#define SysConst_SVarArrayLocked 65494 +#define SysConst_SInvalidVarCast 65495 +#define SysConst_SInvalidVarOp 65496 +#define SysConst_SInvalidVarNullOp 65497 +#define SysConst_SInvalidVarOpWithHResultWithPrefix 65498 +#define SysConst_SVarTypeCouldNotConvert 65499 +#define SysConst_SVarTypeConvertOverflow 65500 +#define SysConst_SVarOverflow 65501 +#define SysConst_SVarInvalid 65502 +#define SysConst_SVarBadType 65503 +#define SysConst_SInvalidOp 65504 +#define SysConst_SZeroDivide 65505 +#define SysConst_SOverflow 65506 +#define SysConst_SUnderflow 65507 +#define SysConst_SInvalidPointer 65508 +#define SysConst_SInvalidCast 65509 +#define SysConst_SAccessViolationArg3 65510 +#define SysConst_SAccessViolationNoArg 65511 +#define SysConst_SStackOverflow 65512 +#define SysConst_SControlC 65513 +#define SysConst_SPrivilege 65514 +#define SysConst_SOperationAborted 65515 +#define SysConst_SException 65516 +#define SysConst_SExceptTitle 65517 +#define SysConst_SInvalidFormat 65518 +#define SysConst_SArgumentMissing 65519 +#define SysConst_SInvalidInteger 65520 +#define SysConst_SInvalidDateTime 65521 +#define SysConst_STimeEncodeError 65522 +#define SysConst_SDateEncodeError 65523 +#define SysConst_SOutOfMemory 65524 +#define SysConst_SInOutError 65525 +#define SysConst_SFileNotFound 65526 +#define SysConst_SInvalidFilename 65527 +#define SysConst_STooManyOpenFiles 65528 +#define SysConst_SAccessDenied 65529 +#define SysConst_SEndOfFile 65530 +#define SysConst_SDiskFull 65531 +#define SysConst_SInvalidInput 65532 +#define SysConst_SDivByZero 65533 +#define SysConst_SRangeError 65534 +#define SysConst_SIntOverflow 65535 +STRINGTABLE +BEGIN + ExtCtrls_clName3DDkShadow, "3D Dark Shadow" + ExtCtrls_clName3DLight, "3D Light" + ExtCtrls_clNameWindow, "Window Background" + ExtCtrls_clNameWindowFrame, "Window Frame" + ExtCtrls_clNameWindowText, "Window Text" + WinHelpViewer_hNoKeyword, "No help keyword specified." + TB2Consts_STBToolbarIndexOutOfBounds, "Toolbar item index out of range" + TB2Consts_STBToolbarItemReinserted, "Toolbar item already inserted" + TB2Consts_STBViewerNotFound, "An item viewer associated the specified item could not be found" + TB2Consts_STBChevronItemMoreButtonsHint, "More Buttons|" + TB2Consts_STBMDIWindowItemDefCaption, "(Window List)" + TB2Consts_STBDockParentNotAllowed, "A TTBDock control cannot be placed inside a tool window or another TTBDock" + TB2Consts_STBDockCannotChangePosition, "Cannot change Position of a TTBDock if it already contains controls" + ExtCtrls_clNameBtnShadow, "Button Shadow" + ExtCtrls_clNameBtnText, "Button Text" + ExtCtrls_clNameCaptionText, "Caption Text" + ExtCtrls_clNameDefault, "Default" + ExtCtrls_clNameGrayText, "Gray Text" + ExtCtrls_clNameHighlight, "Highlight Background" + ExtCtrls_clNameHighlightText, "Highlight Text" + ExtCtrls_clNameInactiveBorder, "Inactive Border" + ExtCtrls_clNameInactiveCaption, "Inactive Caption" + ExtCtrls_clNameInactiveCaptionText, "Inactive Caption Text" + ExtCtrls_clNameInfoBk, "Info Background" + ExtCtrls_clNameInfoText, "Info Text" + ExtCtrls_clNameMenu, "Menu Background" + ExtCtrls_clNameMenuText, "Menu Text" + ExtCtrls_clNameNone, "None" + ExtCtrls_clNameScrollBar, "Scroll Bar" + ExtCtrls_clNameLime, "Lime" + ExtCtrls_clNameYellow, "Yellow" + ExtCtrls_clNameBlue, "Blue" + ExtCtrls_clNameFuchsia, "Fuchsia" + ExtCtrls_clNameAqua, "Aqua" + ExtCtrls_clNameWhite, "White" + ExtCtrls_clNameMoneyGreen, "Money Green" + ExtCtrls_clNameSkyBlue, "Sky Blue" + ExtCtrls_clNameCream, "Cream" + ExtCtrls_clNameMedGray, "Medium Gray" + ExtCtrls_clNameActiveBorder, "Active Border" + ExtCtrls_clNameActiveCaption, "Active Caption" + ExtCtrls_clNameAppWorkSpace, "Application Workspace" + ExtCtrls_clNameBackground, "Background" + ExtCtrls_clNameBtnFace, "Button Face" + ExtCtrls_clNameBtnHighlight, "Button Highlight" + Consts_SErrorSettingCount, "Error setting %s.Count" + Consts_SListBoxMustBeVirtual, "Listbox (%s) style must be virtual in order to set Count" + HelpIntfs_hNoTableOfContents, "Unable to find a Table of Contents" + HelpIntfs_hNothingFound, "No help found for %s" + HelpIntfs_hNoContext, "No context-sensitive help installed" + HelpIntfs_hNoTopics, "No topic-based help system installed" + ExtCtrls_clNameBlack, "Black" + ExtCtrls_clNameMaroon, "Maroon" + ExtCtrls_clNameGreen, "Green" + ExtCtrls_clNameOlive, "Olive" + ExtCtrls_clNameNavy, "Navy" + ExtCtrls_clNamePurple, "Purple" + ExtCtrls_clNameTeal, "Teal" + ExtCtrls_clNameGray, "Gray" + ExtCtrls_clNameSilver, "Silver" + ExtCtrls_clNameRed, "Red" + Consts_SmkcUp, "Up" + Consts_SmkcRight, "Right" + Consts_SmkcDown, "Down" + Consts_SmkcIns, "Ins" + Consts_SmkcDel, "Del" + Consts_SmkcShift, "Shift+" + Consts_SmkcCtrl, "Ctrl+" + Consts_SmkcAlt, "Alt+" + Consts_SInsertLineError, "Unable to insert a line" + Consts_SIconToClipboard, "Clipboard does not support Icons" + Consts_SInvalidMemoSize, "Text exceeds memo capacity" + Consts_SDuplicateMenus, "Menu '%s' is already being used by another form" + Consts_SDockedCtlNeedsName, "Docked control must have a name" + Consts_SDockTreeRemoveError, "Error removing control from dock tree" + Consts_SDockZoneNotFound, " - Dock zone not found" + Consts_SDockZoneHasNoCtl, " - Dock zone has no control" + Consts_SMsgDlgAbort, "&Abort" + Consts_SMsgDlgRetry, "&Retry" + Consts_SMsgDlgIgnore, "&Ignore" + Consts_SMsgDlgAll, "&All" + Consts_SMsgDlgNoToAll, "N&o to All" + Consts_SMsgDlgYesToAll, "Yes to &All" + Consts_SmkcBkSp, "BkSp" + Consts_SmkcTab, "Tab" + Consts_SmkcEsc, "Esc" + Consts_SmkcEnter, "Enter" + Consts_SmkcSpace, "Space" + Consts_SmkcPgUp, "PgUp" + Consts_SmkcPgDn, "PgDn" + Consts_SmkcEnd, "End" + Consts_SmkcHome, "Home" + Consts_SmkcLeft, "Left" + Consts_SHelpButton, "&Help" + Consts_SCloseButton, "&Close" + Consts_SIgnoreButton, "&Ignore" + Consts_SRetryButton, "&Retry" + Consts_SAbortButton, "Abort" + Consts_SAllButton, "&All" + Consts_SCannotDragForm, "Cannot drag a form" + Consts_SMsgDlgWarning, "Warning" + Consts_SMsgDlgError, "Error" + Consts_SMsgDlgInformation, "Information" + Consts_SMsgDlgConfirm, "Confirm" + Consts_SMsgDlgYes, "&Yes" + Consts_SMsgDlgNo, "&No" + Consts_SMsgDlgOK, "OK" + Consts_SMsgDlgCancel, "Cancel" + Consts_SMsgDlgHelp, "&Help" + Consts_SCannotFocus, "Cannot focus a disabled or invisible window" + Consts_SParentRequired, "Control '%s' has no parent window" + Consts_SMDIChildNotVisible, "Cannot hide an MDI Child Form" + Consts_SVisibleChanged, "Cannot change Visible in OnShow or OnHide" + Consts_SCannotShowModal, "Cannot make a visible window modal" + Consts_SMenuIndexError, "Menu index out of range" + Consts_SMenuReinserted, "Menu inserted twice" + Consts_SMenuNotFound, "Sub-menu is not in menu" + Consts_SNoTimers, "Not enough timers available" + Consts_SGroupIndexTooLow, "GroupIndex cannot be less than a previous menu item's GroupIndex" + Consts_SNoMDIForm, "Cannot create form. No MDI forms are currently active" + Consts_SControlParentSetToSelf, "A control cannot have itself as its parent" + Consts_SOKButton, "OK" + Consts_SCancelButton, "Cancel" + Consts_SYesButton, "&Yes" + Consts_SNoButton, "&No" + RTLConsts_SThreadError, "Thread Error: %s (%d)" + Consts_SInvalidBitmap, "Bitmap image is not valid" + Consts_SInvalidIcon, "Icon image is not valid" + Consts_SInvalidPixelFormat, "Invalid pixel format" + Consts_SScanLine, "Scan line index out of range" + Consts_SChangeIconSize, "Cannot change the size of an icon" + Consts_SUnknownClipboardFormat, "Unsupported clipboard format" + Consts_SOutOfResources, "Out of system resources" + Consts_SNoCanvasHandle, "Canvas does not allow drawing" + Consts_SInvalidImageSize, "Invalid image size" + Consts_SInvalidImageList, "Invalid ImageList" + Consts_SImageIndexError, "Invalid ImageList Index" + Consts_SImageReadFail, "Failed to read ImageList data from stream" + Consts_SImageWriteFail, "Failed to write ImageList data to stream" + Consts_SWindowDCError, "Error creating window device context" + Consts_SWindowClass, "Error creating window class" + RTLConsts_SInvalidPropertyPath, "Invalid property path" + RTLConsts_SInvalidPropertyValue, "Invalid property value" + RTLConsts_SListCapacityError, "List capacity out of bounds (%d)" + RTLConsts_SListCountError, "List count out of bounds (%d)" + RTLConsts_SListIndexError, "List index out of bounds (%d)" + RTLConsts_SMemoryStreamError, "Out of memory while expanding memory stream" + RTLConsts_SPropertyException, "Error reading %s%s%s: %s" + RTLConsts_SReadError, "Stream read error" + RTLConsts_SReadOnlyProperty, "Property is read-only" + RTLConsts_SResNotFound, "Resource %s not found" + RTLConsts_SSeekNotImplemented, "%s.Seek not implemented" + RTLConsts_SSortedListError, "Operation not allowed on sorted list" + RTLConsts_SUnknownGroup, "%s not in a class registration group" + RTLConsts_SUnknownProperty, "Property %s does not exist" + RTLConsts_SWriteError, "Stream write error" + RTLConsts_SThreadCreateError, "Thread creation error: %s" + SysConst_SLongDayNameSat, "Saturday" + RTLConsts_SAncestorNotFound, "Ancestor for '%s' not found" + RTLConsts_SAssignError, "Cannot assign a %s to a %s" + RTLConsts_SBitsIndexError, "Bits index out of range" + RTLConsts_SCantWriteResourceStreamError, "Can't write to a read-only resource stream" + RTLConsts_SCheckSynchronizeError, "CheckSynchronize called from thread $%x, which is NOT the main thread" + RTLConsts_SClassNotFound, "Class %s not found" + RTLConsts_SDuplicateClass, "A class named %s already exists" + RTLConsts_SDuplicateItem, "List does not allow duplicates ($0%x)" + RTLConsts_SDuplicateName, "A component named %s already exists" + RTLConsts_SDuplicateString, "String list does not allow duplicates" + RTLConsts_SFCreateErrorEx, "Cannot create file \"%s\". %s" + RTLConsts_SFOpenErrorEx, "Cannot open file \"%s\". %s" + RTLConsts_SInvalidImage, "Invalid stream format" + RTLConsts_SInvalidName, "''%s'' is not a valid component name" + RTLConsts_SInvalidProperty, "Invalid property value" + SysConst_SLongMonthNameOct, "October" + SysConst_SLongMonthNameNov, "November" + SysConst_SLongMonthNameDec, "December" + SysConst_SShortDayNameSun, "Sun" + SysConst_SShortDayNameMon, "Mon" + SysConst_SShortDayNameTue, "Tue" + SysConst_SShortDayNameWed, "Wed" + SysConst_SShortDayNameThu, "Thu" + SysConst_SShortDayNameFri, "Fri" + SysConst_SShortDayNameSat, "Sat" + SysConst_SLongDayNameSun, "Sunday" + SysConst_SLongDayNameMon, "Monday" + SysConst_SLongDayNameTue, "Tuesday" + SysConst_SLongDayNameWed, "Wednesday" + SysConst_SLongDayNameThu, "Thursday" + SysConst_SLongDayNameFri, "Friday" + SysConst_SShortMonthNameJun, "Jun" + SysConst_SShortMonthNameJul, "Jul" + SysConst_SShortMonthNameAug, "Aug" + SysConst_SShortMonthNameSep, "Sep" + SysConst_SShortMonthNameOct, "Oct" + SysConst_SShortMonthNameNov, "Nov" + SysConst_SShortMonthNameDec, "Dec" + SysConst_SLongMonthNameJan, "January" + SysConst_SLongMonthNameFeb, "February" + SysConst_SLongMonthNameMar, "March" + SysConst_SLongMonthNameApr, "April" + SysConst_SLongMonthNameMay, "May" + SysConst_SLongMonthNameJun, "June" + SysConst_SLongMonthNameJul, "July" + SysConst_SLongMonthNameAug, "August" + SysConst_SLongMonthNameSep, "September" + SysConst_SVarNotImplemented, "Operation not supported" + SysConst_SVarUnexpected, "Unexpected variant error" + SysConst_SExternalException, "External exception %x" + SysConst_SAssertionFailed, "Assertion failed" + SysConst_SIntfCastError, "Interface not supported" + SysConst_SSafecallException, "Exception in safecall method" + SysConst_SAssertError, "%s (%s, line %d)" + SysConst_SAbstractError, "Abstract Error" + SysConst_SModuleAccessViolation, "Access violation at address %p in module '%s'. %s of address %p" + SysConst_SOSError, "System Error. Code: %d.\r\n%s" + SysConst_SUnkOSError, "A call to an OS function failed" + SysConst_SShortMonthNameJan, "Jan" + SysConst_SShortMonthNameFeb, "Feb" + SysConst_SShortMonthNameMar, "Mar" + SysConst_SShortMonthNameApr, "Apr" + SysConst_SShortMonthNameMay, "May" + SysConst_SDispatchError, "Variant method calls not supported" + SysConst_SReadAccess, "Read" + SysConst_SWriteAccess, "Write" + SysConst_SFormatTooLong, "Format string too long" + SysConst_SVarArrayCreate, "Error creating variant or safe array" + SysConst_SVarArrayBounds, "Variant or safe array index out of bounds" + SysConst_SVarArrayLocked, "Variant or safe array is locked" + SysConst_SInvalidVarCast, "Invalid variant type conversion" + SysConst_SInvalidVarOp, "Invalid variant operation" + SysConst_SInvalidVarNullOp, "Invalid NULL variant operation" + SysConst_SInvalidVarOpWithHResultWithPrefix, "Invalid variant operation (%s%.8x)\n%s" + SysConst_SVarTypeCouldNotConvert, "Could not convert variant of type (%s) into type (%s)" + SysConst_SVarTypeConvertOverflow, "Overflow while converting variant of type (%s) into type (%s)" + SysConst_SVarOverflow, "Variant overflow" + SysConst_SVarInvalid, "Invalid argument" + SysConst_SVarBadType, "Invalid variant type" + SysConst_SInvalidOp, "Invalid floating point operation" + SysConst_SZeroDivide, "Floating point division by zero" + SysConst_SOverflow, "Floating point overflow" + SysConst_SUnderflow, "Floating point underflow" + SysConst_SInvalidPointer, "Invalid pointer operation" + SysConst_SInvalidCast, "Invalid class typecast" + SysConst_SAccessViolationArg3, "Access violation at address %p. %s of address %p" + SysConst_SAccessViolationNoArg, "Access violation" + SysConst_SStackOverflow, "Stack overflow" + SysConst_SControlC, "Control-C hit" + SysConst_SPrivilege, "Privileged instruction" + SysConst_SOperationAborted, "Operation aborted" + SysConst_SException, "Exception %s in module %s at %p.\r\n%s%s\r\n" + SysConst_SExceptTitle, "Application Error" + SysConst_SInvalidFormat, "Format '%s' invalid or incompatible with argument" + SysConst_SArgumentMissing, "No argument for format '%s'" + SysConst_SInvalidInteger, "'%s' is not a valid integer value" + SysConst_SInvalidDateTime, "'%s' is not a valid date and time" + SysConst_STimeEncodeError, "Invalid argument to time encode" + SysConst_SDateEncodeError, "Invalid argument to date encode" + SysConst_SOutOfMemory, "Out of memory" + SysConst_SInOutError, "I/O error %d" + SysConst_SFileNotFound, "File not found" + SysConst_SInvalidFilename, "Invalid filename" + SysConst_STooManyOpenFiles, "Too many open files" + SysConst_SAccessDenied, "File access denied" + SysConst_SEndOfFile, "Read beyond end of file" + SysConst_SDiskFull, "Disk full" + SysConst_SInvalidInput, "Invalid numeric input" + SysConst_SDivByZero, "Division by zero" + SysConst_SRangeError, "Range check error" + SysConst_SIntOverflow, "Integer overflow" +END + diff --git a/official/2.1.6+2.1.beta1/TBX/Demo/Project1.exe b/official/2.1.6+2.1.beta1/TBX/Demo/Project1.exe new file mode 100644 index 0000000..b0f9728 Binary files /dev/null and b/official/2.1.6+2.1.beta1/TBX/Demo/Project1.exe differ diff --git a/official/2.1.6+2.1.beta1/TBX/Demo/Project1.res b/official/2.1.6+2.1.beta1/TBX/Demo/Project1.res new file mode 100644 index 0000000..bf64b35 Binary files /dev/null and b/official/2.1.6+2.1.beta1/TBX/Demo/Project1.res differ diff --git a/official/2.1.6+2.1.beta1/TBX/Demo/Unit1.dcu b/official/2.1.6+2.1.beta1/TBX/Demo/Unit1.dcu new file mode 100644 index 0000000..6cd9685 Binary files /dev/null and b/official/2.1.6+2.1.beta1/TBX/Demo/Unit1.dcu differ diff --git a/official/2.1.6+2.1.beta1/TBX/Demo/Unit1.ddp b/official/2.1.6+2.1.beta1/TBX/Demo/Unit1.ddp new file mode 100644 index 0000000..4370276 Binary files /dev/null and b/official/2.1.6+2.1.beta1/TBX/Demo/Unit1.ddp differ diff --git a/official/2.1.6+2.1.beta1/TBX/Demo/Unit1.dfm b/official/2.1.6+2.1.beta1/TBX/Demo/Unit1.dfm new file mode 100644 index 0000000..2f4229b Binary files /dev/null and b/official/2.1.6+2.1.beta1/TBX/Demo/Unit1.dfm differ diff --git a/official/2.1.6+2.1.beta1/TBX/Demo/Unit1.pas b/official/2.1.6+2.1.beta1/TBX/Demo/Unit1.pas new file mode 100644 index 0000000..ca09a7d --- /dev/null +++ b/official/2.1.6+2.1.beta1/TBX/Demo/Unit1.pas @@ -0,0 +1,487 @@ +unit Unit1; + +interface + +uses + Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Menus, + Dialogs, ImgList, StdCtrls, ExtCtrls, ComCtrls, TBX, TB2Dock, TB2Toolbar, + TB2Item, TB2Common, TB2ExtItems, TBXMDI, TBXExtItems, TBXSwitcher, + TBXLists, TBXDkPanels, TBXToolPals, TBXStatusBars, TB2MDI, + TBXOffice2003Theme, TB2ToolWindow, + Buttons, XPMan, TBXOfficeXPTheme, TBXWhidbeyTheme; + +type + TForm1 = class(TForm) + TBDock1: TTBXDock; + TBToolbar1: TTBXToolbar; + TBXSubmenuItem1: TTBXSubmenuItem; + TBXItem1: TTBXItem; + TBXItem2: TTBXItem; + TBXItem3: TTBXItem; + TBXItem4: TTBXItem; + mnEdit: TTBXSubmenuItem; + TBXItem5: TTBXItem; + TBXSeparatorItem1: TTBXSeparatorItem; + TBXSeparatorItem2: TTBXSeparatorItem; + TBXItem6: TTBXItem; + ImageList1: TImageList; + TBXItem7: TTBXItem; + TBXSeparatorItem3: TTBXSeparatorItem; + TBXItem8: TTBXItem; + TBXSubmenuItem3: TTBXSubmenuItem; + TBXSubmenuItem4: TTBXSubmenuItem; + TBXSeparatorItem4: TTBXSeparatorItem; + TBXItem9: TTBXItem; + TBXItem10: TTBXItem; + TBXItem11: TTBXItem; + TBXItem15: TTBXItem; + TBDock2: TTBXDock; + TBDock3: TTBXDock; + TBDock4: TTBXDock; + ImageList2: TImageList; + TBXSeparatorItem11: TTBXSeparatorItem; + TBXItem29: TTBXItem; + TBXItem28: TTBXItem; + TBXItem38: TTBXItem; + TBXToolbar2: TTBXToolbar; + TBXItem40: TTBXItem; + TBXItem41: TTBXItem; + TBXItem42: TTBXItem; + TBXSeparatorItem12: TTBXSeparatorItem; + TBXItem43: TTBXItem; + TBXItem44: TTBXItem; + TBXSeparatorItem13: TTBXSeparatorItem; + TBXItem45: TTBXItem; + TBXItem46: TTBXItem; + TBXItem47: TTBXItem; + TBXSeparatorItem14: TTBXSeparatorItem; + mnUndoItems: TTBXSubmenuItem; + TBXSubmenuItem9: TTBXSubmenuItem; + TBXItem12: TTBXItem; + TBXItem13: TTBXItem; + TBXSeparatorItem6: TTBXSeparatorItem; + bColorItem: TTBXColorItem; + TBXSubmenuItem6: TTBXSubmenuItem; + ColorDialog: TColorDialog; + TBXSubmenuItem2: TTBXSubmenuItem; + TBXItem16: TTBXItem; + TBXItem17: TTBXItem; + TBXItem18: TTBXItem; + TBXItem19: TTBXItem; + TBXSeparatorItem9: TTBXSeparatorItem; + TBXItem20: TTBXItem; + TBXItem21: TTBXItem; + TBXSeparatorItem10: TTBXSeparatorItem; + TBXItem22: TTBXItem; + TBXMDIHandler1: TTBXMDIHandler; + TBXSubmenuItem5: TTBXSubmenuItem; + TBXMDIWindowItem1: TTBXMDIWindowItem; + TBXItem23: TTBXItem; + TBXItem26: TTBXItem; + TBXSeparatorItem16: TTBXSeparatorItem; + TBXSwitcher: TTBXSwitcher; + TBXPopupMenu1: TTBXPopupMenu; + TBXItem36: TTBXItem; + TBXItem37: TTBXItem; + TBXSubmenuItem7: TTBXSubmenuItem; + TBXItem39: TTBXItem; + TBXItem55: TTBXItem; + TBXSeparatorItem17: TTBXSeparatorItem; + TBXItem56: TTBXItem; + TBXItem57: TTBXItem; + TBXItem58: TTBXItem; + TBXItem59: TTBXItem; + TBXToolbar3: TTBXToolbar; + TBXSeparatorItem18: TTBXSeparatorItem; + TBXItem61: TTBXItem; + TBXItem62: TTBXItem; + TBXItem64: TTBXItem; + TBXItem65: TTBXItem; + TBXItem66: TTBXItem; + TBXSeparatorItem19: TTBXSeparatorItem; + TBXSubmenuItem8: TTBXSubmenuItem; + TBXSeparatorItem20: TTBXSeparatorItem; + MoreColors: TTBXItem; + TBXSeparatorItem5: TTBXSeparatorItem; + TBXLabelItem1: TTBXLabelItem; + TBToolbar3: TTBXToolbar; + be1: TTBXSubmenuItem; + TBXItem24: TTBXItem; + TBXItem25: TTBXItem; + TBXItem30: TTBXItem; + be2: TTBXSubmenuItem; + be3: TTBXItem; + be4: TTBXItem; + TBXSeparatorItem8: TTBXSeparatorItem; + be5: TTBXItem; + be6: TTBXItem; + be7: TTBXSubmenuItem; + TBXItem27: TTBXItem; + TBXItem31: TTBXItem; + TBXEditItem2: TTBXEditItem; + TBXSeparatorItem7: TTBXSeparatorItem; + UndoList: TTBXUndoList; + UndoLabel: TTBXLabelItem; + lstFonts: TTBXComboBoxItem; + TBXComboList1: TTBXComboBoxItem; + ColorCombo: TTBXDropDownItem; + TBXSubmenuItem10: TTBXSubmenuItem; + TBXList1: TTBXStringList; + TBXSeparatorItem15: TTBXSeparatorItem; + DockablePanel: TTBXDockablePanel; + TBXPageScroller: TTBXPageScroller; + TBXLabel1: TTBXLabel; + TBXLabel2: TTBXLabel; + TBXLabel3: TTBXLabel; + TBXAlignmentPanel2: TTBXAlignmentPanel; + ListBox1: TListBox; + TBXLabel4: TTBXLabel; + TBXAlignmentPanel4: TTBXAlignmentPanel; + TBXToolbar1: TTBXToolbar; + TBXSubmenuItem11: TTBXSubmenuItem; + TBXSeparatorItem21: TTBXSeparatorItem; + TBXComboList2: TTBXComboBoxItem; + ClrDefault: TTBXColorItem; + ColorPalette: TTBXColorPalette; + TBXSeparatorItem26: TTBXSeparatorItem; + ToolPalette: TTBXToolPalette; + TBXCheckBox1: TTBXCheckBox; + TBXRadioButton1: TTBXRadioButton; + TBXRadioButton2: TTBXRadioButton; + TBXRadioButton3: TTBXRadioButton; + TBXCheckBox2: TTBXCheckBox; + TBXLink1: TTBXLink; + TBXLabel5: TTBXLabel; + TBXStatusBar: TTBXStatusBar; + Edit1: TEdit; + bColorButton: TTBXSubmenuItem; + TBXSeparatorItem22: TTBXSeparatorItem; + TBXVisibilityToggleItem1: TTBXVisibilityToggleItem; + TBXSpinEditItem1: TTBXSpinEditItem; + TBXSeparatorItem23: TTBXSeparatorItem; + TBXComboList3: TTBXComboBoxItem; + TBXMultiDock1: TTBXMultiDock; + TBXMultiDock2: TTBXMultiDock; + TBXMultiDock3: TTBXMultiDock; + TBXMultiDock4: TTBXMultiDock; + TBXDockablePanel1: TTBXDockablePanel; + TBXDockablePanel2: TTBXDockablePanel; + TBXDockablePanel3: TTBXDockablePanel; + TBXLabel6: TTBXLabel; + TBXRadioButton4: TTBXRadioButton; + TBXRadioButton5: TTBXRadioButton; + TBXRadioButton6: TTBXRadioButton; + TBXLabel7: TTBXLabel; + TBXCheckBox3: TTBXCheckBox; + TBXCheckBox4: TTBXCheckBox; + TBXToolWindow1: TTBXToolWindow; + TBXSpinEditItem2: TTBXSpinEditItem; + TBXComboBoxItem1: TTBXComboBoxItem; + XPManifest1: TXPManifest; + TBXButton1: TTBXButton; + TBXButton2: TTBXButton; + TBXButton3: TTBXButton; + TBXPageScroller1: TTBXPageScroller; + TBXButton4: TTBXButton; + TBXButton5: TTBXButton; + TBXButton6: TTBXButton; + pruebaedit: TTBXEditItem; + procedure TBXItem31Click(Sender: TObject); + procedure FormCreate(Sender: TObject); + procedure ListBox1Click(Sender: TObject); + procedure MakeNewWindow(Sender: TObject); + procedure TBXItem23Click(Sender: TObject); + procedure TBXItem26Click(Sender: TObject); + procedure TBXItem27Click(Sender: TObject); + procedure mnUndoItemsPopup(Sender: TTBCustomItem; FromLink: Boolean); + procedure UndoListChange(Sender: TObject); + procedure lstFontsMeasureHeight(Sender: TTBXCustomList; + ACanvas: TCanvas; var AHeight: Integer); + procedure lstFontsDrawItem(Sender: TTBXCustomList; ACanvas: TCanvas; + ARect: TRect; AIndex, AHoverIndex: Integer; var DrawDefault: Boolean); + procedure TBXItem60Click(Sender: TObject); + procedure MoreColorsClick(Sender: TObject); + procedure ColorPaletteChange(Sender: TObject); + procedure ClrDefaultClick(Sender: TObject); + procedure TBXRadioButton1Change(Sender: TObject); + procedure TBXRadioButton2Change(Sender: TObject); + procedure TBXRadioButton3Change(Sender: TObject); + procedure TBXCheckBox1Change(Sender: TObject); + procedure TBXStatusBarPanelClick(Sender: TTBXCustomStatusBar; + Panel: TTBXStatusPanel); + procedure bColorButtonDrawImage(Item: TTBCustomItem; + Viewer: TTBItemViewer; Canvas: TCanvas; ImageRect: TRect; + ImageOffset: TPoint; StateFlags: Integer); + procedure TBXSpinEditItem1TextToValue(Sender: TTBXCustomSpinEditItem; + const AText: String; out AValue: Extended; var CanConvert: Boolean); + procedure TBXSpinEditItem1ValueToText(Sender: TTBXCustomSpinEditItem; + const AValue: Extended; var Text: String); + procedure TBXSpinEditItem1Convert(Sender: TTBXCustomSpinEditItem; + const APrefix, APostfix: String; var AValue: Extended; + var CanConvert: Boolean); + procedure TBXComboList3Change(Sender: TObject; const Text: String); + procedure TBXRadioButton4Click(Sender: TObject); + procedure TBXCheckBox3Change(Sender: TObject); + procedure TBXCheckBox4Change(Sender: TObject); + procedure TBXColorSet1GetColorInfo(Sender: TTBXCustomColorSet; Col, + Row: Integer; var Color: TColor; var Name: String); + procedure be3Click(Sender: TObject); + end; + +var + Form1: TForm1; + +implementation + +uses Unit2, TBXUtils, TBXThemes; + +{$R *.DFM} + +procedure TForm1.TBXItem31Click(Sender: TObject); +begin + TTBXItem(Sender).Checked := True; +end; + +procedure TForm1.FormCreate(Sender: TObject); +var + C: HCURSOR; +begin + if not IsWindowsXP then + begin + TBXLabel1.Enabled := False; + TBXCheckBox1.Enabled := False; + end; + GetAvailableTBXThemes(ListBox1.Items); + lstFonts.Strings := Screen.Fonts; + + { Replace Borland's hand cursor with windows default one, if available } + C := LoadCursor(0, IDC_HAND); + if C <> 0 then Screen.Cursors[crHandPoint] := C; +end; + +procedure TForm1.ListBox1Click(Sender: TObject); +begin + TBXSetTheme(ListBox1.Items[ListBox1.ItemIndex]); +end; + +procedure TForm1.MakeNewWindow(Sender: TObject); +begin + TForm2.Create(Self); +end; + +procedure TForm1.TBXItem23Click(Sender: TObject); +begin + Cascade; +end; + +procedure TForm1.TBXItem26Click(Sender: TObject); +begin + Tile; +end; + +procedure TForm1.TBXItem27Click(Sender: TObject); +begin + TTBXItem(Sender).Checked := True; +end; + +type + TTBViewAccess = class(TTBView); + +procedure TForm1.mnUndoItemsPopup(Sender: TTBCustomItem; FromLink: Boolean); +begin + UndoList.ItemIndex := 0; +end; + +procedure TForm1.UndoListChange(Sender: TObject); +const + Actns: array [Boolean] of string = (' Action', ' Actions'); +begin + with UndoList do + UndoLabel.UpdateCaption('Undo ' + IntToStr(ItemIndex + 1) + Actns[ItemIndex <> 0]); +end; + +procedure TForm1.lstFontsMeasureHeight(Sender: TTBXCustomList; + ACanvas: TCanvas; var AHeight: Integer); +begin + AHeight := AHeight * 3 div 2; +end; + +procedure TForm1.lstFontsDrawItem(Sender: TTBXCustomList; ACanvas: TCanvas; + ARect: TRect; AIndex, AHoverIndex: Integer; var DrawDefault: Boolean); +var + S: string; +begin + S := lstFonts.Strings[AIndex]; + ACanvas.Font.Size := 12; + ACanvas.Font.Name := S; +end; + +procedure TForm1.TBXItem60Click(Sender: TObject); +begin + DockablePanel.Visible := True; +end; + +procedure TForm1.MoreColorsClick(Sender: TObject); +begin + with ColorDialog do + begin + Color := ColorPalette.Color; + if Execute then ColorPalette.Color := Color; + end; +end; + +procedure TForm1.ColorPaletteChange(Sender: TObject); +begin + ClrDefault.Checked := ColorPalette.Color = clNone; + ColorCombo.Text := ColorPalette.ColorToString(ColorPalette.Color); + bColorItem.Color := ColorPalette.Color; + bColorItem.Caption := 'Current Color: ' + ColorPalette.ColorToString(ColorPalette.Color); + bColorButton.Invalidate; +end; + +procedure TForm1.ClrDefaultClick(Sender: TObject); +begin + ColorPalette.Color := clNone; + ClrDefault.Checked := True; +end; + +procedure TForm1.TBXRadioButton1Change(Sender: TObject); +begin + TBXSwitcher.FlatMenuStyle := fmsAuto; +end; + +procedure TForm1.TBXRadioButton2Change(Sender: TObject); +begin + TBXSwitcher.FlatMenuStyle := fmsEnable; +end; + +procedure TForm1.TBXRadioButton3Change(Sender: TObject); +begin + TBXSwitcher.FlatMenuStyle := fmsDisable; +end; + +procedure TForm1.TBXCheckBox1Change(Sender: TObject); +begin + TBXSwitcher.EnableXPStyles := TBXCheckBox1.Checked; +end; + +procedure TForm1.TBXStatusBarPanelClick(Sender: TTBXCustomStatusBar; Panel: TTBXStatusPanel); +begin + if Panel.Index in [2, 4] then Panel.Enabled := not Panel.Enabled; +end; + +procedure TForm1.bColorButtonDrawImage(Item: TTBCustomItem; + Viewer: TTBItemViewer; Canvas: TCanvas; ImageRect: TRect; + ImageOffset: TPoint; StateFlags: Integer); +var + DC: HDC; + Color: TColor; +begin + DC := Canvas.Handle; + if not Boolean(StateFlags and ISF_DISABLED) then + begin + Color := ColorPalette.Color; + OffsetRect(ImageRect, ImageOffset.X, ImageOffset.Y); + ImageRect.Top := ImageRect.Bottom - 4; + if Color <> clNone then + begin + Canvas.Brush.Color := Color; + Canvas.FillRect(ImageRect); + end + else + begin + FrameRectEx(DC, ImageRect, clBtnShadow, True); + DitherRect(DC, ImageRect, clBtnFace, clBtnShadow); + end; + end; +end; + +procedure TForm1.TBXSpinEditItem1TextToValue( + Sender: TTBXCustomSpinEditItem; const AText: String; + out AValue: Extended; var CanConvert: Boolean); +begin + if CompareText(AText, 'Auto') = 0 then + begin + AValue := 0; + CanConvert := True; + end + else if CompareText(AText, 'pi') = 0 then + begin + AValue := 3.14; + CanConvert := True; + end; +end; + +procedure TForm1.TBXSpinEditItem1ValueToText( + Sender: TTBXCustomSpinEditItem; const AValue: Extended; + var Text: String); +begin + if AValue <= 0 then Text := 'Auto'; +end; + +procedure TForm1.TBXSpinEditItem1Convert(Sender: TTBXCustomSpinEditItem; + const APrefix, APostfix: String; var AValue: Extended; + var CanConvert: Boolean); +var + S: string; +begin + S := APostfix; + + { use current units if user did not type in units explicitly } + if Length(S) = 0 then S := Sender.Postfix; + + { convert everything to mm } + if CompareText(S, 'in') = 0 then AValue := AValue * 25.4 + else if CompareText(S, 'cm') = 0 then AValue := AValue * 10; + + { convert mm to current units } + if CompareText(Sender.Postfix, 'in') = 0 then AValue := AValue / 25.4 + else if CompareText(Sender.Postfix, 'cm') = 0 then AValue := AValue * 0.1; +end; + +procedure TForm1.TBXComboList3Change(Sender: TObject; const Text: String); +begin + TBXSpinEditItem1.Postfix := Text; +end; + +procedure TForm1.TBXRadioButton4Click(Sender: TObject); +begin + TBXDockablePanel1.CaptionRotation := TDPCaptionRotation((Sender as TComponent).Tag); +end; + +procedure TForm1.TBXCheckBox3Change(Sender: TObject); +var + B: Boolean; +begin + B := (Sender as TTBXCheckBox).Checked; + DockablePanel.SmoothDrag := B; + TBXDockablePanel1.SmoothDrag := B; + TBXDockablePanel2.SmoothDrag := B; + TBXDockablePanel3.SmoothDrag := B; +end; + +procedure TForm1.TBXCheckBox4Change(Sender: TObject); +var + B: Boolean; +begin + B := (Sender as TTBXCheckBox).Checked; + DockablePanel.SmoothDockedResize := B; + TBXDockablePanel1.SmoothDockedResize := B; + TBXDockablePanel2.SmoothDockedResize := B; + TBXDockablePanel3.SmoothDockedResize := B; +end; + +procedure TForm1.TBXColorSet1GetColorInfo(Sender: TTBXCustomColorSet; Col, + Row: Integer; var Color: TColor; var Name: String); +begin + Color := clRed; + Name := 'Red'; +end; + +procedure TForm1.be3Click(Sender: TObject); +begin + TBXToolbar3.View.Select(TBXToolbar3.View.Find(pruebaedit), True); + TBXToolbar3.View.ExecuteSelected(True); +end; + +end. diff --git a/official/2.1.6+2.1.beta1/TBX/Demo/Unit2.dcu b/official/2.1.6+2.1.beta1/TBX/Demo/Unit2.dcu new file mode 100644 index 0000000..596219f Binary files /dev/null and b/official/2.1.6+2.1.beta1/TBX/Demo/Unit2.dcu differ diff --git a/official/2.1.6+2.1.beta1/TBX/Demo/Unit2.dfm b/official/2.1.6+2.1.beta1/TBX/Demo/Unit2.dfm new file mode 100644 index 0000000..93c495c Binary files /dev/null and b/official/2.1.6+2.1.beta1/TBX/Demo/Unit2.dfm differ diff --git a/official/2.1.6+2.1.beta1/TBX/Demo/Unit2.pas b/official/2.1.6+2.1.beta1/TBX/Demo/Unit2.pas new file mode 100644 index 0000000..fafde92 --- /dev/null +++ b/official/2.1.6+2.1.beta1/TBX/Demo/Unit2.pas @@ -0,0 +1,44 @@ +unit Unit2; + +interface + +uses + Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, + ExtCtrls, StdCtrls; + +type + TForm2 = class(TForm) + Memo1: TMemo; + private + procedure WMEraseBkgnd(var Message: TMessage); message WM_ERASEBKGND; + public + constructor Create(AOwner: TComponent); override; + end; + +var + Form2: TForm2; + +implementation + +{$R *.DFM} + +var + N: Integer = 1; + +{ TForm2 } + +constructor TForm2.Create(AOwner: TComponent); +begin + inherited; + ControlStyle := ControlStyle + [csOpaque]; + Caption := 'MDI Child Window ' + IntToStr(N); + Inc(N); +end; + +procedure TForm2.WMEraseBkgnd(var Message: TMessage); +begin + Message.Result := 1; +end; + +end. + \ No newline at end of file diff --git a/official/2.1.6+2.1.beta1/TBX/Diffs/Readme.txt b/official/2.1.6+2.1.beta1/TBX/Diffs/Readme.txt new file mode 100644 index 0000000..489d9b0 --- /dev/null +++ b/official/2.1.6+2.1.beta1/TBX/Diffs/Readme.txt @@ -0,0 +1,2 @@ +This directory contains files required for patching Toolbar 2000 +sources to make them compatible with TBX. \ No newline at end of file diff --git a/official/2.1.6+2.1.beta1/TBX/Diffs/_cvs_patch-2_1_4.bat b/official/2.1.6+2.1.beta1/TBX/Diffs/_cvs_patch-2_1_4.bat new file mode 100644 index 0000000..ff38eca --- /dev/null +++ b/official/2.1.6+2.1.beta1/TBX/Diffs/_cvs_patch-2_1_4.bat @@ -0,0 +1 @@ +patch -p0 --backup < _cvs_patch-2_1_4.diff diff --git a/official/2.1.6+2.1.beta1/TBX/Diffs/_cvs_patch-2_1_4.diff b/official/2.1.6+2.1.beta1/TBX/Diffs/_cvs_patch-2_1_4.diff new file mode 100644 index 0000000..49460d7 --- /dev/null +++ b/official/2.1.6+2.1.beta1/TBX/Diffs/_cvs_patch-2_1_4.diff @@ -0,0 +1,1441 @@ +Index: TB2Common.pas +=================================================================== +RCS file: /data/cvs/tb2k/Source/TB2Common.pas,v +retrieving revision 1.28 +diff -u -r1.28 TB2Common.pas +--- TB2Common.pas 26 Feb 2004 07:05:57 -0000 1.28 ++++ TB2Common.pas 29 May 2004 22:19:14 -0000 +@@ -868,40 +868,82 @@ + procedure DrawRotatedText(const DC: HDC; AText: String; const ARect: TRect; + const AFormat: Cardinal); + { Like DrawText, but draws the text at a 270 degree angle. +- The only format flag this function respects is DT_HIDEPREFIX. Text is always +- drawn centered. } ++ The format flag this function respects are ++ DT_NOPREFIX, DT_HIDEPREFIX, DT_CENTER, DT_END_ELLIPSIS, DT_NOCLIP } + var + RotatedFont, SaveFont: HFONT; + TextMetrics: TTextMetric; +- X, Y, P, I, SU, FU: Integer; ++ X, Y, P, I, SU, FU, W: Integer; + SaveAlign: UINT; + SavePen, Pen: HPEN; ++ Clip: Boolean; ++ ++ function GetSize(DC: HDC; const S: string): Integer; ++ var ++ Size: TSize; ++ begin ++ GetTextExtentPoint32(DC, PChar(S), Length(S), Size); ++ Result := Size.cx; ++ end; ++ + begin ++ if Length(AText) = 0 then Exit; ++ + RotatedFont := CreateRotatedFont(DC); + SaveFont := SelectObject(DC, RotatedFont); + + GetTextMetrics(DC, TextMetrics); + X := ARect.Left + ((ARect.Right - ARect.Left) - TextMetrics.tmHeight) div 2; +- Y := ARect.Top + ((ARect.Bottom - ARect.Top) - GetTextWidth(DC, AText, True)) div 2; ++ ++ Clip := (AFormat and DT_NOCLIP) <> DT_NOCLIP; + + { Find the index of the character that should be underlined. Delete '&' + characters from the string. Like DrawText, only the last prefixed character + will be underlined. } + P := 0; + I := 1; +- while I <= Length(AText) do begin +- if AText[I] in LeadBytes then +- Inc(I) +- else if AText[I] = '&' then begin +- Delete(AText, I, 1); +- { Note: PChar cast is so that if Delete deleted the last character in +- the string, we don't step past the end of the string (which would cause +- an AV if AText is now empty), but rather look at the null character +- and treat it as an accelerator key like DrawText. } +- if PChar(AText)[I-1] <> '&' then +- P := I; ++ if (AFormat and DT_NOPREFIX) <> DT_NOPREFIX then ++ while I <= Length(AText) do begin ++ if AText[I] in LeadBytes then ++ Inc(I) ++ else if AText[I] = '&' then begin ++ Delete(AText, I, 1); ++ { Note: PChar cast is so that if Delete deleted the last character in ++ the string, we don't step past the end of the string (which would cause ++ an AV if AText is now empty), but rather look at the null character ++ and treat it as an accelerator key like DrawText. } ++ if PChar(AText)[I-1] <> '&' then ++ P := I; ++ end; ++ Inc(I); ++ end; ++ ++ if (AFormat and DT_END_ELLIPSIS) = DT_END_ELLIPSIS then ++ begin ++ if (Length(AText) > 1) and (GetSize(DC, AText) > ARect.Bottom - ARect.Top) then ++ begin ++ W := ARect.Bottom - ARect.Top; ++ if W > 2 then ++ begin ++ Delete(AText, Length(AText), 1); ++ while (Length(AText) > 1) and (GetSize(DC, AText + '...') > W) do ++ Delete(AText, Length(AText), 1); ++ end ++ else AText := AText[1]; ++ if P > Length(AText) then P := 0; ++ AText := AText + '...'; + end; +- Inc(I); ++ end; ++ ++ if (AFormat and DT_CENTER) = DT_CENTER then ++ Y := ARect.Top + ((ARect.Bottom - ARect.Top) - GetSize(DC, AText)) div 2 ++ else ++ Y := ARect.Top; ++ ++ if Clip then ++ begin ++ SaveDC(DC); ++ with ARect do IntersectClipRect(DC, Left, Top, Right, Bottom); + end; + + SaveAlign := SetTextAlign(DC, TA_BOTTOM); +@@ -920,6 +962,8 @@ + DeleteObject(Pen); + end; + ++ if Clip then RestoreDC(DC, -1); ++ + SelectObject(DC, SaveFont); + DeleteObject(RotatedFont); + end; +Index: TB2Dock.pas +=================================================================== +RCS file: /data/cvs/tb2k/Source/TB2Dock.pas,v +retrieving revision 1.88 +diff -u -r1.88 TB2Dock.pas +--- TB2Dock.pas 26 Feb 2004 07:05:57 -0000 1.88 ++++ TB2Dock.pas 29 May 2004 22:19:14 -0000 +@@ -82,9 +82,6 @@ + FDisableArrangeToolbars: Integer; { Increment to disable ArrangeToolbars } + FArrangeToolbarsNeeded: Boolean; + FNonClientWidth, FNonClientHeight: Integer; +- DockList: TList; { List of the toolbars docked, and those floating and have LastDock +- pointing to the dock. Items are casted in TTBCustomDockableWindow's. } +- DockVisibleList: TList; { Similar to DockList, but lists only docked and visible toolbars } + + { Property access methods } + //function GetVersion: TToolbar97Version; +@@ -102,14 +99,11 @@ + { Internal } + procedure BackgroundChanged(Sender: TObject); + procedure ChangeDockList(const Insert: Boolean; const Bar: TTBCustomDockableWindow); +- procedure ChangeWidthHeight(const NewWidth, NewHeight: Integer); + procedure CommitPositions; + procedure DrawNCArea(const DrawToDC: Boolean; const ADC: HDC; + const Clip: HRGN); + function GetDesignModeRowOf(const XY: Integer): Integer; +- function HasVisibleToolbars: Boolean; + procedure RelayMsgToFloatingBars(var Message: TMessage); +- function ToolbarVisibleOnDock(const AToolbar: TTBCustomDockableWindow): Boolean; + procedure ToolbarVisibilityChanged(const Bar: TTBCustomDockableWindow; + const ForceRemove: Boolean); + +@@ -128,21 +122,30 @@ + procedure WMPrintClient(var Message: TMessage); message WM_PRINTCLIENT; + procedure WMSysCommand(var Message: TWMSysCommand); message WM_SYSCOMMAND; + protected ++ DockList: TList; { List of the toolbars docked, and those floating and have LastDock ++ pointing to the dock. Items are casted in TTBCustomDockableWindow's. } ++ DockVisibleList: TList; { Similar to DockList, but lists only docked and visible toolbars } ++ function Accepts(ADockableWindow: TTBCustomDockableWindow): Boolean; virtual; + procedure AlignControls(AControl: TControl; var Rect: TRect); override; ++ procedure ChangeWidthHeight(const NewWidth, NewHeight: Integer); + procedure DrawBackground(DC: HDC; const DrawRect: TRect); virtual; + function GetPalette: HPALETTE; override; ++ function HasVisibleToolbars: Boolean; + procedure InvalidateBackgrounds; + procedure Loaded; override; + procedure Notification(AComponent: TComponent; Operation: TOperation); override; + procedure SetParent(AParent: TWinControl); override; ++ function ToolbarVisibleOnDock(const AToolbar: TTBCustomDockableWindow): Boolean; + procedure Paint; override; + function UsingBackground: Boolean; virtual; ++ property ArrangeToolbarsNeeded: Boolean read FArrangeToolbarsNeeded write FArrangeToolbarsNeeded; ++ property DisableArrangeToolbars: Integer read FDisableArrangeToolbars write FDisableArrangeToolbars; + public + constructor Create(AOwner: TComponent); override; + procedure CreateParams(var Params: TCreateParams); override; + destructor Destroy; override; + +- procedure ArrangeToolbars; ++ procedure ArrangeToolbars; virtual; + procedure BeginUpdate; + procedure EndUpdate; + function GetCurrentRowSize(const Row: Integer; var AFullSize: Boolean): Integer; +@@ -266,6 +269,7 @@ + private + { Property variables } + FAutoResize: Boolean; ++ FDblClickUndock: Boolean; + FDockPos, FDockRow, FEffectiveDockPos, FEffectiveDockRow: Integer; + FDocked: Boolean; + FCurrentDock, FDefaultDock, FLastDock: TTBDock; +@@ -427,6 +431,7 @@ + { Methods accessible to descendants } + procedure Arrange; + function CalcNCSizes: TPoint; virtual; ++ function CanDockTo(ADock: TTBDock): Boolean; virtual; + procedure ChangeSize(AWidth, AHeight: Integer); + function ChildControlTransparent(Ctl: TControl): Boolean; dynamic; + procedure Close; +@@ -451,7 +456,10 @@ + procedure ResizeTrack(var Rect: TRect; const OrigRect: TRect); dynamic; + procedure ResizeTrackAccept; dynamic; + procedure SizeChanging(const AWidth, AHeight: Integer); virtual; ++ property EffectiveDockPosAccess: Integer read FEffectiveDockPos write FEffectiveDockPos; ++ property EffectiveDockRowAccess: Integer read FEffectiveDockRow write FEffectiveDockRow; + public ++ property DblClickUndock: Boolean read FDblClickUndock write FDblClickUndock default True; + property Docked: Boolean read FDocked; + property CurrentDock: TTBDock read FCurrentDock write SetCurrentDock stored False; + property CurrentSize: Integer read FCurrentSize write FCurrentSize; +@@ -1000,6 +1008,11 @@ + end; + end; + ++function TTBDock.Accepts(ADockableWindow: TTBCustomDockableWindow): Boolean; ++begin ++ Result := AllowDrag; ++end; ++ + procedure TTBDock.AlignControls(AControl: TControl; var Rect: TRect); + begin + ArrangeToolbars; +@@ -2494,6 +2507,7 @@ + FActivateParent := True; + FBorderStyle := bsSingle; + FCloseButton := True; ++ FDblClickUndock := True; + FDockableTo := [dpTop, dpBottom, dpLeft, dpRight]; + FDockableWindowStyles := [tbdsResizeEightCorner, tbdsResizeClipCursor]; + FDockPos := -1; +@@ -2911,6 +2925,11 @@ + RemoveFromList(FDockForms, Form); + end; + ++function TTBCustomDockableWindow.CanDockTo(ADock: TTBDock): Boolean; ++begin ++ Result := ADock.Position in DockableTo; ++end; ++ + function TTBCustomDockableWindow.IsAutoResized: Boolean; + begin + Result := AutoResize or Assigned(CurrentDock) or Floating; +@@ -3879,11 +3898,6 @@ + + procedure BuildDockList; + +- function AcceptableDock(const D: TTBDock): Boolean; +- begin +- Result := D.FAllowDrag and (D.Position in DockableTo); +- end; +- + procedure Recurse(const ParentCtl: TWinControl); + var + D: TTBDockPosition; +@@ -3900,7 +3914,7 @@ + if (Controls[I] is TWinControl) and not(Controls[I] is TTBDock) then + Recurse(TWinControl(Controls[I])); + end; +- if (ParentCtl is TTBDock) and AcceptableDock(TTBDock(ParentCtl)) and ++ if (ParentCtl is TTBDock) and TTBDock(ParentCtl).Accepts(Self) and CanDockTo(TTBDock(ParentCtl)) and + (DockList.IndexOf(ParentCtl) = -1) then + DockList.Add(ParentCtl); + end; +@@ -3912,7 +3926,7 @@ + begin + { Manually add CurrentDock to the DockList first so that it gets priority + over other docks } +- if Assigned(CurrentDock) and AcceptableDock(CurrentDock) then ++ if Assigned(CurrentDock) and CurrentDock.Accepts(Self) and CanDockTo(CurrentDock) then + DockList.Add(CurrentDock); + ParentForm := TBGetToolWindowParentForm(Self); + DockFormsList := TList.Create; +@@ -4201,19 +4215,20 @@ + procedure TTBCustomDockableWindow.DoubleClick; + begin + if Docked then begin +- if DockMode = dmCanFloat then begin ++ if DblClickUndock and (DockMode = dmCanFloat) then begin + Floating := True; + MoveOnScreen(True); + end; + end +- else +- if Assigned(LastDock) then +- Parent := LastDock +- else +- if Assigned(DefaultDock) then begin +- FDockRow := ForceDockAtTopRow; +- FDockPos := ForceDockAtLeftPos; +- Parent := DefaultDock; ++ else if Floating then begin ++ if Assigned(LastDock) then ++ Parent := LastDock ++ else ++ if Assigned(DefaultDock) then begin ++ FDockRow := ForceDockAtTopRow; ++ FDockPos := ForceDockAtLeftPos; ++ Parent := DefaultDock; ++ end; + end; + end; + +Index: TB2DsgnItemEditor.pas +=================================================================== +RCS file: /data/cvs/tb2k/Source/TB2DsgnItemEditor.pas,v +retrieving revision 1.52 +diff -u -r1.52 TB2DsgnItemEditor.pas +--- TB2DsgnItemEditor.pas 26 Feb 2004 07:05:57 -0000 1.52 ++++ TB2DsgnItemEditor.pas 29 May 2004 22:19:14 -0000 +@@ -152,6 +152,12 @@ + procedure TBRegisterItemClass(AClass: TTBCustomItemClass; + const ACaption: String; ResInstance: HINST); + ++type ++ TTBDsgnEditorHook = procedure(Sender: TTBItemEditForm) of object; ++ ++procedure TBRegisterDsgnEditorHook(Hook: TTBDsgnEditorHook); ++procedure TBUnregisterDsgnEditorHook(Hook: TTBDsgnEditorHook); ++ + implementation + + {$R *.DFM} +@@ -179,6 +185,7 @@ + var + ItemClasses: TList; + ItemImageList: TImageList; ++ EditFormHooks: TList; + + {$IFNDEF JR_D6} + function CreateSelectionList: TDesignerSelectionList; +@@ -240,7 +247,18 @@ + const ACaption: String; ResInstance: HINST); + var + Info: PItemClassInfo; ++ I: Integer; + begin ++ if ItemClasses <> nil then ++ for I := ItemClasses.Count - 1 downto 0 do ++ begin ++ Info := ItemClasses[I]; ++ if Info.ItemClass = AClass then ++ begin ++ Dispose(Info); ++ ItemClasses.Delete(I); ++ end; ++ end; + New(Info); + Info.ItemClass := AClass; + Info.Caption := ACaption; +@@ -357,6 +375,11 @@ + Item.OnClick := MoreItemClick; + MoreMenu.Add(Item); + end; ++ { Run the hooks } ++ ++ if EditFormHooks <> nil then ++ for I := 0 to EditFormHooks.Count - 1 do ++ TTBDsgnEditorHook(EditFormHooks[I]^)(Self); + end; + + destructor TTBItemEditForm.Destroy; +@@ -1332,14 +1355,44 @@ + Result := '(TB2000 Items)'; + end; + ++ ++procedure TBRegisterDsgnEditorHook(Hook: TTBDsgnEditorHook); ++var ++ H: ^TTBDsgnEditorHook; ++begin ++ New(H); ++ H^ := Hook; ++ EditFormHooks.Add(H); ++end; ++ ++procedure TBUnregisterDsgnEditorHook(Hook: TTBDsgnEditorHook); ++var ++ H: ^TTBDsgnEditorHook; ++ I: Integer; ++begin ++ for I := EditFormHooks.Count - 1 downto 0 do ++ begin ++ H := EditFormHooks[I]; ++ if (TMethod(H^).Code = TMethod(Hook).Code) and ++ (TMethod(H^).Data = TMethod(Hook).Data) then ++ begin ++ Dispose(H); ++ EditFormHooks.Delete(I); ++// Break; ++ end; ++ end; ++end; ++ + initialization + ItemImageList := TImageList.Create(nil); + ItemImageList.Handle := ImageList_LoadImage(HInstance, 'TB2_DSGNEDITORIMAGES', + 16, 0, clFuchsia, IMAGE_BITMAP, 0); + ItemClasses := TList.Create; ++ EditFormHooks := TList.Create; + AddModuleUnloadProc(UnregisterModuleItemClasses); + finalization + RemoveModuleUnloadProc(UnregisterModuleItemClasses); + FreeItemClasses; + FreeAndNil(ItemImageList); ++ FreeAndNil(EditFormHooks); + end. +Index: TB2ExtItems.pas +=================================================================== +RCS file: /data/cvs/tb2k/Source/TB2ExtItems.pas,v +retrieving revision 1.56 +diff -u -r1.56 TB2ExtItems.pas +--- TB2ExtItems.pas 26 Feb 2004 07:05:57 -0000 1.56 ++++ TB2ExtItems.pas 29 May 2004 22:19:14 -0000 +@@ -43,6 +43,11 @@ + EditItemDefaultEditOptions = []; + EditItemDefaultEditWidth = 64; + ++{ Change reasons for TTBEditItem.Text property } ++ tcrSetProperty = 0; // direct assignment to TTBEditItem.Text property ++ tcrActionLink = 1; // change comes from an action link ++ tcrEditControl = 2; // change is caused by typing in edit area ++ + type + TTBEditItem = class; + TTBEditItemViewer = class; +@@ -96,6 +101,7 @@ + FEditCaption: String; + FEditOptions: TTBEditItemOptions; + FEditWidth: Integer; ++ FExtendedAccept: Boolean; + FMaxLength: Integer; + FOnAcceptText: TTBAcceptTextEvent; + FOnBeginEdit: TTBBeginEditEvent; +@@ -112,10 +118,15 @@ + procedure SetText(Value: String); + protected + procedure ActionChange(Sender: TObject; CheckDefaults: Boolean); override; ++ function DoAcceptText(var NewText: string): Boolean; virtual; + procedure DoBeginEdit(Viewer: TTBEditItemViewer); virtual; ++ procedure DoTextChanging(const OldText: String; var NewText: String; Reason: Integer); virtual; ++ procedure DoTextChanged(Reason: Integer); virtual; + function GetActionLinkClass: TTBCustomItemActionLinkClass; override; + function GetItemViewerClass(AView: TTBView): TTBItemViewerClass; override; + function NeedToRecreateViewer(AViewer: TTBItemViewer): Boolean; override; ++ property ExtendedAccept: Boolean read FExtendedAccept write FExtendedAccept default False; ++ procedure SetTextEx(Value: String; Reason: Integer); + public + constructor Create(AOwner: TComponent); override; + procedure Clear; +@@ -146,6 +157,8 @@ + property OnSelect; + end; + ++ TEditClass = class of TEdit; ++ + TTBEditItemViewer = class(TTBItemViewer) + private + FEditControl: TEdit; +@@ -162,6 +175,7 @@ + function GetAccValue(var Value: WideString): Boolean; override; + function GetCaptionText: String; override; + procedure GetCursor(const Pt: TPoint; var ACursor: HCURSOR); override; ++ function GetEditControlClass: TEditClass; virtual; + procedure GetEditRect(var R: TRect); virtual; + procedure MouseDown(Shift: TShiftState; X, Y: Integer; + var MouseDownOnMenu: Boolean); override; +@@ -365,7 +379,7 @@ + + procedure TTBEditItemActionLink.SetText(const Value: String); + begin +- if IsTextLinked then TTBEditItem(FClient).Text := Value; ++ if IsTextLinked then TTBEditItem(FClient).SetTextEx(Value , tcrActionLink); + end; + + +@@ -389,7 +403,7 @@ + if not CheckDefaults or (Self.EditOptions = []) then + Self.EditOptions := EditOptions; + if not CheckDefaults or (Self.Text = '') then +- Self.Text := Text; ++ Self.SetTextEx(Text, tcrActionLink); + if not CheckDefaults or not Assigned(Self.OnAcceptText) then + Self.OnAcceptText := OnAcceptText; + end; +@@ -496,15 +510,41 @@ + end; + end; + +-procedure TTBEditItem.SetText(Value: String); ++function TTBEditItem.DoAcceptText(var NewText: string): Boolean; ++begin ++ Result := True; ++ if Assigned(FOnAcceptText) then FOnAcceptText(Self, NewText, Result); ++end; ++ ++procedure TTBEditItem.DoTextChanging(const OldText: String; var NewText: String; Reason: Integer); + begin + case FCharCase of +- ecUpperCase: Value := AnsiUpperCase(Value); +- ecLowerCase: Value := AnsiLowerCase(Value); ++ ecUpperCase: NewText := AnsiUpperCase(NewText); ++ ecLowerCase: NewText := AnsiLowerCase(NewText); ++ end; ++end; ++ ++procedure TTBEditItem.DoTextChanged(Reason: Integer); ++begin ++end; ++ ++procedure TTBEditItem.SetText(Value: String); ++begin ++ DoTextChanging(FText, Value, tcrSetProperty); ++ if FText <> Value then begin ++ FText := Value; ++ Change(False); ++ DoTextChanged(tcrSetProperty); + end; ++end; ++ ++procedure TTBEditItem.SetTextEx(Value: String; Reason: Integer); ++begin ++ DoTextChanging(FText, Value, Reason); + if FText <> Value then begin + FText := Value; + Change(False); ++ DoTextChanged(Reason); + end; + end; + +@@ -518,14 +558,9 @@ + procedure AcceptText; + var + S: String; +- Accept: Boolean; + begin + S := FEditControl.Text; +- Accept := True; +- if Assigned(Item.FOnAcceptText) then +- Item.FOnAcceptText(Self, S, Accept); +- if Accept then +- Item.Text := S; ++ if Item.DoAcceptText(S) then Item.SetTextEx(S, tcrEditControl); + end; + + begin +@@ -552,6 +587,11 @@ + TEditAccess(FEditControl).WndProc(Message); + end; + ++function TTBEditItemViewer.GetEditControlClass: TEditClass; ++begin ++ Result := TEdit; ++end; ++ + procedure TTBEditItemViewer.GetEditRect(var R: TRect); + var + Item: TTBEditItem; +@@ -771,6 +811,7 @@ + Item: TTBEditItem; + R: TRect; + ActiveWnd, FocusWnd: HWND; ++ S: string; + begin + Item := TTBEditItem(Self.Item); + GetEditRect(R); +@@ -784,8 +825,8 @@ + + { Create the edit control } + InflateRect(R, -3, -3); +- //View.FreeNotification(Self); +- FEditControl := TEdit.Create(nil); ++ //View.FreeNotification (Self); ++ FEditControl := GetEditControlClass.Create(nil); + try + FEditControl.Name := Format('%s_edit_control_%p', [ClassName, + Pointer(FEditControl)]); +@@ -812,9 +853,14 @@ + FEditControlStatus := [ecsContinueLoop]; + ControlMessageLoop; + finally ++ S := FEditControl.Text; + FreeAndNil(FEditControl); + end; + ++ with TTBEditItem(Item) do ++ if (FEditControlStatus = [ecsContinueLoop]) and ExtendedAccept then ++ if DoAcceptText(S) then SetTextEx(S, tcrEditControl); ++ + { ensure the area underneath the edit control is repainted immediately } + View.Window.Update; + { If app is still active, set focus to previous control and restore capture +Index: TB2Item.pas +=================================================================== +RCS file: /data/cvs/tb2k/Source/TB2Item.pas,v +retrieving revision 1.258 +diff -u -r1.258 TB2Item.pas +--- TB2Item.pas 26 Feb 2004 07:05:57 -0000 1.258 ++++ TB2Item.pas 29 May 2004 22:19:15 -0000 +@@ -1,5 +1,5 @@ + unit TB2Item; +- ++ + { + Toolbar2000 + Copyright (C) 1998-2004 by Jordan Russell +@@ -23,7 +23,7 @@ + GPL. If you do not delete the provisions above, a recipient may use your + version of this file under either the "Toolbar2000 License" or the GPL. + +- $jrsoftware: tb2k/Source/TB2Item.pas,v 1.258 2004/02/26 07:05:57 jr Exp $ ++ $jrsoftware: tb2k/Source/TB2Item.pas,v 1.259 2004/05/05 08:43:18 jr Exp $ + } + + interface +@@ -41,6 +41,14 @@ + Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, + StdCtrls, CommCtrl, Menus, ActnList, ImgList, TB2Anim; + ++const ++ WM_TB2K_POPUPSHOWING = WM_USER + 554; ++ ++ { Parameter in LParam of WM_TB2K_POPUPSHOWING } ++ TPS_ANIMSTART = 1; // animation query: if Result <> 0, do not animate! ++ TPS_ANIMFINISHED = 2; // only fired when animation thread is done ++ TPS_NOANIM = 3; // fired when animation is done, or if showing with no animation ++ + type + TTBCustomItem = class; + TTBCustomItemClass = class of TTBCustomItem; +@@ -82,7 +90,7 @@ + TTBItemStyle = set of (tbisSubmenu, tbisSelectable, tbisSeparator, + tbisEmbeddedGroup, tbisClicksTransparent, tbisCombo, tbisNoAutoOpen, + tbisSubitemsEditable, tbisNoLineBreak, tbisRightAlign, tbisDontSelectFirst, +- tbisRedrawOnSelChange, tbisRedrawOnMouseOverChange); ++ tbisRedrawOnSelChange, tbisRedrawOnMouseOverChange, tbisStretch); + TTBPopupAlignment = (tbpaLeft, tbpaRight, tbpaCenter); + TTBPopupEvent = procedure(Sender: TTBCustomItem; FromLink: Boolean) of object; + TTBSelectEvent = procedure(Sender: TTBCustomItem; Viewer: TTBItemViewer; +@@ -97,6 +105,18 @@ + {$IFNDEF JR_D5} + TImageIndex = type Integer; + {$ENDIF} ++ TTBPopupPositionRec = record ++ PositionAsSubmenu: Boolean; ++ Alignment: TTBPopupAlignment; ++ Opposite: Boolean; ++ MonitorRect: TRect; ++ ParentItemRect: TRect; ++ NCSizeX: Integer; ++ NCSizeY: Integer; ++ X, Y, W, H: Integer; ++ AnimDir: TTBAnimationDirection; ++ PlaySound: Boolean; ++ end; + + TTBCustomItem = class(TComponent) + private +@@ -186,6 +206,8 @@ + function GetChevronParentView: TTBView; virtual; + procedure GetChildren(Proc: TGetChildProc; Root: TComponent); override; + function GetItemViewerClass(AView: TTBView): TTBItemViewerClass; virtual; ++ procedure GetPopupPosition(ParentView: TTBView; ++ PopupWindow: TTBPopupWindow; var PopupPositionRec: TTBPopupPositionRec); virtual; + function GetPopupWindowClass: TTBPopupWindowClass; virtual; + procedure IndexError; + procedure Loaded; override; +@@ -315,7 +337,7 @@ + function DoExecute: Boolean; virtual; + procedure DrawItemCaption(const Canvas: TCanvas; ARect: TRect; + const ACaption: String; ADrawDisabledShadow: Boolean; AFormat: UINT); virtual; +- procedure Entering; virtual; ++ procedure Entering(OldSelected: TTBItemViewer); virtual; + function GetAccRole: Integer; virtual; + function GetAccValue(var Value: WideString): Boolean; virtual; + function GetCaptionText: String; virtual; +@@ -323,7 +345,7 @@ + function GetImageList: TCustomImageList; + function ImageShown: Boolean; + function IsRotated: Boolean; +- function IsToolbarSize: Boolean; ++ function IsToolbarSize: Boolean; virtual; + function IsPtInButtonPart(X, Y: Integer): Boolean; virtual; + procedure KeyDown(var Key: Word; Shift: TShiftState); virtual; + procedure Leaving; virtual; +@@ -352,7 +374,7 @@ + function GetAccObject: IDispatch; + function GetHintText: String; + function IsAccessible: Boolean; +- function IsToolbarStyle: Boolean; ++ function IsToolbarStyle: Boolean; virtual; + function ScreenToClient(const P: TPoint): TPoint; + end; + PTBItemViewerArray = ^TTBItemViewerArray; +@@ -450,6 +472,8 @@ + procedure KeyDown(var Key: Word; Shift: TShiftState); virtual; + procedure Notification(AComponent: TComponent; Operation: TOperation); override; + procedure SetAccelsVisibility(AShowAccels: Boolean); ++ procedure SetState(AState: TTBViewState); ++ property DoneActionData: TTBDoneActionData read FDoneActionData write FDoneActionData; + public + constructor CreateView(AOwner: TComponent; AParentView: TTBView; + AParentItem: TTBCustomItem; AWindow: TWinControl; +@@ -653,10 +677,12 @@ + procedure WMPrint(var Message: TMessage); message WM_PRINT; + procedure WMPrintClient(var Message: TMessage); message WM_PRINTCLIENT; + procedure WMTB2kStepAnimation(var Message: TMessage); message WM_TB2K_STEPANIMATION; ++ procedure WMTB2kAnimationEnded (var Message: TMessage); message WM_TB2K_ANIMATIONENDED; + protected + procedure CreateParams(var Params: TCreateParams); override; + procedure CreateWnd; override; + procedure DestroyWindowHandle; override; ++ function GetNCSize: TPoint; dynamic; + function GetViewClass: TTBViewClass; dynamic; + procedure Paint; override; + procedure PaintScrollArrows; virtual; +@@ -800,6 +826,21 @@ + var + ToolbarFont: TFont; + ++type ++ TTBModalHandler = class ++ private ++ FCreatedWnd: Boolean; ++ FInited: Boolean; ++ FWnd: HWND; ++ public ++ constructor Create(AExistingWnd: HWND); ++ destructor Destroy; override; ++ procedure Loop(const RootView: TTBView; const AMouseDown, AExecuteSelected, ++ AFromMSAA, TrackRightButton: Boolean); ++ property Wnd: HWND read FWnd; ++ end; ++ ++procedure ProcessDoneAction(const DoneActionData: TTBDoneActionData); + + implementation + +@@ -815,19 +856,6 @@ + ClickList: TList; + + type +- TTBModalHandler = class +- private +- FCreatedWnd: Boolean; +- FInited: Boolean; +- FWnd: HWND; +- public +- constructor Create(AExistingWnd: HWND); +- destructor Destroy; override; +- procedure Loop(const RootView: TTBView; const AMouseDown, AExecuteSelected, +- AFromMSAA, TrackRightButton: Boolean); +- property Wnd: HWND read FWnd; +- end; +- + PItemChangedNotificationData = ^TItemChangedNotificationData; + TItemChangedNotificationData = record + Proc: TTBItemChangedProc; +@@ -1645,10 +1673,11 @@ + var + PlayedSound: Boolean = False; + +-function TTBCustomItem.CreatePopup(const ParentView: TTBView; +- const ParentViewer: TTBItemViewer; const PositionAsSubmenu, SelectFirstItem, +- Customizing: Boolean; const APopupPoint: TPoint; +- const Alignment: TTBPopupAlignment): TTBPopupWindow; ++procedure TTBCustomItem.GetPopupPosition(ParentView: TTBView; ++ PopupWindow: TTBPopupWindow; var PopupPositionRec: TTBPopupPositionRec); ++var ++ X2, Y2: Integer; ++ RepeatCalcX: Boolean; + + function CountObscured(X, Y, W, H: Integer): Integer; + var +@@ -1672,114 +1701,9 @@ + end; + end; + +-var +- EventItem, ParentItem: TTBCustomItem; +- Opposite: Boolean; +- ChevronParentView: TTBView; +- X, X2, Y, Y2, W, H: Integer; +- P: TPoint; +- RepeatCalcX: Boolean; +- ParentItemRect: TRect; +- MonitorRect: TRect; +- AnimDir: TTBAnimationDirection; + begin +- EventItem := ItemContainingItems(Self); +- if EventItem <> Self then +- EventItem.DoPopup(Self, True); +- DoPopup(Self, False); +- +- ChevronParentView := GetChevronParentView; +- if ChevronParentView = nil then +- ParentItem := Self +- else +- ParentItem := ChevronParentView.FParentItem; +- +- Opposite := Assigned(ParentView) and (vsOppositePopup in ParentView.FState); +- Result := GetPopupWindowClass.CreatePopupWindow(nil, ParentView, ParentItem, +- Customizing); +- try +- if Assigned(ChevronParentView) then begin +- ChevronParentView.FreeNotification(Result.View); +- Result.View.FChevronParentView := ChevronParentView; +- Result.View.FIsToolbar := True; +- Result.View.Style := Result.View.Style + +- (ChevronParentView.Style * [vsAlwaysShowHints]); +- Result.Color := clBtnFace; +- end; +- +- { Calculate ParentItemRect, and MonitorRect (the rectangle of the monitor +- that the popup window will be confined to) } +- if Assigned(ParentView) then begin +- ParentView.ValidatePositions; +- ParentItemRect := ParentViewer.BoundsRect; +- P := ParentView.FWindow.ClientToScreen(Point(0, 0)); +- OffsetRect(ParentItemRect, P.X, P.Y); +- if not IsRectEmpty(ParentView.FMonitorRect) then +- MonitorRect := ParentView.FMonitorRect +- else +- MonitorRect := GetRectOfMonitorContainingRect(ParentItemRect, False); +- end +- else begin +- ParentItemRect.TopLeft := APopupPoint; +- ParentItemRect.BottomRight := APopupPoint; +- MonitorRect := GetRectOfMonitorContainingPoint(APopupPoint, False); +- end; +- Result.View.FMonitorRect := MonitorRect; +- +- { Initialize item positions and size of the popup window } +- if ChevronParentView = nil then +- Result.View.FMaxHeight := (MonitorRect.Bottom - MonitorRect.Top) - +- (PopupMenuWindowNCSize * 2) +- else +- Result.View.WrapOffset := (MonitorRect.Right - MonitorRect.Left) - +- (PopupMenuWindowNCSize * 2); +- if SelectFirstItem then +- Result.View.Selected := Result.View.FirstSelectable; +- Result.View.UpdatePositions; +- W := Result.Width; +- H := Result.Height; +- +- { Calculate initial X,Y position of the popup window } +- if Assigned(ParentView) then begin +- if not PositionAsSubmenu then begin +- if ChevronParentView = nil then begin +- if (ParentView = nil) or (ParentView.FOrientation <> tbvoVertical) then begin +- if GetSystemMetrics(SM_MENUDROPALIGNMENT) = 0 then +- X := ParentItemRect.Left +- else +- X := ParentItemRect.Right - W; +- Y := ParentItemRect.Bottom; +- end +- else begin +- X := ParentItemRect.Left - W; +- Y := ParentItemRect.Top; +- end; +- end +- else begin +- if ChevronParentView.FOrientation <> tbvoVertical then begin +- X := ParentItemRect.Right - W; +- Y := ParentItemRect.Bottom; +- end +- else begin +- X := ParentItemRect.Left - W; +- Y := ParentItemRect.Top; +- end; +- end; +- end +- else begin +- X := ParentItemRect.Right - PopupMenuWindowNCSize; +- Y := ParentItemRect.Top - PopupMenuWindowNCSize; +- end; +- end +- else begin +- X := APopupPoint.X; +- Y := APopupPoint.Y; +- case Alignment of +- tbpaRight: Dec(X, W); +- tbpaCenter: Dec(X, W div 2); +- end; +- end; +- ++ with PopupPositionRec do ++ begin + { Adjust the Y position of the popup window } + { If the window is going off the bottom of the monitor, try placing it + above the parent item } +@@ -1788,7 +1712,7 @@ + if not PositionAsSubmenu then + Y2 := ParentItemRect.Top + else +- Y2 := ParentItemRect.Bottom + PopupMenuWindowNCSize; ++ Y2 := ParentItemRect.Bottom + NCSizeY; + Dec(Y2, H); + { Only place it above the parent item if it isn't going to go off the + top of the monitor } +@@ -1864,17 +1788,17 @@ + X2 := X; + if Opposite or (X2 + W > MonitorRect.Right) then begin + if Assigned(ParentView) then +- X2 := ParentItemRect.Left + PopupMenuWindowNCSize; ++ X2 := ParentItemRect.Left + NCSizeX; + Dec(X2, W); + if not Opposite then +- Include(Result.View.FState, vsOppositePopup) ++ Include(PopupWindow.View.FState, vsOppositePopup) + else begin + if X2 < MonitorRect.Left then begin + Opposite := False; + RepeatCalcX := True; + end + else +- Include(Result.View.FState, vsOppositePopup); ++ Include(PopupWindow.View.FState, vsOppositePopup); + end; + end; + until not RepeatCalcX; +@@ -1901,8 +1825,141 @@ + else + Include(AnimDir, tbadLeft); + end; +- Result.FAnimationDirection := AnimDir; ++ end; ++end; ++ ++function TTBCustomItem.CreatePopup(const ParentView: TTBView; ++ const ParentViewer: TTBItemViewer; const PositionAsSubmenu, SelectFirstItem, ++ Customizing: Boolean; const APopupPoint: TPoint; ++ const Alignment: TTBPopupAlignment): TTBPopupWindow; ++var ++ EventItem, ParentItem: TTBCustomItem; ++ Opposite: Boolean; ++ ChevronParentView: TTBView; ++ X, Y, W, H: Integer; ++ P: TPoint; ++ ParentItemRect: TRect; ++ MonitorRect: TRect; ++ PopupRec: TTBPopupPositionRec; ++ NCSize: TPoint; ++begin ++ EventItem := ItemContainingItems(Self); ++ if EventItem <> Self then ++ EventItem.DoPopup(Self, True); ++ DoPopup(Self, False); ++ ++ ChevronParentView := GetChevronParentView; ++ if ChevronParentView = nil then ++ ParentItem := Self ++ else ++ ParentItem := ChevronParentView.FParentItem; + ++ Opposite := Assigned(ParentView) and (vsOppositePopup in ParentView.FState); ++ Result := GetPopupWindowClass.CreatePopupWindow(nil, ParentView, ParentItem, ++ Customizing); ++ try ++ if Assigned(ChevronParentView) then begin ++ ChevronParentView.FreeNotification(Result.View); ++ Result.View.FChevronParentView := ChevronParentView; ++ Result.View.FIsToolbar := True; ++ Result.View.Style := Result.View.Style + ++ (ChevronParentView.Style * [vsAlwaysShowHints]); ++ Result.Color := clBtnFace; ++ end; ++ ++ { Calculate ParentItemRect, and MonitorRect (the rectangle of the monitor ++ that the popup window will be confined to) } ++ if Assigned(ParentView) then begin ++ ParentView.ValidatePositions; ++ ParentItemRect := ParentViewer.BoundsRect; ++ P := ParentView.FWindow.ClientToScreen(Point(0, 0)); ++ OffsetRect(ParentItemRect, P.X, P.Y); ++ if not IsRectEmpty(ParentView.FMonitorRect) then ++ MonitorRect := ParentView.FMonitorRect ++ else ++ MonitorRect := GetRectOfMonitorContainingRect(ParentItemRect, False); ++ end ++ else begin ++ ParentItemRect.TopLeft := APopupPoint; ++ ParentItemRect.BottomRight := APopupPoint; ++ MonitorRect := GetRectOfMonitorContainingPoint(APopupPoint, False); ++ end; ++ Result.View.FMonitorRect := MonitorRect; ++ ++ { Initialize item positions and size of the popup window } ++ NCSize := Result.GetNCSize; ++ if ChevronParentView = nil then ++ Result.View.FMaxHeight := (MonitorRect.Bottom - MonitorRect.Top) - ++ (NCSize.Y * 2) ++ else ++ Result.View.WrapOffset := (MonitorRect.Right - MonitorRect.Left) - ++ (NCSize.X * 2); ++ if SelectFirstItem then ++ Result.View.Selected := Result.View.FirstSelectable; ++ Result.View.UpdatePositions; ++ W := Result.Width; ++ H := Result.Height; ++ ++ { Calculate initial X,Y position of the popup window } ++ if Assigned(ParentView) then begin ++ if not PositionAsSubmenu then begin ++ if ChevronParentView = nil then begin ++ if (ParentView = nil) or (ParentView.FOrientation <> tbvoVertical) then begin ++ if GetSystemMetrics(SM_MENUDROPALIGNMENT) = 0 then ++ X := ParentItemRect.Left ++ else ++ X := ParentItemRect.Right - W; ++ Y := ParentItemRect.Bottom; ++ end ++ else begin ++ X := ParentItemRect.Left - W; ++ Y := ParentItemRect.Top; ++ end; ++ end ++ else begin ++ if ChevronParentView.FOrientation <> tbvoVertical then begin ++ X := ParentItemRect.Right - W; ++ Y := ParentItemRect.Bottom; ++ end ++ else begin ++ X := ParentItemRect.Left - W; ++ Y := ParentItemRect.Top; ++ end; ++ end; ++ end ++ else begin ++ X := ParentItemRect.Right - NCSize.X; ++ Y := ParentItemRect.Top - NCSize.Y; ++ end; ++ end ++ else begin ++ X := APopupPoint.X; ++ Y := APopupPoint.Y; ++ case Alignment of ++ tbpaRight: Dec(X, W); ++ tbpaCenter: Dec(X, W div 2); ++ end; ++ end; ++ ++ PopupRec.PositionAsSubmenu := PositionAsSubmenu; ++ PopupRec.Alignment := Alignment; ++ PopupRec.Opposite := Opposite; ++ PopupRec.MonitorRect := MonitorRect; ++ PopupRec.ParentItemRect := ParentItemRect; ++ PopupRec.NCSizeX := NCSize.X; ++ PopupRec.NCSizeY := NCSize.Y; ++ PopupRec.X := X; ++ PopupRec.Y := Y; ++ PopupRec.W := W; ++ PopupRec.H := H; ++ PopupRec.AnimDir := []; ++ PopupRec.PlaySound := True; ++ GetPopupPosition(ParentView, Result, PopupRec); ++ X := PopupRec.X; ++ Y := PopupRec.Y; ++ W := PopupRec.W; ++ H := PopupRec.H; ++ Result.FAnimationDirection := PopupRec.AnimDir; + Result.SetBounds(X, Y, W, H); + if Assigned(ParentView) then begin + Result.FreeNotification(ParentView); +@@ -1916,7 +1973,7 @@ + end; + end; + Include(Result.View.FState, vsDrawInOrder); +- if not NeedToPlaySound('MenuPopup') then begin ++ if not PopupRec.PlaySound or not NeedToPlaySound('MenuPopup') then begin + { Don't call PlaySound if we don't have to } + Result.Visible := True; + end +@@ -3224,7 +3281,7 @@ + View.Invalidate(Self); + end; + +-procedure TTBItemViewer.Entering; ++procedure TTBItemViewer.Entering(OldSelected: TTBItemViewer); + begin + if Assigned(Item.FOnSelect) then + Item.FOnSelect(Item, Self, True); +@@ -4015,7 +4072,7 @@ + if Assigned(Value) then begin + if tbisRedrawOnSelChange in Value.Item.ItemStyle then + Invalidate(Value); +- Value.Entering; ++ Value.Entering(OldSelected); + end; + NotifyFocusEvent; + +@@ -4308,7 +4365,7 @@ + HighestHeightOnLine := TotalSize.Y; + end; + { Make separators on toolbars as tall/wide as the tallest/widest item } +- if tbisSeparator in Item.ItemStyle then begin ++ if [tbisSeparator, tbisStretch] * Item.ItemStyle <> [] then begin + if AOrientation <> tbvoVertical then + Pos.BoundsRect.Bottom := Pos.BoundsRect.Top + HighestHeightOnLine + else +@@ -5576,12 +5633,30 @@ + Result := GetRootView.FCaptureWnd; + end; + ++procedure TTBView.SetState(AState: TTBViewState); ++begin ++ FState := AState; ++end; ++ + + { TTBModalHandler } + ++const ++ LSFW_LOCK = 1; ++ LSFW_UNLOCK = 2; ++ ++var ++ LockSetForegroundWindowInited: BOOL; ++ LockSetForegroundWindow: function(uLockCode: UINT): BOOL; stdcall; ++ + constructor TTBModalHandler.Create(AExistingWnd: HWND); + begin + inherited Create; ++ if not LockSetForegroundWindowInited then begin ++ LockSetForegroundWindow := GetProcAddress(GetModuleHandle(user32), ++ 'LockSetForegroundWindow'); ++ LockSetForegroundWindowInited := True; ++ end; + LastPos := SmallPointToPoint(TSmallPoint(GetMessagePos())); + if AExistingWnd <> 0 then + FWnd := AExistingWnd +@@ -5589,6 +5664,13 @@ + FWnd := {$IFDEF JR_D6}Classes.{$ENDIF} AllocateHWnd(nil); + FCreatedWnd := True; + end; ++ if Assigned(LockSetForegroundWindow) then begin ++ { Like standard menus, don't allow other apps to steal the focus during ++ our modal loop. This also prevents us from losing activation when ++ "active window tracking" is enabled and the user moves the mouse over ++ another application's window. } ++ LockSetForegroundWindow(LSFW_LOCK); ++ end; + SetCapture(FWnd); + SetCursor(LoadCursor(0, IDC_ARROW)); + CallNotifyWinEvent(EVENT_SYSTEM_MENUSTART, FWnd, OBJID_CLIENT, CHILDID_SELF); +@@ -5597,6 +5679,8 @@ + + destructor TTBModalHandler.Destroy; + begin ++ if Assigned(LockSetForegroundWindow) then ++ LockSetForegroundWindow(LSFW_UNLOCK); + if FWnd <> 0 then begin + if GetCapture = FWnd then + ReleaseCapture; +@@ -6021,9 +6105,10 @@ + + procedure TTBPopupView.AutoSize(AWidth, AHeight: Integer); + begin +- with FWindow do +- SetBounds(Left, Top, AWidth + (PopupMenuWindowNCSize * 2), +- AHeight + (PopupMenuWindowNCSize * 2)); ++ with TTBPopupWindow(FWindow) do ++ with GetNCSize do ++ SetBounds(Left, Top, AWidth + (X * 2), ++ AHeight + (Y * 2)); + end; + + function TTBPopupView.GetFont: TFont; +@@ -6100,6 +6185,12 @@ + inherited; + end; + ++function TTBPopupWindow.GetNCSize: TPoint; ++begin ++ Result.X := PopupMenuWindowNCSize; ++ Result.Y := PopupMenuWindowNCSize; ++end; ++ + function TTBPopupWindow.GetViewClass: TTBViewClass; + begin + Result := TTBPopupView; +@@ -6183,8 +6274,12 @@ + SystemParametersInfo(SPI_GETMENUANIMATION, 0, @Animate, 0) and Animate then begin + Blend := SystemParametersInfo(SPI_GETMENUFADE, 0, @Animate, 0) and Animate; + if Blend or (FAnimationDirection <> []) then begin +- TBStartAnimation(WindowHandle, 150, Blend, FAnimationDirection); +- Exit; ++ if SendMessage(WindowHandle, WM_TB2K_POPUPSHOWING, TPS_ANIMSTART, 0) = 0 then ++ begin ++ { Start animation only if WM_TB2K_POPUPSHOWING returns zero (or not handled) } ++ TBStartAnimation(WindowHandle, 150, Blend, FAnimationDirection); ++ Exit; ++ end; + end; + end; + {$ENDIF} +@@ -6197,6 +6292,12 @@ + TBEndAnimation(WindowHandle); + end; + SetWindowPos(WindowHandle, 0, 0, 0, 0, 0, ShowFlags[Showing]); ++ if Showing then SendNotifyMessage(WindowHandle, WM_TB2K_POPUPSHOWING, TPS_NOANIM, 0); ++end; ++ ++procedure TTBPopupWindow.WMTB2kAnimationEnded(var Message: TMessage); ++begin ++ SendNotifyMessage(WindowHandle, WM_TB2K_POPUPSHOWING, TPS_ANIMFINISHED, 0); + end; + + procedure TTBPopupWindow.WMTB2kStepAnimation(var Message: TMessage); +@@ -6266,8 +6367,8 @@ + + procedure TTBPopupWindow.WMNCCalcSize(var Message: TWMNCCalcSize); + begin +- InflateRect(Message.CalcSize_Params^.rgrc[0], +- -PopupMenuWindowNCSize, -PopupMenuWindowNCSize); ++ with GetNCSize do ++ InflateRect(Message.CalcSize_Params^.rgrc[0], -X, -Y); + inherited; + end; + +Index: TB2MRU.pas +=================================================================== +RCS file: /data/cvs/tb2k/Source/TB2MRU.pas,v +retrieving revision 1.22 +diff -u -r1.22 TB2MRU.pas +--- TB2MRU.pas 26 Feb 2004 07:05:58 -0000 1.22 ++++ TB2MRU.pas 29 May 2004 22:19:15 -0000 +@@ -53,6 +53,7 @@ + procedure SetMaxItems(Value: Integer); + protected + property Container: TTBCustomItem read FContainer; ++ function GetFirstKey: Integer; virtual; + function GetItemClass: TTBCustomItemClass; virtual; + procedure SetItemCaptions; virtual; + public +@@ -107,7 +108,7 @@ + procedure Delete(Index: Integer); override; + function Get(Index: Integer): String; override; + function GetCount: Integer; override; +- function IndexOf(const S: String): Integer; override; ++ function IndexOf(const S: String): Integer; override; + procedure Insert(Index: Integer; const S: String); override; + procedure Move(CurIndex, NewIndex: Integer); override; + procedure Put(Index: Integer; const S: String); override; +@@ -296,20 +297,21 @@ + + procedure TTBMRUList.SetItemCaptions; + var +- I, J: Integer; ++ I, J, N: Integer; + Key: Char; + S: String; + Buf: array[0..MAX_PATH-1] of Char; + begin + while FList.Count > FMaxItems do + FList.Delete(FList.Count-1); ++ N := GetFirstKey; + for I := 0 to FContainer.Count-1 do begin + Key := #0; +- if I < 9 then +- Key := Chr(Ord('1') + I) ++ if N < 9 then ++ Key := Chr(Ord('1') + N) + else begin + { No more numbers; try letters } +- J := I - 9; ++ J := N - 9; + if J < 26 then + Key := Chr(Ord('A') + J); + end; +@@ -321,6 +323,7 @@ + FContainer[I].Caption := Format('&%s %s', [Key, S]) + else + FContainer[I].Caption := S; ++ Inc(N); + end; + end; + +@@ -361,6 +364,11 @@ + Result := TTBCustomItem; + end; + ++function TTBMRUList.GetFirstKey: Integer; ++begin ++ Result := 0; ++end; ++ + + { TTBMRUListItem } + +Index: TB2Reg.pas +=================================================================== +RCS file: /data/cvs/tb2k/Source/TB2Reg.pas,v +retrieving revision 1.27 +diff -u -r1.27 TB2Reg.pas +--- TB2Reg.pas 26 Feb 2004 07:05:58 -0000 1.27 ++++ TB2Reg.pas 29 May 2004 22:19:15 -0000 +@@ -36,13 +36,6 @@ + TB2Toolbar, TB2ToolWindow, TB2Dock, TB2Item, TB2ExtItems, TB2MRU, TB2MDI, + TB2DsgnItemEditor; + +-procedure Register; +- +-implementation +- +-uses +- ImgEdit; +- + {$IFDEF JR_D5} + + { TTBImageIndexPropertyEditor } +@@ -67,6 +60,25 @@ + const ARect: TRect; ASelected: Boolean); {$IFNDEF JR_D6} override; {$ENDIF} + end; + ++{ TTBItemImageIndexPropertyEditor } ++ ++type ++ TTBItemImageIndexPropertyEditor = class(TTBImageIndexPropertyEditor) ++ public ++ function GetImageListAt (Index: Integer): TCustomImageList; override; ++ end; ++ ++{$ENDIF} ++ ++procedure Register; ++ ++implementation ++ ++uses ++ ImgEdit; ++ ++{$IFDEF JR_D5} ++ + function TTBImageIndexPropertyEditor.GetAttributes: TPropertyAttributes; + begin + Result := [paMultiSelect, paValueList, paRevertable]; +@@ -128,12 +140,6 @@ + + { TTBItemImageIndexPropertyEditor } + +-type +- TTBItemImageIndexPropertyEditor = class(TTBImageIndexPropertyEditor) +- protected +- function GetImageListAt(Index: Integer): TCustomImageList; override; +- end; +- + function TTBItemImageIndexPropertyEditor.GetImageListAt(Index: Integer): TCustomImageList; + var + C: TPersistent; +Index: TB2ToolWindow.pas +=================================================================== +RCS file: /data/cvs/tb2k/Source/TB2ToolWindow.pas,v +retrieving revision 1.17 +diff -u -r1.17 TB2ToolWindow.pas +--- TB2ToolWindow.pas 26 Feb 2004 07:05:58 -0000 1.17 ++++ TB2ToolWindow.pas 29 May 2004 22:19:15 -0000 +@@ -195,14 +195,24 @@ + begin + Result.X := FBarWidth; + Result.Y := FBarHeight; +- if Assigned(ADock) and (FullSize or Stretch) then begin +- { If docked and stretching, return the minimum size so that the toolbar +- can shrink below FBarWidth/FBarHeight } +- if not(ADock.Position in [dpLeft, dpRight]) then +- Result.X := FMinClientWidth +- else +- Result.Y := FMinClientHeight; +- end; ++ if Assigned(ADock) then ++ if FullSize then ++ begin ++ { If docked and full size, return the size corresponding to docked size } ++ if not(ADock.Position in [dpLeft, dpRight]) then ++ Result.X := ADock.ClientWidth - (Width - ClientWidth) ++ else ++ Result.Y := ADock.ClientHeight - (Height - ClientHeight); ++ end ++ else if Stretch then ++ begin ++ { If docked and stretching, return the minimum size so that the toolbar ++ can shrink below FBarWidth/FBarHeight } ++ if not(ADock.Position in [dpLeft, dpRight]) then ++ Result.X := FMinClientWidth ++ else ++ Result.Y := FMinClientHeight; ++ end; + end; + + procedure TTBToolWindow.GetBaseSize(var ASize: TPoint); +Index: TB2Toolbar.pas +=================================================================== +RCS file: /data/cvs/tb2k/Source/TB2Toolbar.pas,v +retrieving revision 1.99 +diff -u -r1.99 TB2Toolbar.pas +--- TB2Toolbar.pas 26 Feb 2004 07:05:58 -0000 1.99 ++++ TB2Toolbar.pas 29 May 2004 22:19:15 -0000 +@@ -23,7 +23,7 @@ + GPL. If you do not delete the provisions above, a recipient may use your + version of this file under either the "Toolbar2000 License" or the GPL. + +- $jrsoftware: tb2k/Source/TB2Toolbar.pas,v 1.99 2004/02/26 07:05:58 jr Exp $ ++ $jrsoftware: tb2k/Source/TB2Toolbar.pas,v 1.100 2004/04/30 21:06:18 jr Exp $ + } + + interface +@@ -327,7 +327,9 @@ + SetWindowsHookExW, Msg.wParam may either be an ANSI character or a + Unicode character, due to an apparent bug on these platforms. It is + an ANSI character when the message passes through a separate +- SetWindowsHookExA-installed WH_GETMESSAGE hook first. ++ SetWindowsHookExA-installed WH_GETMESSAGE hook first, and that hook ++ calls us via CallNextHookEx. Windows apparently "forgets" to convert ++ the character from ANSI back to Unicode in this case. + We can't convert the character code because there seems to be no way + to detect whether it is ANSI or Unicode. So we can't really do much + with Msg.wParam, apart from comparing it against character codes that +@@ -340,9 +342,12 @@ + { Redirect the message to the main form. + Note: Unfortunately, due to a bug in Windows NT 4.0 (and not + 2000/XP/9x/Me), modifications to the message don't take effect if +- another WH_GETMESSAGE hook has been installed above this one. I +- don't know of any clean workaround, other than to ensure other +- WH_GETMESSAGE hooks are installed *before* Toolbar2000's. } ++ another WH_GETMESSAGE hook has been installed above this one. ++ (The bug is that CallNextHookEx copies lParam^ to a local buffer, but ++ does not propogate the changes made by the hook back to lParam^ when ++ it returns.) I don't know of any clean workaround, other than to ++ ensure other WH_GETMESSAGE hooks are installed *before* ++ Toolbar2000's. } + Msg.hwnd := MainForm.Handle; + end; + end; +@@ -891,6 +896,11 @@ + Hint := Item.Hint + else + Hint := ''; ++ ++ with TTBItemViewerAccess(FView.Find(Item)) do ++ begin ++ MouseMove(X - BoundsRect.Left, Y - BoundsRect.Top); ++ end; + end + else + Hint := ''; + diff --git a/official/2.1.6+2.1.beta1/TBX/Documentation/TBX Reference A4 Print.pdf b/official/2.1.6+2.1.beta1/TBX/Documentation/TBX Reference A4 Print.pdf new file mode 100644 index 0000000..5dbf145 Binary files /dev/null and b/official/2.1.6+2.1.beta1/TBX/Documentation/TBX Reference A4 Print.pdf differ diff --git a/official/2.1.6+2.1.beta1/TBX/Documentation/TBX Reference LTR Print.pdf b/official/2.1.6+2.1.beta1/TBX/Documentation/TBX Reference LTR Print.pdf new file mode 100644 index 0000000..72f6567 Binary files /dev/null and b/official/2.1.6+2.1.beta1/TBX/Documentation/TBX Reference LTR Print.pdf differ diff --git a/official/2.1.6+2.1.beta1/TBX/Documentation/TBX Reference LTR.pdf b/official/2.1.6+2.1.beta1/TBX/Documentation/TBX Reference LTR.pdf new file mode 100644 index 0000000..eecc007 --- /dev/null +++ b/official/2.1.6+2.1.beta1/TBX/Documentation/TBX Reference LTR.pdf @@ -0,0 +1,23199 @@ +%PDF-1.4 +5 0 obj +<< /S /GoTo /D (chapter.1) >> +endobj +8 0 obj +(Introduction) +endobj +9 0 obj +<< /S /GoTo /D (section*.2) >> +endobj +12 0 obj +(Features) +endobj +13 0 obj +<< /S /GoTo /D (section*.3) >> +endobj +16 0 obj +(License) +endobj +17 0 obj +<< /S /GoTo /D (section*.4) >> +endobj +20 0 obj +(Registration and Donations) +endobj +21 0 obj +<< /S /GoTo /D (section*.5) >> +endobj +24 0 obj +(Contacts) +endobj +25 0 obj +<< /S /GoTo /D (chapter.2) >> +endobj +28 0 obj +(Usage) +endobj +29 0 obj +<< /S /GoTo /D (section*.6) >> +endobj +32 0 obj +(Installing TBX Package) +endobj +33 0 obj +<< /S /GoTo /D (section*.7) >> +endobj +36 0 obj +(Getting Started) +endobj +37 0 obj +<< /S /GoTo /D (section*.8) >> +endobj +40 0 obj +(TBX Themes) +endobj +41 0 obj +<< /S /GoTo /D (subsection*.9) >> +endobj +44 0 obj +(Default Theme) +endobj +45 0 obj +<< /S /GoTo /D (subsection*.10) >> +endobj +48 0 obj +(Office XP Theme) +endobj +49 0 obj +<< /S /GoTo /D (subsection*.11) >> +endobj +52 0 obj +(Stripes Theme) +endobj +53 0 obj +<< /S /GoTo /D (subsection*.12) >> +endobj +56 0 obj +(Aluminum Theme) +endobj +57 0 obj +<< /S /GoTo /D (section*.13) >> +endobj +60 0 obj +(Converterting and Upgrading Existing Projects) +endobj +61 0 obj +<< /S /GoTo /D (subsection*.14) >> +endobj +64 0 obj +(Conversion Rules) +endobj +65 0 obj +<< /S /GoTo /D (subsection*.15) >> +endobj +68 0 obj +(Using TBX Converter) +endobj +69 0 obj +<< /S /GoTo /D (section*.16) >> +endobj +72 0 obj +(Known Issues) +endobj +73 0 obj +<< /S /GoTo /D (section*.17) >> +endobj +76 0 obj +(Frequently Asked Questions) +endobj +77 0 obj +<< /S /GoTo /D (chapter.3) >> +endobj +80 0 obj +(Reference) +endobj +81 0 obj +<< /S /GoTo /D (section*.18) >> +endobj +84 0 obj +(Unit TBX.pas) +endobj +85 0 obj +<< /S /GoTo /D (subsection*.19) >> +endobj +88 0 obj +(Class TFontSettings) +endobj +89 0 obj +<< /S /GoTo /D (subsection*.20) >> +endobj +92 0 obj +(Class TTBXCustomItem) +endobj +93 0 obj +<< /S /GoTo /D (subsection*.21) >> +endobj +96 0 obj +(Class TTBXDock) +endobj +97 0 obj +<< /S /GoTo /D (subsection*.22) >> +endobj +100 0 obj +(Class TTBXItem) +endobj +101 0 obj +<< /S /GoTo /D (subsection*.23) >> +endobj +104 0 obj +(Class TTBXPopupMenu) +endobj +105 0 obj +<< /S /GoTo /D (subsection*.24) >> +endobj +108 0 obj +(Class TTBXSeparatorItem) +endobj +109 0 obj +<< /S /GoTo /D (subsection*.25) >> +endobj +112 0 obj +(Class TTBXSubmenuItem) +endobj +113 0 obj +<< /S /GoTo /D (subsection*.26) >> +endobj +116 0 obj +(Class TTBXToolbar) +endobj +117 0 obj +<< /S /GoTo /D (subsection*.27) >> +endobj +120 0 obj +(Class TTBXToolWindow) +endobj +121 0 obj +<< /S /GoTo /D (subsection*.28) >> +endobj +124 0 obj +(Class TTBXVisibilityToggleItem) +endobj +125 0 obj +<< /S /GoTo /D (subsection*.29) >> +endobj +128 0 obj +(Routines) +endobj +129 0 obj +<< /S /GoTo /D (subsection*.35) >> +endobj +132 0 obj +(Types) +endobj +133 0 obj +<< /S /GoTo /D (subsection*.38) >> +endobj +136 0 obj +(Variables) +endobj +137 0 obj +<< /S /GoTo /D (section*.40) >> +endobj +140 0 obj +(Unit TBXDkPanels.pas) +endobj +141 0 obj +<< /S /GoTo /D (subsection*.41) >> +endobj +144 0 obj +(Class TTBXAlignmentPanel) +endobj +145 0 obj +<< /S /GoTo /D (subsection*.42) >> +endobj +148 0 obj +(Class TTBXButton) +endobj +149 0 obj +<< /S /GoTo /D (subsection*.43) >> +endobj +152 0 obj +(Class TTBXCheckBox) +endobj +153 0 obj +<< /S /GoTo /D (subsection*.44) >> +endobj +156 0 obj +(Class TTBXControlMargins) +endobj +157 0 obj +<< /S /GoTo /D (subsection*.45) >> +endobj +160 0 obj +(Class TTBXCustomButton) +endobj +161 0 obj +<< /S /GoTo /D (subsection*.46) >> +endobj +164 0 obj +(Class TTBXCustomCheckBox) +endobj +165 0 obj +<< /S /GoTo /D (subsection*.47) >> +endobj +168 0 obj +(Class TTBXCustomLabel) +endobj +169 0 obj +<< /S /GoTo /D (subsection*.48) >> +endobj +172 0 obj +(Class TTBXCustomLink) +endobj +173 0 obj +<< /S /GoTo /D (subsection*.49) >> +endobj +176 0 obj +(Class TTBXCustomPageScroller) +endobj +177 0 obj +<< /S /GoTo /D (subsection*.50) >> +endobj +180 0 obj +(Class TTBXCustomRadioButton) +endobj +181 0 obj +<< /S /GoTo /D (subsection*.51) >> +endobj +184 0 obj +(Class TTBXDockablePanel) +endobj +185 0 obj +<< /S /GoTo /D (subsection*.52) >> +endobj +188 0 obj +(Class TTBXLabel) +endobj +189 0 obj +<< /S /GoTo /D (subsection*.53) >> +endobj +192 0 obj +(Class TTBXLink) +endobj +193 0 obj +<< /S /GoTo /D (subsection*.54) >> +endobj +196 0 obj +(Class TTBXMultiDock) +endobj +197 0 obj +<< /S /GoTo /D (subsection*.55) >> +endobj +200 0 obj +(Class TTBXPageScroller) +endobj +201 0 obj +<< /S /GoTo /D (subsection*.56) >> +endobj +204 0 obj +(Class TTBXPanelObject) +endobj +205 0 obj +<< /S /GoTo /D (subsection*.57) >> +endobj +208 0 obj +(Class TTBXRadioButton) +endobj +209 0 obj +<< /S /GoTo /D (subsection*.58) >> +endobj +212 0 obj +(Class TTBXTextObject) +endobj +213 0 obj +<< /S /GoTo /D (subsection*.59) >> +endobj +216 0 obj +(Types) +endobj +217 0 obj +<< /S /GoTo /D (section*.61) >> +endobj +220 0 obj +(Unit TBXExtItems.pas) +endobj +221 0 obj +<< /S /GoTo /D (subsection*.62) >> +endobj +224 0 obj +(Class TTBXColorItem) +endobj +225 0 obj +<< /S /GoTo /D (subsection*.63) >> +endobj +228 0 obj +(Class TTBXComboBoxItem) +endobj +229 0 obj +<< /S /GoTo /D (subsection*.64) >> +endobj +232 0 obj +(Class TTBXCustomDropDownItem) +endobj +233 0 obj +<< /S /GoTo /D (subsection*.65) >> +endobj +236 0 obj +(Class TTBXCustomSpinEditItem) +endobj +237 0 obj +<< /S /GoTo /D (subsection*.66) >> +endobj +240 0 obj +(Class TTBXDropDownItem) +endobj +241 0 obj +<< /S /GoTo /D (subsection*.67) >> +endobj +244 0 obj +(Class TTBXEditItem) +endobj +245 0 obj +<< /S /GoTo /D (subsection*.68) >> +endobj +248 0 obj +(Class TTBXLabelItem) +endobj +249 0 obj +<< /S /GoTo /D (subsection*.69) >> +endobj +252 0 obj +(Class TTBXMRUList) +endobj +253 0 obj +<< /S /GoTo /D (subsection*.70) >> +endobj +256 0 obj +(Class TTBXMRUListItem) +endobj +257 0 obj +<< /S /GoTo /D (subsection*.71) >> +endobj +260 0 obj +(Class TTBXSpinEditItem) +endobj +261 0 obj +<< /S /GoTo /D (section*.72) >> +endobj +264 0 obj +(Unit TBXLists.pas) +endobj +265 0 obj +<< /S /GoTo /D (subsection*.73) >> +endobj +268 0 obj +(Class TTBXCustomList) +endobj +269 0 obj +<< /S /GoTo /D (subsection*.74) >> +endobj +272 0 obj +(Class TTBXStringList) +endobj +273 0 obj +<< /S /GoTo /D (subsection*.75) >> +endobj +276 0 obj +(Class TTBXUndoList) +endobj +277 0 obj +<< /S /GoTo /D (section*.76) >> +endobj +280 0 obj +(Unit TBXMDI.pas) +endobj +281 0 obj +<< /S /GoTo /D (subsection*.77) >> +endobj +284 0 obj +(Class TTBXMDIHandler) +endobj +285 0 obj +<< /S /GoTo /D (subsection*.78) >> +endobj +288 0 obj +(Class TTBXMDIWindowItem) +endobj +289 0 obj +<< /S /GoTo /D (section*.79) >> +endobj +292 0 obj +(Unit TBXStatusBars.pas) +endobj +293 0 obj +<< /S /GoTo /D (subsection*.80) >> +endobj +296 0 obj +(Class TTBXCustomStatusBar) +endobj +297 0 obj +<< /S /GoTo /D (subsection*.81) >> +endobj +300 0 obj +(Class TTBXStatusBar) +endobj +301 0 obj +<< /S /GoTo /D (subsection*.82) >> +endobj +304 0 obj +(Class TTBXStatusPanel) +endobj +305 0 obj +<< /S /GoTo /D (subsection*.83) >> +endobj +308 0 obj +(Class TTBXStatusPanels) +endobj +309 0 obj +<< /S /GoTo /D (section*.84) >> +endobj +312 0 obj +(Unit TBXSwitcher.pas) +endobj +313 0 obj +<< /S /GoTo /D (subsection*.85) >> +endobj +316 0 obj +(Class TTBXSwitcher) +endobj +317 0 obj +<< /S /GoTo /D (section*.86) >> +endobj +320 0 obj +(Unit TBXThemes.pas) +endobj +321 0 obj +<< /S /GoTo /D (subsection*.87) >> +endobj +324 0 obj +(Types) +endobj +325 0 obj +<< /S /GoTo /D (section*.89) >> +endobj +328 0 obj +(Unit TBXToolPals.pas) +endobj +329 0 obj +<< /S /GoTo /D (subsection*.90) >> +endobj +332 0 obj +(Class TTBXColorPalette) +endobj +333 0 obj +<< /S /GoTo /D (subsection*.91) >> +endobj +336 0 obj +(Class TTBXColorSet) +endobj +337 0 obj +<< /S /GoTo /D (subsection*.92) >> +endobj +340 0 obj +(Class TTBXCustomColorSet) +endobj +341 0 obj +<< /S /GoTo /D (subsection*.93) >> +endobj +344 0 obj +(Class TTBXCustomToolPalette) +endobj +345 0 obj +<< /S /GoTo /D (subsection*.94) >> +endobj +348 0 obj +(Class TTBXToolPalette) +endobj +349 0 obj +<< /S /GoTo /D (appendix.A) >> +endobj +352 0 obj +(Changes) +endobj +353 0 obj +<< /S /GoTo /D (appendix.A) >> +endobj +355 0 obj +(Index) +endobj +356 0 obj +<< /S /GoTo /D [357 0 R /Fit ] >> +endobj +359 0 obj << +/Length 502 +/Filter /FlateDecode +>> +stream +xڍSMo0 Wh'R%ӏ0ˇ]ifdKnHi$MJO{O4**RH*R족j;W ;M !qL Qg} rU0'HS{P?i/PL}_)9HS>bpX,3^aD*1@QqoUkmud>7`^c["ů)3 K{oxa[^'粺nʫT98`OPyҔa[ns-T.Tr>d d-EMʟ@~5 1de + 4R1d5-Ű^6RH S ʀ쭔8($|&cZA=1=p'ߢ(K{Q|[ ]Ϳcendstream +endobj +357 0 obj << +/Type /Page +/Contents 359 0 R +/Resources 358 0 R +/MediaBox [0 0 612 792] +/Parent 373 0 R +>> endobj +360 0 obj << +/D [357 0 R /XYZ 109.858 727.97 null] +>> endobj +361 0 obj << +/D [357 0 R /XYZ 109.858 703.064 null] +>> endobj +358 0 obj << +/Font << /F22 363 0 R /F21 366 0 R /F8 369 0 R /F14 372 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +376 0 obj << +/Length 2314 +/Filter /FlateDecode +>> +stream +x\ے}W| Ѳl:IEޥ*r@RF\&Q03*QeIv6 4V"J,6 4>z0!ez[ X_^g/ k<Ͽt,8k}M0=̄inf?MʴZ*؋O3hz)I1Ewf~}:K)R&qXHnIu^"# \d! >0 0>6tLίv aXw.tw[ՙ)TĀ|;>Con` aH*QKL+Kd`S~a|8lQ=RD ^)}Ƣo},vXȪxgKl!f/~<Վ'ñRe GO-`jeETCC҉>$C;~HTU3Vr*, + ۵?(6Q^0 +\G;7 b .7mWϮRwJ}hLJ]W +8+U=IaB%4B?\߼m`1(sR^[ WRK +Ļh=C;>ަ*P6@ӼŒy>2RL5GBNm1SsRhN~,v[,lʕ4kY$!7[ z}f槇GSF *J9@I@;= p63"Ud6͏ ֻ/ya}T~גo]))N9X 21.D +Jr0 Ech'tIUP'Ȗ\`Vil!c1ϝ6hܭc [2O\ Tl.U(R ܝJyD)P1!cJǍei+4[ D*5sRϽe=C;A< I9qrxޅe>ļyu /A ԌԢI4@@"4'rIa`D: ׇdh'hz;6A9 w& i r^y+NM{YbV߇v܏Ӧ@}-Z㸣F!z4%ܜ%A=,Vw Ȩ+7 7o.٥Z`%sm@$$X Z Ŋ'MI! _x 㺰(:-e I7C2SVy&&(O 66>Vn xIi|sbp7F1#&bv=S1״ Df=C;A Eq 2fL^ߞi[#ipK3b BLYгxĴc=C;A %5* 1&HE/w7ǧs,sS8k1t>suB>kNhM y aR_p8A*uixpʬOpfF"M@@;i=YAަHR`+Fw{4?J)1X*[*%Ȍճ͏@$:Gr`%hXպca8>*ܭs2;>I Ѫendstream +endobj +375 0 obj << +/Type /Page +/Contents 376 0 R +/Resources 374 0 R +/MediaBox [0 0 612 792] +/Parent 373 0 R +/Annots [ 382 0 R 386 0 R 387 0 R 388 0 R 389 0 R 390 0 R 391 0 R 392 0 R 393 0 R 394 0 R 395 0 R 396 0 R 397 0 R 398 0 R 399 0 R 400 0 R 401 0 R 402 0 R 403 0 R 404 0 R 405 0 R 406 0 R 407 0 R 408 0 R 409 0 R 410 0 R 411 0 R 412 0 R 413 0 R ] +>> endobj +382 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [108.862 580.346 188.964 589.257] +/Subtype /Link +/A << /S /GoTo /D (chapter.1) >> +>> endobj +386 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [123.806 563.41 162.549 572.21] +/Subtype /Link +/A << /S /GoTo /D (section*.2) >> +>> endobj +387 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [123.806 546.473 157.54 555.273] +/Subtype /Link +/A << /S /GoTo /D (section*.3) >> +>> endobj +388 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [123.806 527.599 246.042 538.448] +/Subtype /Link +/A << /S /GoTo /D (section*.4) >> +>> endobj +389 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [123.806 512.6 164.321 521.4] +/Subtype /Link +/A << /S /GoTo /D (section*.5) >> +>> endobj +390 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [108.862 483.764 155.68 494.529] +/Subtype /Link +/A << /S /GoTo /D (chapter.2) >> +>> endobj +391 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [123.806 466.827 229.631 477.676] +/Subtype /Link +/A << /S /GoTo /D (section*.6) >> +>> endobj +392 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [123.806 449.891 194.527 460.739] +/Subtype /Link +/A << /S /GoTo /D (section*.7) >> +>> endobj +393 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [123.806 434.892 184.661 443.803] +/Subtype /Link +/A << /S /GoTo /D (section*.8) >> +>> endobj +394 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [146.72 417.955 214.162 426.866] +/Subtype /Link +/A << /S /GoTo /D (subsection*.9) >> +>> endobj +395 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [146.72 401.019 224.401 409.93] +/Subtype /Link +/A << /S /GoTo /D (subsection*.10) >> +>> endobj +396 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [146.72 382.145 212.169 392.993] +/Subtype /Link +/A << /S /GoTo /D (subsection*.11) >> +>> endobj +397 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [146.72 367.146 227.86 376.057] +/Subtype /Link +/A << /S /GoTo /D (subsection*.12) >> +>> endobj +398 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [123.806 348.272 332.745 359.12] +/Subtype /Link +/A << /S /GoTo /D (section*.13) >> +>> endobj +399 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [146.72 333.273 223.986 342.184] +/Subtype /Link +/A << /S /GoTo /D (subsection*.14) >> +>> endobj +400 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [146.72 314.399 244.714 325.136] +/Subtype /Link +/A << /S /GoTo /D (subsection*.15) >> +>> endobj +401 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [123.806 299.4 185.187 308.2] +/Subtype /Link +/A << /S /GoTo /D (section*.16) >> +>> endobj +402 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [123.806 280.526 247.896 291.374] +/Subtype /Link +/A << /S /GoTo /D (section*.17) >> +>> endobj +403 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [108.862 255.564 175.072 264.475] +/Subtype /Link +/A << /S /GoTo /D (chapter.3) >> +>> endobj +404 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [123.806 236.69 187.705 247.428] +/Subtype /Link +/A << /S /GoTo /D (section*.18) >> +>> endobj +405 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [146.72 219.754 236.744 230.602] +/Subtype /Link +/A << /S /GoTo /D (subsection*.19) >> +>> endobj +406 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [146.72 204.755 257.499 213.666] +/Subtype /Link +/A << /S /GoTo /D (subsection*.20) >> +>> endobj +407 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [146.72 187.818 226.034 196.729] +/Subtype /Link +/A << /S /GoTo /D (subsection*.21) >> +>> endobj +408 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [146.72 170.882 223.958 179.793] +/Subtype /Link +/A << /S /GoTo /D (subsection*.22) >> +>> endobj +409 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [146.72 152.008 256.198 162.856] +/Subtype /Link +/A << /S /GoTo /D (subsection*.23) >> +>> endobj +410 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [146.72 135.071 266.078 145.92] +/Subtype /Link +/A << /S /GoTo /D (subsection*.24) >> +>> endobj +411 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [146.72 120.072 264.086 128.983] +/Subtype /Link +/A << /S /GoTo /D (subsection*.25) >> +>> endobj +412 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [146.72 103.136 237.546 112.047] +/Subtype /Link +/A << /S /GoTo /D (subsection*.26) >> +>> endobj +413 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [146.72 86.199 259.104 95.11] +/Subtype /Link +/A << /S /GoTo /D (subsection*.27) >> +>> endobj +377 0 obj << +/D [375 0 R /XYZ 109.858 727.97 null] +>> endobj +381 0 obj << +/D [375 0 R /XYZ 109.858 603.205 null] +>> endobj +374 0 obj << +/Font << /F28 380 0 R /F20 385 0 R /F8 369 0 R /F29 416 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +419 0 obj << +/Length 2526 +/Filter /FlateDecode +>> +stream +x]o+x)]!Nb,HE/-Öߗ E* Hc ?Wg?F5?Ds-3ްW u{Eڋ\}rA7?RѱW\4ի?ɲbWdQ%WxY==-/jWW oǥX7RWKO^s-qWoFd/xk٘˨A^eo+_^_ھ~:ZQ0퀐T2/l'ٔSi|y|k!|}DoJ:M +ҽ!Aj\D+}I8VM +}RZH(>BS|X^/`M˛N,Q3[{e4iIWHvA9:m+<܏7?}]}Qu 4˂Wn@ڪ?@)hHעsZZ}KÕmOj\3&J_KRbI}XMTCG #UǕ6 Pe#lstV;QBL߅{Yo<X*:H3i`T)At8CCrpgLq%;?OSwW5Gls +Dfh`t!׿\/Y|Lm;%":H!=0tj3"IP$]2N`ҒLls4Kf$M%I*ݗO~^=~ziɲA{ kqέި@X $ ͱ.;q vۻKg?Up N5՞ 2X9 6G3OIGQ__ mznaYJW4ȣ[w_{|w| E|e_>%IA9Pl:^`8VU kB;ᠹD\TRX: (f.f'PH +A(l&8?On"b-L 5Ȍq!7s2>{AM8DroeD#y/ qqXQ 7@_Yq¦s7el/C` <`e͍0-i=ؽ_}Zo/Ùڬ} ANt.dw*klX%?;67;uV_,X4Vm7Q{2Ai8LrQeo*#jbdƹaoںZ%x rurWjkZ9B$6G-w) MqSſnn*pjSpz 233xp&8隖q76GtiZD 'j/|)wYAfKnd':@e@ eأ 0g>?5;2]ʔq2;vhx'C4QB=D(7MǍ3enz W7sK +{FA8Qm*w9F <>:Jjõ,KS= 5K\4ʽ@iti8Gr+e (8%aOhBIc7,]='n/;}IT#]2A9z +xB7Jx}Vݯ=PL_{endstream +endobj +418 0 obj << +/Type /Page +/Contents 419 0 R +/Resources 417 0 R +/MediaBox [0 0 612 792] +/Parent 373 0 R +/Annots [ 421 0 R 422 0 R 423 0 R 424 0 R 425 0 R 426 0 R 427 0 R 428 0 R 429 0 R 430 0 R 431 0 R 432 0 R 433 0 R 434 0 R 435 0 R 436 0 R 437 0 R 438 0 R 439 0 R 440 0 R 441 0 R 442 0 R 443 0 R 444 0 R 445 0 R 446 0 R 447 0 R 448 0 R 449 0 R 450 0 R 451 0 R 452 0 R 453 0 R 454 0 R 455 0 R 456 0 R 457 0 R ] +>> endobj +421 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [146.72 690.167 292.092 701.016] +/Subtype /Link +/A << /S /GoTo /D (subsection*.28) >> +>> endobj +422 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [146.72 675.168 187.096 683.968] +/Subtype /Link +/A << /S /GoTo /D (subsection*.29) >> +>> endobj +423 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [146.72 656.294 175.058 667.032] +/Subtype /Link +/A << /S /GoTo /D (subsection*.35) >> +>> endobj +424 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [146.72 641.295 188.646 650.206] +/Subtype /Link +/A << /S /GoTo /D (subsection*.38) >> +>> endobj +425 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [123.806 622.421 228.718 633.27] +/Subtype /Link +/A << /S /GoTo /D (section*.40) >> +>> endobj +426 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [146.72 605.485 273.356 616.333] +/Subtype /Link +/A << /S /GoTo /D (subsection*.41) >> +>> endobj +427 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [146.72 590.486 234.613 599.397] +/Subtype /Link +/A << /S /GoTo /D (subsection*.42) >> +>> endobj +428 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [146.72 573.549 247.066 582.46] +/Subtype /Link +/A << /S /GoTo /D (subsection*.43) >> +>> endobj +429 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [146.72 554.676 271.668 565.524] +/Subtype /Link +/A << /S /GoTo /D (subsection*.44) >> +>> endobj +430 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [146.72 539.676 268.154 548.587] +/Subtype /Link +/A << /S /GoTo /D (subsection*.45) >> +>> endobj +431 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [146.72 522.74 280.884 531.651] +/Subtype /Link +/A << /S /GoTo /D (subsection*.46) >> +>> endobj +432 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [146.72 505.803 261.512 514.714] +/Subtype /Link +/A << /S /GoTo /D (subsection*.47) >> +>> endobj +433 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [146.72 488.867 257.084 497.778] +/Subtype /Link +/A << /S /GoTo /D (subsection*.48) >> +>> endobj +434 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [146.72 469.993 290.902 480.841] +/Subtype /Link +/A << /S /GoTo /D (subsection*.49) >> +>> endobj +435 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [146.72 454.994 293.752 463.905] +/Subtype /Link +/A << /S /GoTo /D (subsection*.50) >> +>> endobj +436 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [146.72 438.057 267.406 446.968] +/Subtype /Link +/A << /S /GoTo /D (subsection*.51) >> +>> endobj +437 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [146.72 421.121 227.971 430.032] +/Subtype /Link +/A << /S /GoTo /D (subsection*.52) >> +>> endobj +438 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [146.72 404.184 223.543 413.095] +/Subtype /Link +/A << /S /GoTo /D (subsection*.53) >> +>> endobj +439 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [146.72 387.248 250.11 396.159] +/Subtype /Link +/A << /S /GoTo /D (subsection*.54) >> +>> endobj +440 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [146.72 368.374 257.361 379.222] +/Subtype /Link +/A << /S /GoTo /D (subsection*.55) >> +>> endobj +441 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [146.72 351.438 257.582 362.286] +/Subtype /Link +/A << /S /GoTo /D (subsection*.56) >> +>> endobj +442 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [146.72 336.438 260.211 345.349] +/Subtype /Link +/A << /S /GoTo /D (subsection*.57) >> +>> endobj +443 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [146.72 317.565 253.293 328.413] +/Subtype /Link +/A << /S /GoTo /D (subsection*.58) >> +>> endobj +444 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [146.72 300.628 175.058 311.366] +/Subtype /Link +/A << /S /GoTo /D (subsection*.59) >> +>> endobj +445 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [123.806 283.692 227.75 294.429] +/Subtype /Link +/A << /S /GoTo /D (section*.61) >> +>> endobj +446 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [146.72 268.692 247.509 277.603] +/Subtype /Link +/A << /S /GoTo /D (subsection*.62) >> +>> endobj +447 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [146.72 251.756 271.696 260.667] +/Subtype /Link +/A << /S /GoTo /D (subsection*.63) >> +>> endobj +448 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [146.72 232.882 304.573 243.73] +/Subtype /Link +/A << /S /GoTo /D (subsection*.64) >> +>> endobj +449 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [146.72 215.946 295.828 226.794] +/Subtype /Link +/A << /S /GoTo /D (subsection*.65) >> +>> endobj +450 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [146.72 199.009 271.032 209.857] +/Subtype /Link +/A << /S /GoTo /D (subsection*.66) >> +>> endobj +451 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [146.72 184.01 242.915 192.921] +/Subtype /Link +/A << /S /GoTo /D (subsection*.67) >> +>> endobj +452 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [146.72 167.073 248.173 175.984] +/Subtype /Link +/A << /S /GoTo /D (subsection*.68) >> +>> endobj +453 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [146.72 150.137 244.216 159.048] +/Subtype /Link +/A << /S /GoTo /D (subsection*.69) >> +>> endobj +454 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [146.72 133.2 264.418 142.112] +/Subtype /Link +/A << /S /GoTo /D (subsection*.70) >> +>> endobj +455 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [146.72 114.327 262.287 125.175] +/Subtype /Link +/A << /S /GoTo /D (subsection*.71) >> +>> endobj +456 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [123.806 97.39 208.433 108.128] +/Subtype /Link +/A << /S /GoTo /D (section*.72) >> +>> endobj +457 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [146.72 82.391 254.095 91.302] +/Subtype /Link +/A << /S /GoTo /D (subsection*.73) >> +>> endobj +420 0 obj << +/D [418 0 R /XYZ 109.858 727.97 null] +>> endobj +417 0 obj << +/Font << /F8 369 0 R /F29 416 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +460 0 obj << +/Length 1597 +/Filter /FlateDecode +>> +stream +xYoF)QzvvzhVEXu $i}gI.ѠP.mPIuzAe-)?H,8CH"_'a\ + k I c35DDi;p3RqJ{ +P\0 cɒ z2=f?bRx.LdטFC%dvЩ1 0lwƩ5(=(H^ C_/^~'nPfcnk rQ π4F!QˎB8G($'Q,`CQHH + RǪu݈IX>{ eTA C//JC|xqpHqE\n$7lLmfԒc + 2 o{}Q6QT8pa( jY4"/>w5czM5Ya9'ABd Iz-}Dqh(6n \g u)Ǎp 4T*y.Sykv4Ʃh (&'"Ic#9FO+nv<a Sk u2Q3gHcL5k:sImiw^co!mNVxN@Ykx]&v5U̎F8^4n3\Js_kk>V]*xa DѱpbR*@ NtIԻ0NEBi%Xυ \?{Nl6mfY"l.s{{+R?]'3s]mKZ> Vu⡂s-m W3ܶ& XkĞ%pŋъ{bmDXfu’Cb 6ߺU̎E8Gh$fdRҫ~#9eTsQʌD;6 +Tlw(9Z\FYrEzZP!e}ZCo\yЍK|~xq*6Ck!p8~Yr\ѐ`^bLdRU~XTHխE0NPfK=AwnS;FB`ĎPi囖eZ~Ӓi$^a +Ɉ"IY)@1@6YҰ3EJD6Ii~\9-m'.9l FtrArs+Vx MJQ> endobj +462 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [146.72 690.167 247.149 701.016] +/Subtype /Link +/A << /S /GoTo /D (subsection*.74) >> +>> endobj +463 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [146.72 675.168 244.077 684.079] +/Subtype /Link +/A << /S /GoTo /D (subsection*.75) >> +>> endobj +464 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [123.806 656.294 208.046 667.032] +/Subtype /Link +/A << /S /GoTo /D (section*.76) >> +>> endobj +465 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [146.72 641.295 258.717 650.206] +/Subtype /Link +/A << /S /GoTo /D (subsection*.77) >> +>> endobj +466 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [146.72 624.359 280.275 633.27] +/Subtype /Link +/A << /S /GoTo /D (subsection*.78) >> +>> endobj +467 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [123.806 605.485 235.305 616.222] +/Subtype /Link +/A << /S /GoTo /D (section*.79) >> +>> endobj +468 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [146.72 590.486 280.967 599.397] +/Subtype /Link +/A << /S /GoTo /D (subsection*.80) >> +>> endobj +469 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [146.72 573.549 247.426 582.46] +/Subtype /Link +/A << /S /GoTo /D (subsection*.81) >> +>> endobj +470 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [146.72 556.613 255.7 565.524] +/Subtype /Link +/A << /S /GoTo /D (subsection*.82) >> +>> endobj +471 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [146.72 539.676 259.63 548.587] +/Subtype /Link +/A << /S /GoTo /D (subsection*.83) >> +>> endobj +472 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [123.806 520.803 225.093 531.651] +/Subtype /Link +/A << /S /GoTo /D (section*.84) >> +>> endobj +473 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [146.72 505.803 241.144 514.714] +/Subtype /Link +/A << /S /GoTo /D (subsection*.85) >> +>> endobj +474 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [123.806 486.93 221.523 497.778] +/Subtype /Link +/A << /S /GoTo /D (section*.86) >> +>> endobj +475 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [146.72 469.993 175.058 480.731] +/Subtype /Link +/A << /S /GoTo /D (subsection*.87) >> +>> endobj +476 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [123.806 453.057 225.259 463.905] +/Subtype /Link +/A << /S /GoTo /D (section*.89) >> +>> endobj +477 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [146.72 438.057 258.163 446.968] +/Subtype /Link +/A << /S /GoTo /D (subsection*.90) >> +>> endobj +478 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [146.72 421.121 241.144 430.032] +/Subtype /Link +/A << /S /GoTo /D (subsection*.91) >> +>> endobj +479 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [146.72 404.184 274.961 413.095] +/Subtype /Link +/A << /S /GoTo /D (subsection*.92) >> +>> endobj +480 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [146.72 387.248 287.525 396.159] +/Subtype /Link +/A << /S /GoTo /D (subsection*.93) >> +>> endobj +481 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [146.72 370.311 253.984 379.222] +/Subtype /Link +/A << /S /GoTo /D (subsection*.94) >> +>> endobj +482 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [108.862 341.475 167.871 352.323] +/Subtype /Link +/A << /S /GoTo /D (appendix.A) >> +>> endobj +483 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [108.862 316.513 139.227 325.424] +/Subtype /Link +/A << /S /GoTo /D (appendix.A) >> +>> endobj +461 0 obj << +/D [459 0 R /XYZ 109.858 727.97 null] +>> endobj +458 0 obj << +/Font << /F8 369 0 R /F20 385 0 R /F29 416 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +486 0 obj << +/Length 1293 +/Filter /FlateDecode +>> +stream +x͘]o6+t)I${f +Pl%"KMwI}Xv3 A|͗9njY@jH.z=`^Ì):4iE"Ui 7},4< 4)oyZ\*จ VwAEͧw77/kP D)lPAp"؊oVq"$ H)Qb0Ш4Jh#J%Xz*83%ӄĕua{`%x&!!m)U18#Nd*y-LYt]Ri\kl4vmj7OǣmQ` +E"ƚ=BG?Xi%u1 w0&phIOF@8:%T.#ۗݬuϗnИ=t"`X6 +,^ +/-YLhh^4Vw7+&i +ahJN-077Gz> endobj +489 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[0 1 1] +/Rect [253.708 392.552 415.518 404.507] +/Subtype/Link/A<> +>> endobj +487 0 obj << +/D [485 0 R /XYZ 109.858 703.064 null] +>> endobj +6 0 obj << +/D [485 0 R /XYZ 109.858 703.064 null] +>> endobj +488 0 obj << +/D [485 0 R /XYZ 109.858 454.279 null] +>> endobj +10 0 obj << +/D [485 0 R /XYZ 109.858 454.279 null] +>> endobj +490 0 obj << +/D [485 0 R /XYZ 109.858 186.824 null] +>> endobj +484 0 obj << +/Font << /F28 380 0 R /F22 363 0 R /F8 369 0 R /F14 372 0 R /F29 416 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +493 0 obj << +/Length 3069 +/Filter /FlateDecode +>> +stream +xk + +hrr?v&/@8@y#L2Ibw^\irvfv33 u҅djb<%"/bd\[6 O\GY4EHTS@ѓy[_.u=[90HuCvsdWuﬦZ挳D"QQqWA$EPGtYۻEKʣuiJCwY7I(0yiG &)#i"( {lc9GAB(C{*+UKeW 'w +Ʌ`2Zsn>)6tyy@W?)h͒c,xu!a4,R&`4d}ܒD9BUX%F]{[y;5['L̜7Jg#SOdpZY\tYEK>ѻ'*3 +|)!6C% e%[їҢ{&SH}W]{[.XG5리'ldmu2EQ~]L`8q#4GS7[j$ҶyVz^IHsib(`"`Wv M&NG%01\87UZVu5^䜢@'1֒hP!'b Qq68eU-Rh-ꖩV )*,B@Ǐj <:tch v^U8^܃DeWPS]t-vmjF*ԪWhl0p u||{)' DY,?b@w3n4LՄ90M9u@}Nuœu(f(]xA`f<\\ia'1Swom4$QLWG(Se/`(0M#s<*'] `=x<}8В.^0&gKn(Oa<~Ci + 1aQ;:vEF9OI]MxYܤXvrcb6$%≻3ZNQW&\-6bJޏ8~;?,h:!־.iz89DJXS0jɳ*8̋hCŋ x5-IDlL3?_)B%@&5#{0я_G[ c#Vr݆Cr{t1X/~GɕwtS^M=䎶یE\EV[Rϋ?|s5h̄s0HZLe)5}c+2ihlR}ڄ&xkF) džc'e~w_[,'Px*3/KY8)2L|ni}խ픑G<aX:u~$o]eOg$c-B%?5JՍUwϧHg[ܺq*^>U{j%3,cwM*iJg|=W1*~p5"E2uvzo12q'LF6w?"y5oZI`K7-tHd!޷8Y1w8 \rxY6sM̦)T_ɕw<ޜc?+I/q5 |QXLT Y 0<ǃl,o LCI'AoO<.gř @>>$ОlaPsD)*!%1Ĺ:eC)8>6C}.@/gfwUl"ƿfz<֠ÅPCi vblڭ?endstream +endobj +492 0 obj << +/Type /Page +/Contents 493 0 R +/Resources 491 0 R +/MediaBox [0 0 612 792] +/Parent 373 0 R +/Annots [ 494 0 R 495 0 R 497 0 R 498 0 R 499 0 R ] +>> endobj +494 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[0 1 1] +/Rect [108.862 337.587 167.614 348.435] +/Subtype/Link/A<> +>> endobj +495 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[0 1 1] +/Rect [108.862 320.097 173.702 332.052] +/Subtype/Link/A<> +>> endobj +497 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [126.163 241.375 159.898 252.224] +/Subtype /Link +/A << /S /GoTo /D (license) >> +>> endobj +498 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[0 1 1] +/Rect [121.038 216.912 253.971 228.867] +/Subtype/Link/A<> +>> endobj +499 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[0 1 1] +/Rect [381.769 159.128 514.701 171.083] +/Subtype/Link/A<> +>> endobj +14 0 obj << +/D [492 0 R /XYZ 109.858 703.064 null] +>> endobj +496 0 obj << +/D [492 0 R /XYZ 109.858 321.093 null] +>> endobj +18 0 obj << +/D [492 0 R /XYZ 109.858 306.08 null] +>> endobj +500 0 obj << +/D [492 0 R /XYZ 109.858 119.831 null] +>> endobj +491 0 obj << +/Font << /F29 416 0 R /F28 380 0 R /F8 369 0 R /F14 372 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +503 0 obj << +/Length 933 +/Filter /FlateDecode +>> +stream +xڥV]6}0H}SfӦ}jS2ج8W0NgNjs= ?2@ ͬUlqʙ10D~~`X1 65 ,c`L4xXcYc}OA;okq>揫_1!qw{r2+tӿPQ, 4+֮í}aV)  +FslYȲ[6plˆ2i b2q(BjIK(S].z㊕If,L}GZ(řV!y>4 #6{\(iPlH: ׅ+7V9MBf,V4&)[C`|1ˍe)fczy ÿ5hҠ`H4zgybx,;i`# 2'q"̳^v\mfRf5-B?σG]YWDzATmI5n}1P.vdzV;mt 9|ljk 8p0ksF(fSHѭ'v4_Vn^DN}Ke"\CdkQvqe6мǃͭgyǞv +Lo##1WOܾ=k3 O)ʨ_+~jqNS`CSA,/ϑ _^^Ӊȱ~K/b +}ջ92GB핝$|V_Yendstream +endobj +502 0 obj << +/Type /Page +/Contents 503 0 R +/Resources 501 0 R +/MediaBox [0 0 612 792] +/Parent 509 0 R +/Annots [ 504 0 R 505 0 R 506 0 R 507 0 R ] +>> endobj +504 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[0 1 1] +/Rect [244.023 658.273 308.863 670.228] +/Subtype/Link/A<> +>> endobj +505 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[0 1 1] +/Rect [212.073 629.935 358.441 640.783] +/Subtype/Link/A<> +>> endobj +506 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[0 1 1] +/Rect [212.031 601.043 270.783 611.892] +/Subtype/Link/A<> +>> endobj +507 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[0 1 1] +/Rect [331.14 583.553 448.118 595.509] +/Subtype/Link/A<> +>> endobj +22 0 obj << +/D [502 0 R /XYZ 109.858 703.064 null] +>> endobj +508 0 obj << +/D [502 0 R /XYZ 109.858 584.55 null] +>> endobj +501 0 obj << +/Font << /F29 416 0 R /F28 380 0 R /F8 369 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +512 0 obj << +/Length 2429 +/Filter /FlateDecode +>> +stream +xYo_>Pq]@}圦IhӢB.E"-8gfME'.0,3YoϸP#a+9g bRfD 5@?X""Nd.bƚ"POчOaw@-:cƤH6]Z0 $;ki1LؓI3+N#9v'Let~%Ywg.NPLX_xt`X#,p擘4]DT8ϗ&_6*^*+ap!׽*Xa6r F7z)T\GCGC89v,Ҡ*F7˘G@F&ʷ>_گw -cOlp3wmۥ<..aSקZ)sYZˠ@u Dy#$il:hIU ,*hiINEg[Ê-cdFUHӃu=qoZr(p,vm yUE[T= +ޡJ⫇ /ڭ}ACB#o&x+(A&{uP"je'SΧo(a!k9F-,(q6@yifAiҡқ"B,6{^BnCepYg]P?!E PaWP~|F {Oc}y 5r߃TuIk09k&Ih֜Z3҂z0ވn +e/+Hq.2!>ȓ`* <MIxr9i3=iząs@kOy$0k&$F`NZ@OFɈ8l>+j\ ڲ̆v;f`kLv?f83Rf$ rs-u.či x#[v#*c0xwc6>]5bi˄:F15t +xXvc}RG,$sjCq +1f>zDSHPYi!XKk +*MrAuLPX!/2 ܘ宷k*TW0'~"TU:Nϻ~MTe:>yԊcA.,ko qs5 ol{m7Qij=}5Q8;tkl8Ͼ&}ٓ7u:_|'[8ȍ/)KR173)09 4yp8_`}NFKwM-)f6=;3:[Uki\LTY#r) 7&W_}U'rN' tA nFғ!4z?Uva~y(} p'WŠst ]!S}q H 1pA&`X1%Wm<;zz'̱hU?/=OlTk Tr^vy*>rJ a ZJ]MtrfU%COģɔ7ͳUΤL KF*Y FYͪdS馯TۼEe~YM|I{x`y[{M׊i(og56T_QMf2ȯDYP)S f3hl_%u~9aºɒMmZ~Y4N ,M 4OBԯcQdUbendstream +endobj +511 0 obj << +/Type /Page +/Contents 512 0 R +/Resources 510 0 R +/MediaBox [0 0 612 792] +/Parent 509 0 R +/Annots [ 526 0 R ] +>> endobj +526 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[0 1 1] +/Rect [165.065 115.766 282.044 127.721] +/Subtype/Link/A<> +>> endobj +26 0 obj << +/D [511 0 R /XYZ 109.858 703.064 null] +>> endobj +513 0 obj << +/D [511 0 R /XYZ 109.858 455.179 null] +>> endobj +30 0 obj << +/D [511 0 R /XYZ 109.858 455.179 null] +>> endobj +517 0 obj << +/D [511 0 R /XYZ 109.858 294.733 null] +>> endobj +521 0 obj << +/D [511 0 R /XYZ 109.858 275.853 null] +>> endobj +522 0 obj << +/D [511 0 R /XYZ 109.858 256.973 null] +>> endobj +523 0 obj << +/D [511 0 R /XYZ 109.858 238.093 null] +>> endobj +524 0 obj << +/D [511 0 R /XYZ 109.858 207.257 null] +>> endobj +525 0 obj << +/D [511 0 R /XYZ 109.858 134.67 null] +>> endobj +510 0 obj << +/Font << /F28 380 0 R /F22 363 0 R /F8 369 0 R /F19 516 0 R /F20 385 0 R /F11 520 0 R /F14 372 0 R /F29 416 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +531 0 obj << +/Length 3150 +/Filter /FlateDecode +>> +stream +xZYF~_B%>x,`#'Y/H 1PSW7ɡq,>UU_W5BEy"i"Zla %+,&΅)@"͟zhaHůE pyx(6_/l:ͤx}s³((>BU߯ŗW7 ͯb[.+)O,II(Έʳ0P[J,]UWp㇥A^8iI\ (NJ& u”pʒFwJrHe41:Lp$+tTМڦXګ++mR;(Ƌz&3nC| ȵYhLyxuڂセǂrZTzHX9^+ WmfXqhQY*IBґVgd뢛7N Eycs8$qήǐ觬l,3a P2Fu#Ñ]3USixnf̀&5n[1a=NN'p4S$3gDy0=I6irv9V0Y2DT܆:?NNy + hJ} t&Qq$޽[AYPÉے$B>mŰ1xɂk:i˛ub`JblE)W;a|Rt)\BX,Ԭ J%Aqfe;2y#8~F¦ʼng>VB @3=󮹃=0׾Q]#ق^4 &hhCtF]sCAA6OCO4 B:y|8'i!ҾB[Vy\-3#op{VGQQN7x$cF8PZK" +Ax5fu=e]pQ5ykYcwT6 ?tD@wJRd'Uu#& ȱfe~&@vz;R=ԙgqG[ґP3g9<'Mr(E?TXIQRJv1p>H( M&6GĢzg)z Ɋ)$;&-fC8t^-%/"ed<7Tޢ)^gQpy#vg)Ĭ5Ž ' ze:vx BxGdD;;-E5ixC Xwg0OEKO4-BO4-ghHs nU + T|AGn1 ~>m8 1Tt̗RzX}$z4G(hJA3dhWH%ꘂ6a'\+hpϞh=yNw3Ҝ{`ܑbg9 0Oҁ9Uijx᱑3ɢGx%U$xnZ,12[N/dz;sz8Ob8GΡ5Aj!k_f</xq$l6^JsrNPOgݖB/+8R9O-ڶAO!δq3߷2k.-;I><~YJը:QE(^>G#KnE + R")<\p胪bΊֈ%*DZBG8ӓ$=y7lzp뎎"aLRX7Ċ#nآ͖fnLv6ģiG>QrSO%j3_9Lvww*2o0L>v5$ է\s<MjzH|ox#E%vԤӋ +zP.+gЙ +n$<_ǎ|;_ҹJXm.p@J܈> endobj +527 0 obj << +/Type /XObject +/Subtype /Form +/FormType 1 +/PTEX.FileName (ss_compbar.pdf) +/PTEX.PageNumber 1 +/PTEX.InfoDict 541 0 R +/Matrix [1.00000000 0.00000000 0.00000000 1.00000000 0.00000000 0.00000000] +/BBox [0.00000000 0.00000000 397.00000000 72.00000000] +/Resources << +/ProcSet [ /PDF /ImageC /ImageI ] +/XObject << +/Im1 542 0 R +>>/ExtGState << +/GS1 543 0 R +>>/ColorSpace << +/Cs6 544 0 R +/Cs9 545 0 R +>>>> +/Length 92 +/Filter /FlateDecode +>> +stream +H*2TT230V0372Q04ճ43Q53R݃ ҋ + +,- ȄO5Tp +B= +endstream +endobj +541 0 obj +<< +/CreationDate (D:20030406193450-04'00') +/ModDate (D:20030406193450-04'00') +/Producer (Acrobat Distiller 5.0.5 \(Windows\)) +/Creator (Corel PHOTO-PAINT 10) +/Title (ss_compbar.ep$) +>> +endobj +542 0 obj +<< +/Type /XObject +/Subtype /Image +/Width 726 +/Height 52 +/BitsPerComponent 8 +/ColorSpace 545 0 R +/Length 2044 +/Filter /FlateDecode +>> +stream +H엋* Gݗ.! MǓLbi?aU7Rz?E@JYjc]T~.Vr9Ы]#ذv>wB}Gہ^m:Zk#3[LOD3\.ma|[ᶚ7<}%Ͷ℻z0Mj^ݧe&GYD'4ORs]8ոhY!3f\-F!߶;"I^R[9շY6ƚvpϥWǙR->VnP<?a>()TJ5N4vYa1£~uFSf8W* zڎяD>)#$Fѥ)Ju.6^՜j>=K +<ӗiwyu,u0xXsj%Dȫ㏽/55{Ҽsy/U"^x Hw6^>Wps&.SJm +B^@uu?v5Z4|z:gؾuX4j)׈qBKZw!`ոFOܨ%LlC'"\9 nQꇳB^懰iNs0:IT[L=I= DODATAV 6!^kr +^z5v'ƃ+X ;Gnc]FW q7jN@w.~e{agLosT?? 05a6eOżBK].ğωTVP@nIu6^,MA>{5q]-a"3^MS/TVX~S:xHŕ*ebg]>ˡCP X`nS(ՎS]MZ]4NjMZ;݌ºL^vm[Szz%٪%js܈CN&Phj,B5״WZQlUEu չMaØWڑ +ķS"LZDvBCN@8mq,S< ljeqv!۩W2~w^Րjnx磱GZjjYetUEϰd^0ީcK[oԘ%u"F*_#‹LZLb!*SqF(6j~3uw$:c cgR z0^-Lb.{I~d&zmifXp>;f~Q'4ڼRutWT'IZ:P@u_J)RRjIV̇kt\J=2Rz?)ժRz?)ժS|-}wtTU:Z}{2UU(ժiRBR:f.lCjՙ5[ R:(`jO9J*Ħjcը iJT5N)ժHV>wRE}|q=T[Ah +endstream +endobj +543 0 obj +<< +/Type /ExtGState +/SA false +/SM 0.02 +/OP false +/op false +/OPM 1 +/BG2 /Default +/UCR2 /Default +/TR2 /Default +>> +endobj +544 0 obj +[/ICCBased 546 0 R] +endobj +545 0 obj +[/Indexed 544 0 R 16 547 0 R] +endobj +546 0 obj +<< +/N 3 +/Alternate /DeviceRGB +/Length 2575 +/Filter /FlateDecode +>> +stream +HyTSwoɞc [5laQIBHADED2mtFOE.c}08׎8GNg9w߽'0 ֠Jb  + 2y.-;!KZ ^i"L0- @8(r;q7Ly&Qq4j|9 +V)gB0iW8#8wթ8_٥ʨQQj@&A)/g>'Kt;\ ӥ$պFZUn(4T%)뫔0C&Zi8bxEB;Pӓ̹A om?W= +x-[0}y)7ta>jT7@tܛ`q2ʀ&6ZLĄ?_yxg)˔zçLU*uSkSeO4?׸c. R ߁-25 S>ӣVd`rn~Y&+`;A4 A9=-tl`;~p Gp| [`L`< "A YA+Cb(R,*T2B- +ꇆnQt}MA0alSx k&^>0|>_',G!"F$H:R!zFQd?r 9\A&G rQ hE]a4zBgE#H *B=0HIpp0MxJ$D1D, VĭKĻYdE"EI2EBGt4MzNr!YK ?%_&#(0J:EAiQ(()ӔWT6U@P+!~mD eԴ!hӦh/']B/ҏӿ?a0nhF!X8܌kc&5S6lIa2cKMA!E#ƒdV(kel }}Cq9 +N')].uJr + wG xR^[oƜchg`>b$*~ :Eb~,m,-ݖ,Y¬*6X[ݱF=3뭷Y~dó ti zf6~`{v.Ng#{}}jc1X6fm;'_9 r:8q:˜O:ϸ8uJqnv=MmR 4 +n3ܣkGݯz=[==<=GTB(/S,]6*-W:#7*e^YDY}UjAyT`#D="b{ų+ʯ:!kJ4Gmt}uC%K7YVfFY .=b?SƕƩȺy چ k5%4m7lqlioZlG+Zz͹mzy]?uuw|"űNwW&e֥ﺱ*|j5kyݭǯg^ykEklD_p߶7Dmo꿻1ml{Mś nLl<9O[$h՛BdҞ@iءG&vVǥ8nRĩ7u\ЭD-u`ֲK³8%yhYѹJº;.! +zpg_XQKFAǿ=ȼ:ɹ8ʷ6˶5̵5͵6ζ7ϸ9к<Ѿ?DINU\dlvۀ܊ݖޢ)߯6DScs 2F[p(@Xr4Pm8Ww)Km +endstream +endobj +547 0 obj +<< +/Length 52 +>> +stream +@@@ +endstream +endobj +532 0 obj << +/D [530 0 R /XYZ 109.858 727.97 null] +>> endobj +533 0 obj << +/D [530 0 R /XYZ 109.858 703.064 null] +>> endobj +534 0 obj << +/D [530 0 R /XYZ 109.858 674.67 null] +>> endobj +535 0 obj << +/D [530 0 R /XYZ 109.858 631.388 null] +>> endobj +536 0 obj << +/D [530 0 R /XYZ 109.858 599.507 null] +>> endobj +537 0 obj << +/D [530 0 R /XYZ 109.858 567.627 null] +>> endobj +538 0 obj << +/D [530 0 R /XYZ 109.858 537.684 null] +>> endobj +539 0 obj << +/D [530 0 R /XYZ 109.858 503.866 null] +>> endobj +540 0 obj << +/D [530 0 R /XYZ 109.858 364.334 null] +>> endobj +34 0 obj << +/D [530 0 R /XYZ 109.858 349.321 null] +>> endobj +529 0 obj << +/Font << /F29 416 0 R /F8 369 0 R /F20 385 0 R /F14 372 0 R /F11 520 0 R /F28 380 0 R >> +/XObject << /Im1 527 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +550 0 obj << +/Length 2709 +/Filter /FlateDecode +>> +stream +xڥZmoH_1} Myu^]NBf ּGvNtWW[W=]`ÿ`g"JTjsW;yw1s^B J*/5)Ruj ~U:5{x=BG#?{.mK}n3bGKn&tjQ )<)w]SYEij^ +nAՋ.?"WhGchϣ9ohzw:ڍteM]wC$hۑ]!aC#kD&v<'|#&ȊD+^(W{m(4݀3ߐցlCX@Spa?@*K~5nѭ[(>E.rVg2'o\41ҔK>Ks[sRu48Z{@ a!0}n\W;ٵ o፲5?,M" ־]Gxi@aUQ.| z6WsH"W>Ehe(;2/xv 8RL$xѮQa$22ᶰ#C%͵]6 4 jZ LaVȘ1k^>&v6]dp/[v88M{ʎWE~ks(,dǭ<8`9l!@/Ce/(1u1dRH㝜@{~BkmfZŀB'"2N smJwt^xQo{M^]_ B +~N[@D9'ɜJ7CQ2 +0.RkpBU°mfzR=v+i7$w-WvΖ$j0ؐ$0$;FsF#HÙ^Ǭ޾%1nSvWnhm36BX3cy/aN=ِg}ɯl={Ȧ!<O` suv]S9ѿ6d]gDrI]bWqV슃* X Im{v}UTr}QmˑF\?(=!noeyejHOhu%^L`C-ʹz-SÆ!ܛf nsȾC5Q81$(wR +Y] !E}_E)q!ܦnhdRm&K6`}Qw]D )cQ++cPl(m^bHy/CƊE>)6Q4^>qBzwYD 3Omk./A:-=`Kאc +n^#LOx@t0ʙХ Հn]5М~^~!=D7W:@p4RV=5[t,FwԞ. /8b#lF-ok&2#I3@4R4#O9 Y鎖.37'w˅|~<t*9'ҜĦElP2f~ٟ1ٖ0*.- ΊYeţ:~ʕ6{}cL ?u% :1o 6~ӛPZU$,ƂZ\wAqcpF<'2?zNh]CՓ54MC⟣IǿRF2@!U +E9 -]08ȷ(BsN;XFGEN~d_Џ(=Q-Fm߱z +9]q>֋$ 0k tш'NPBL[`?9+ INaassR͢v Z@Hn> endobj +528 0 obj << +/Type /XObject +/Subtype /Form +/FormType 1 +/PTEX.FileName (ss_dsgn.pdf) +/PTEX.PageNumber 1 +/PTEX.InfoDict 566 0 R +/Matrix [1.00000000 0.00000000 0.00000000 1.00000000 0.00000000 0.00000000] +/BBox [0.00000000 0.00000000 228.00000000 129.00000000] +/Resources << +/ProcSet [ /PDF /ImageC ] +/XObject << +/Im1 567 0 R +>>/ExtGState << +/GS1 568 0 R +>>/ColorSpace << +/Cs6 569 0 R +>>>> +/Length 85 +/Filter /FlateDecode +>> +stream +H*2TT2P04гP022׳4PMR݃ ҋ + + Hn@r.gK>W   +endstream +endobj +566 0 obj +<< +/CreationDate (D:20030406193455-04'00') +/ModDate (D:20030406193455-04'00') +/Producer (Acrobat Distiller 5.0.5 \(Windows\)) +/Creator (Corel PHOTO-PAINT 10) +/Title (ss_dsgn.ep$) +>> +endobj +567 0 obj +<< +/Type /XObject +/Subtype /Image +/Width 380 +/Height 215 +/BitsPerComponent 8 +/ColorSpace 569 0 R +/Length 5155 +/Filter /FlateDecode +>> +stream +HWF@Lr"`m : cXg#?vtۣЪ4R术tWw^B\J9AM8X:K`JS\Y܄.pkAs+`a-8G-8LsԂs$8G-8LsԂs$8G-8LsԂs$8G-8LsԂs$8G-8LsԂs$8G-8LsԂs$8G-8LsԂs$8G-8LsԂs$8G-8LsԂs$8G-8LsԂs$8G-8LsԂs$8G-8LsԂs$8G-8LsԂs$8G-8LsԂs$8G-8LsԂs$8G-8LsԂs$8G-8LsԂs$8G-8LsԂs$8G-8LsԂs$8G-8LsԂs$8G-8LsԂs$8G-8LsԂs$8G-8LsԂs$8G-8LsԂs$8G-8LsԂs$8G-8LsԂs$8G-8LsԂs$8G-8LsԂs$8G-8LsԂs$8G-8LsԂs$8G-8LsԂs$8G-8LsԂs$8G-8LsԂs$8G-8LsԂs$8G-8LsԂs$8G-8LsԂs$8G-8LsԂs$8G-8LsԂs$8G-8LsԂs$8G-8LsԂs$8G-8LsԂs$8G-8LsԂs$8G-8LsԂs$8G-8LsԂs$8G-8LsԂs$8G-8LsԂs$8G-8LsԂs$8G-8LsԂs$8G-8LsԂs$8G-8LsԂs$8G-8LsԂs$8G-8Ls2s,W%8G-9`B;8G-99j{h>LsB }稅>A0 Q }؃>G39`}fs$8G-9`IpZs9W 8G-9`&9j9`s_,]:g(C09iuΘ"gY6R=VU,Kq΄% S-z%"9RdIm9'\p+%OqNu3B>p9:DjZՃ1Ή7,zӺ4ȿb>9'baomtI9Ήu΀9a]sjxssNlյ8'9\8G9h"~^b#H {k9U8gB檅WZWdsX;\T {ksZ۵s% +NA3RC 9A#$rp|sf9*;ZarqNC]] pN:IcVJbsu)S,z%P[sT%P[sT%P[X9k9 5  !b9A#ɲ"Ǝ$$!$7hI$I$" $>(yEĹ ϻAW9.?QP&Iҙ|#Q8oוd|gt9η*],osB%x9l'Iҙ|̘Np5Q;1KW|d<ٓL٦J29~oKy4 lmcF4r'o!+ .s_rj_t7Ò x9|F".?>7Ēb;Me,ďgY,xH}M[^{ſINՀۑ8'||]DFRk"qNAsQ&/xGjUHmq|MՓG&4d:~3>\Es +Ogm\)?=;>\5hTIҕ-\^ E3O3SYOgHēĝs|e=Αh' JF,9徭!zsB_-%OO98W\>Osq[iΉ#)w]%Wӎ9nJ[]v>>Užs89᭡9fњUYG#a0WIz,%Ms$C$\u*dYbW#Sgt8Ǐ5#?]']~Zk߭P7]#I"D^ȝ3YR*nIөmM%J}m olt\HL0Ux$iqŭT7q.i> t]% ~% CďgYSӛdd:{i)4iC]3ÜӔϲIͱ>'Y]FēOW\Bu>81&GtVIm[_֧;(k5&US֭>GdΉ#t$#)"M$)v$dOxE9]sIڜC؎퍲}K/>Ebdj${Pi[I2Ir8cc#L!b9A8 9Yj*iۊYj*iۊYj*iۊY"-Uy۪Yx7[µ ׍0Cm"1]|5mE뜍gY3:c75%Vll%qN|êT?@CmuNq(ꜳ`i*hof$Mkf#qNCM5JDŽ"J9Ӽ+;T#_)=9ni}>'9a$3{ZxaSWLwdžߟIy7mLzDj?')li&?_ii2qβm1\jyBR}9C;VO I\;vGcX9j MZ;x"C_<8}N9&ZB8ޜ]-I;sDтIa~yt?4w~|^~2sjEª X*\}F<>uNoZ3]f=}TMmlvͫ3B ?/K(w +E%#H&9uϴO6bC;K9g)yJ-?tC7<5:TIrҡNH  (YvʚO}N> \e k]~y`1U +k5X8Btΰnd0]ڟsg|S^.|y1+失>mB!qN#/^$;uao;~{s= +2ƝCLXjsZ~+ syl+ +3g)򪫤yl+ +3g)򪫤yl+ +3g)򪫤yl+ +3g)򪫤yl+ +CĜtWCEk'Oo<\ĵv۩kzӯq;μv<]g߸<__u~"7ݗ"+E?.?I{~co=}Os<?{?/?EnCON<ɧ?<UzEoq37<{}s}|?>§~/~z.٥>_+_\y+Sgp~όc:$q0!Ɗ +Ap)"Jޖj/4],MQ4$? {wy;0s6K !Y3< 3BTT*;OzW,{\{|f/Xw-p+p+tTQ/r/vZY +RjHk esByyo(_Ǎʅ*MU.UծAՋj׸u ٻ8dBo\9l+ψ^ G#!G} ǖobGZ:ߘ:zʝ Jiո2r|UxHӚ kw7K\rjCdHK@JK@j˦3 L?ep!s!CU-0u{XN{8$<ň|ȥmˑW\QruGkebʮǰwCn07vUUy3Vlխqշk ?%{_tNҡ;ɇ&r^ʑ{G:SvL?v?~F탌u3f?jx iMuQ#ҕw+TW~RϢ3gsOKg%J[{^vElrH_ W^Su 򫚎<B2!s0T$s2|Qx{18`Nh2̑_ FᄀᫎBþXYZ2ws2!sNuqo1Ȝ7^@GrOJh\\=G9x.#y]0?`̑Q0GrB93B6OQ~G@sƂQH<\uK=%` s#\#3{N/;*\9dٚU7#'ƙósX-bv9pnE9VF#AFB@vX `GqP3ʩ `ݭȜmS n(,{Ej0fb0cߕ9v^j=!s9Z/Y1G|XFlq3*Pŗ#7GϦE9mIM} I$0gkp[al='Ws2g{NoՁWFxGsFXIz!Xo'}4 O&oŞ6s̈338sprǎNs]=g)isk5{̥*{9cVGsH9Ba} Q GJ9s2JJ9_'sȜ9sF|VsF}:jB[9cgŌz糙/ qhܭМ ⻕Dys2G> +endobj +569 0 obj +[/ICCBased 570 0 R] +endobj +570 0 obj +<< +/N 3 +/Alternate /DeviceRGB +/Length 2575 +/Filter /FlateDecode +>> +stream +HyTSwoɞc [5laQIBHADED2mtFOE.c}08׎8GNg9w߽'0 ֠Jb  + 2y.-;!KZ ^i"L0- @8(r;q7Ly&Qq4j|9 +V)gB0iW8#8wթ8_٥ʨQQj@&A)/g>'Kt;\ ӥ$պFZUn(4T%)뫔0C&Zi8bxEB;Pӓ̹A om?W= +x-[0}y)7ta>jT7@tܛ`q2ʀ&6ZLĄ?_yxg)˔zçLU*uSkSeO4?׸c. R ߁-25 S>ӣVd`rn~Y&+`;A4 A9=-tl`;~p Gp| [`L`< "A YA+Cb(R,*T2B- +ꇆnQt}MA0alSx k&^>0|>_',G!"F$H:R!zFQd?r 9\A&G rQ hE]a4zBgE#H *B=0HIpp0MxJ$D1D, VĭKĻYdE"EI2EBGt4MzNr!YK ?%_&#(0J:EAiQ(()ӔWT6U@P+!~mD eԴ!hӦh/']B/ҏӿ?a0nhF!X8܌kc&5S6lIa2cKMA!E#ƒdV(kel }}Cq9 +N')].uJr + wG xR^[oƜchg`>b$*~ :Eb~,m,-ݖ,Y¬*6X[ݱF=3뭷Y~dó ti zf6~`{v.Ng#{}}jc1X6fm;'_9 r:8q:˜O:ϸ8uJqnv=MmR 4 +n3ܣkGݯz=[==<=GTB(/S,]6*-W:#7*e^YDY}UjAyT`#D="b{ų+ʯ:!kJ4Gmt}uC%K7YVfFY .=b?SƕƩȺy چ k5%4m7lqlioZlG+Zz͹mzy]?uuw|"űNwW&e֥ﺱ*|j5kyݭǯg^ykEklD_p߶7Dmo꿻1ml{Mś nLl<9O[$h՛BdҞ@iءG&vVǥ8nRĩ7u\ЭD-u`ֲK³8%yhYѹJº;.! +zpg_XQKFAǿ=ȼ:ɹ8ʷ6˶5̵5͵6ζ7ϸ9к<Ѿ?DINU\dlvۀ܊ݖޢ)߯6DScs 2F[p(@Xr4Pm8Ww)Km +endstream +endobj +552 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [259.442 448.59 328.029 459.438] +/Subtype /Link +/A << /S /GoTo /D (defaulttheme) >> +>> endobj +553 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [469.952 448.59 538.252 459.438] +/Subtype /Link +/A << /S /GoTo /D (ttbxswitcher) >> +>> endobj +554 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [423.479 436.635 455.359 447.483] +/Subtype /Link +/A << /S /GoTo /D (ttbxswitcher.theme) >> +>> endobj +558 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [352.418 184.508 386.65 195.356] +/Subtype /Link +/A << /S /GoTo /D (defaulttheme) >> +>> endobj +559 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [390.04 184.508 431.192 195.356] +/Subtype /Link +/A << /S /GoTo /D (officexptheme) >> +>> endobj +560 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [452.894 184.508 485.135 195.356] +/Subtype /Link +/A << /S /GoTo /D (stripestheme) >> +>> endobj +561 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[0 1 1] +/Rect [283.955 171.999 405.002 183.955] +/Subtype/Link/A<> +>> endobj +562 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [269.466 126.725 337.766 137.573] +/Subtype /Link +/A << /S /GoTo /D (ttbxswitcher) >> +>> endobj +563 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [108.862 116.707 196.284 125.618] +/Subtype /Link +/A << /S /GoTo /D (tbxcurrenttheme) >> +>> endobj +564 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [216.984 116.707 284.426 125.618] +/Subtype /Link +/A << /S /GoTo /D (tbxsettheme) >> +>> endobj +551 0 obj << +/D [549 0 R /XYZ 109.858 727.97 null] +>> endobj +557 0 obj << +/D [549 0 R /XYZ 109.858 252.824 null] +>> endobj +38 0 obj << +/D [549 0 R /XYZ 109.858 237.811 null] +>> endobj +565 0 obj << +/D [549 0 R /XYZ 109.858 117.703 null] +>> endobj +548 0 obj << +/Font << /F29 416 0 R /F8 369 0 R /F20 385 0 R /F22 363 0 R /F41 556 0 R /F19 516 0 R /F28 380 0 R >> +/XObject << /Im2 528 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +581 0 obj << +/Length 710 +/Filter /FlateDecode +>> +stream +xڍUn0 }WQfUےXtZ`إV탚Kc [m)iK!yC)I)rj+eM&=Xd*! +sDHZ|EJVhGcv}+]W{lں_gُ]Y ЄJŲ|w6gY7K ̯!/""ZSBI坨]F:/v9Jb0}u5:3 !X cQ{)*b2<=z1 zTRh-* ^A*E$!B^(}? #LA|^x0V!mSnrw`w[]-#hdn#vTJ mŢHUπ1%RJqt TE` +I=':&Sb/XTtO]>녴6Ib]J-'I0b"!ScѲsϰ뒇<ҾSv+ɂ"1H4#6f݆F'wJL).*Ϸ$Z4XD$m?p]SF9i]iJ> \ncar{(w=Yڅg=6||o4BKU`M2](3נQ0<-b%2 C/2~z/RTendstream +endobj +580 0 obj << +/Type /Page +/Contents 581 0 R +/Resources 579 0 R +/MediaBox [0 0 612 792] +/Parent 509 0 R +>> endobj +577 0 obj << +/Type /XObject +/Subtype /Form +/FormType 1 +/PTEX.FileName (ss_default1.pdf) +/PTEX.PageNumber 1 +/PTEX.InfoDict 583 0 R +/Matrix [1.00000000 0.00000000 0.00000000 1.00000000 0.00000000 0.00000000] +/BBox [0.00000000 0.00000000 318.00000000 254.00000000] +/Resources << +/ProcSet [ /PDF /ImageC ] +/XObject << +/Im1 584 0 R +>>/ExtGState << +/GS1 585 0 R +>>/ColorSpace << +/Cs6 586 0 R +>>>> +/Length 84 +/Filter /FlateDecode +>> +stream +H*2TT2P02537P064367TЅ(r+q*srAU*!Lˆ\.}\C|@ 0M +endstream +endobj +583 0 obj +<< +/CreationDate (D:20030406193452-04'00') +/ModDate (D:20030406193452-04'00') +/Producer (Acrobat Distiller 5.0.5 \(Windows\)) +/Creator (Corel PHOTO-PAINT 10) +/Title (ss_default1.ep$) +>> +endobj +584 0 obj +<< +/Type /XObject +/Subtype /Image +/Width 529 +/Height 423 +/BitsPerComponent 8 +/ColorSpace 586 0 R +/Length 15200 +/Filter /FlateDecode +>> +stream +Hё,F2 OS@ [hu1Ӧd|K߿B!¿BmiE\`: (/28e&Xgb|2d5F2IOK /Ssl1]RcAF=2<)W3^®_ -ldF H4/2bvv~d#Foc^ݎynԐ鏌]ohl-=m72qxckdp\Z`vIDF6J$pMAFQS!Cv,^II#oVH*WvrT=eؕ7mW [ /JȰcG' awm+hȐ6{=Rdx)<*vXyQCն-2Fδɯڇ&q>s=*v52V^,[=263mü=P;*gN G9nZn z~/#5QqζXx}|$ 2:{T_33Yd4*/ڭY 4*Νu 18k1iPw ODYq2~X.؁z/K}ș7XN ~ Ĥ~x8Ʊ S;^ed44MoȦ וHY<߫ҐuVOK J#rtO7A>w#c҅ V{eMAr++q,|ۆ: HBP@dPY!)(%9of9:$f]غ1=?ؐtgAɵ^ +}.BHM4FD"syn3hOMNLCmd݇ʥl7 AmdV*B‘$$7N0B/ !ҳC< 2SIypA)c72ѥ(4 7ήAFK8>[![?GPȨ H `% UTVnFl=cғ]A:I].+lubt`߿Yxhwv 2Nz܄ K ]?t42Ja͎,lJJ<-͈=OHFɄ)#;k +r9@FA-2JnB +^G)I$[޼cylBRisA3R!2{=K@ ~p]icLNU"N%;&ak{72r\H YszCwd v#nWONvO;_U bȘdarwMbI3m ܤ +ve=(M,v&LIs}x dd)C)r 2u! z*|Kc%{6$[!;z+=q'1(Ze7.m\0Б ~ۈnd嗤vh5_NMIJk{1&G#٫'Am"#[!iNErN3ta0e(FA-2*;S0 glhGI;ʏ>'VvYA{72Mt9n6VMB!m!Ľ2Bp\[ ] ep\2oddg::~!:wӧ # IQ9A W@\;㉐<{02~oVX4|,ѧ'1ͮsoR2N(O>v62pO7GFϭ#]?QXy1LK:GHx Xd e5E]~_._c")^D mq^HRE1N^=jE NuiXY2ƕ2Vjt;h|O8t6q ++)[!cŊ:jlF uσƧ8eHR$%ENsX) _J !<"#BvyȒmZ!Cw28:2 ߏs"s3H#)ó!#K^y)(&ɋ'޲DsdA'9ِ??XRNu`odI!2Ft[0gqXN  +FtxhxȐCNY>2 Tzʘ`}424)몹Ct/;ڇ"#\qrd @校Յ!5/"#q#2}2Q#=eC}h +-2uTic;sXG#F(##r>5pĕx2p7G6M81Bᖨ[ }Y`8/V}Q 2:{I7?yEDg&5zZrt֓ҵd 2xtܽ #b&ov=2~ |A7+ 2Nnq췁 ;d`@@[#Gg,E{i]ñ1>g2~7PD N*'2[8B(CȐ%C318d`m 4 COȘBo,%Pnޓn !xADz!Vy 2B9<AzU V 2kd <|_3@ lx!! !$2d !cB'@ycGJ!@!@!@!@!@!@!@!@!@!@!@!@!@!@!@!@!@!@O,UR` 1.$q#nL Q@F0qB;T~_U >]]ܜ$I$I$I$I$I$I$I$I$I$I$I$I$-w--"$@"ɘ*BgA[؋dI'ɧWGOҮ$.7$HddIJpGP=[[OF̏7&!@"(h?dIK%cTm iU`$I$?Zsn$I$͟M0\:_ߞ̿$@ҲwS:}JdIlq.4QHH2n_(TǏ C2nB*1$HZI2f%@(͍T2d$- VE2$@2$@2$@2$@2 T^:Oul?=$@">sptY8I$-2Kl$HZO2eSJƑ$HZO2:G%$$%G$VgVsK$-޾.`$-̽dF23+}ϖdIkN I2 idZd̖ sS$$tHHL ә"@ 3E2$ɸ ` ә"@ 3E2|z:hTwug|D]F2Νq?rw)3'_0;H̟OF՝d2:2S$Ν-dd.3:E2`ΟKSi+Z|[^߱;g0L 8I26`\>="O 8]G2"@dŧHHL ә"@ 3E2@2Lgdd0)a:S$$tHHL ә"@ 3E2@2Lgddqdox04}o|P)'cx pބ$)$q3 3:E2`db_N2XW7dT+M5E2~$]dN ɸ JSM d÷5"9E2`dLTߋ;/O X$U5GηIS$Ov7F35E2`d"@ 3E2@2Lgdd0)a:S$$tH, ~sH|]>])'cx p{{ܘvd"h/cd/n/?7}'ߦǏ;/s=wێoF2!dL%c/>x>}K/ÿH> `m$j 뇓Ǔăիx{!@kd}5~ٌ>HT#C E,Eݻd22n h2#WGPdT߽Hp!IF{dTNkaɨ,9۝xhO𥪗P}V\H*K%#/l,d5ڷUxxxZi_ `=_2i';1zc2tfdX*j Ow&cH@&+sTcꍣw J/$5s2j 2!U5'c۾d'H2jl|dqn7p72b8f^0Z*dHp 0$I I2dIa$H #@dN W2r^$ɸ+$8dNͷlߕ9[~d/|y;y>7\)dΝdt& 3 +J%C2c0#e#cd&ɐ 'LF{w =TNDad~},^udsΝԫdX$q!@E2NCF#XH0J2N6#+*qd[ctjgdWO}=;/#j׿߇Ii׫+(=-+N2MCNF)U^GuǝO\ԅMGWUso=a[^H2:i﨩3o=qǟ}*Eg΋< Sߎ"Tɘږ?KwHodsOx55upr$Ü5C,F״NhTG?hZI2:*ds'Um/;7t.2M]ΧdοW2 ӿd,aN\E=ySKuʽN;;+3~Ο}v "L,oOܽ耟k_̙]$cUsvY̒9G2JNj㞙9+'OGd/[iT2;92dd3X$w 226w Wr|2dwS5̖JFi_LFlT2ed?y,c5˨"=ER- + 0â,QQW$ ;$&-adUTpAp)FVUKMv]Ν}wy?AaT ^ž%' 223X@E~d[Ҍ(NpEٳPes40}d;.dڝ߶p`d02o]d92 . C\p_en-y5b~d a<c}1lm^g lTڑlWȠdxAXdX~ǽBe Q̠G:ُ?Y64Ջ.-d$ȓV|П2E,zW4_(pO SYd +~; ń.gVa"E# +x!2RBoʸ͙䘼<20"@Pi"@PBd[12{#(T+'Ȉgن SH yL1"#Ƞ3AIW@ %?p +eW tm!C=TD(JG"xKAUd6"#HJeD ffYٺ(ʖ ziGFRi˂<2a3"\Bi+d=2 ԅAd arj>ΣS + +P$shУJ2XR+ߐey^֙!aTWAP-d0rxU!O2aG'wZ¸,&"b h[``R /DP^dH:d/D +A>qB'"7"B(hH  +F cdPlS6#0VӞk52P(Tv*ka#٥ 4Bdм0JѴ[U W:E]mm5y6/^pIK{^v}e=m5߄ڇ) w~ ;/EWXppǁ%\5hUvRi貫b ;G]"˻X~ணVv^uoY}̚c\?v-u=ǯ5~}s·o<}'VToReɕo|㔪;o +8΍ V3M!wo2}[2ll>s[?ȬeGf/;_V_K|U/?Ck^Y?Gޘ[F7y*ͫhWِ_yU' +o=j)Nwm9՞ZTwzq%dKw~tׇ>Zh?O|+~b'+ W6yڧ>]{u>[_e|^b/YQes?G:uѯ~S7_< yo/}+ly׾?o|Wwuo~_w~Î >qn׉s%n;y]{NO{iߩ>ى La B$1Oˆl*a!a 2 DFAK H<2,q,FdBF$/GCDd 2ΑIʠSWR)h,08D sl +y@d 24*-wJ6#PqFM2hX$3aD#hS3@d#֧jU5 ЯlU4D F(p6x܈ǁ!<5H6 LdA@id6 4AAm"\2H 2 2舉 rIA<2聈lC:)1ȰLeiAF&9}_;>dfD"h8> P2HAfA.**-A mA m m}d@AU"@? 4vL5 7p +5(@!CF 2]Fzl&jxD DO=2E?kUWiOhΜ Dž1:B @pULa"$@T #24FFt! J6#8{*# tk6EȠ3ps:蕳hh~Hc )1 Ҿ 2"Pw?҃Gї"T!BdtI#DFF2a)UwT3q@I a3"2ACU39}ɷͨ{F1U2B!!2 IIѦk ,12HTWd@!2,gB }'UTI V3UxݛI1t3EjG̮91*}Խdw ~ C}G0["Ohh0_<:sflHD DGFksMd0a]tFF !2d ߐU"CȐϯ[(:҈@7[Mh*-@(5$\UeBX5.e(G!2ځ[UFpq>LQ*c/2z_kzea(1|2cL}(@d?UYgd0DdFd[ C b #K:*!Α8nѫRjMAd 2Af@NPc]I@GJ@dB2lwJ|PVwGGFi"Ä`lfD" ;uUFЌH24@d 2'DFh4`)0UĶnQ#"FCF@_1ѥy7~qTq׼~8 o#1o1Mq+VHxȒAlXL3`/2[rz>]U?nݺ]UT_z0 ##T5:OWc ~B(udt ==9 ٳΝ;`qQ2Amya#ccccssskkk֍FFu7U 3 .0|( Q͇ =U|W˛7޹}~B8h:\D z_ 2@FjTKTb cd}Ȱe5O@HL>{, هGFσT2/1y! هѧʨEޙ/}"}An'^9K~\u}xxxtt$r2#ICAq|S2 dT~3ܒ<Կ&wfU Te8 *G-9aT L^e-F %w߇ѿ0xQkԨ}yhicԿ&w9ۣd?2A"cUe~j89^z}ݩ7Կ:%y>2 FF4;A5h= #})zaD_XCzVu jc7su"qDFӐ0R~ZoYGTxM^ZeiNsNVEP62D*ś!Uay!4jm.FBđ'dDY5 'AhȨ]gɎ4B _H*fPc*^l2hww␡/42 8-v{T2*m]L'(J!4jkdw$/vCȐ7E eldtX^>2iFB[au3 ~uOc}pCSeb *oePbqV>dy"B6#T·+ + ʨp!S=S2"з5(iԐ g{۱Dt6F>B2RШ2T*6z"?|+ᯐ?8h= g#VeY@H>BFrf}mF*Ch+S#CXFQ +PT1kǚwdaِSp + {˶uT|ɋj超/xcU#J!֩ATp8'w^O aA9myidg/AVe& +2l9yDF&;w>TXUШuq +k|1d5\aË*22z*9"Nd`PwȨ}6Hˉ9 E=dA|p"N|{REF@x #ɼ3D ه*):]BkA$!۠ʀ8>T TN9ӵQwYOk{_ryy;v:@iUjhL&5@K62b%*.2{a1E#P 睭\.wvv><<<::JC _!cPmB…/nlllnnnmm! |(:%Cw>}p? PdbD,B@_FF TW!BLd#3_@F2d@@F251d@Fr2}^5JG@F"݄swQM͒[D b?2ӧ7dtTUתzPK c5VW7V*Z%JsQA,+2:@ёGo_o +O :s݄C2֠.V'^8홯6F(WDEfȐg'5βa kW52m}Us:i@nk8'_ѧWjCO iV?9 ^qU3X}a/lb"CE}v$RAFп=ƿ6 3|k2"Pp&)sBgko{Ȓ_.;;;U +%E#؝:/ Z}w׍rs I|p&߫U9IalsXd$ |CЩA}1 d')BQ8v֢{Zoh0|3FsϓLd>Âհ2Zwa]d5jA]hNY*Czp]'|9o5M^@+2bp'2W2Nwdla]d F\d/C 2NZ!֗mp~aX5i"l0k\zu>Am28꼉y> Z%AmAdG5m3A^hpJ ' БA;~ҥM;aзf`.@QCQ2nV)4Z항-.26o[=k:(&2wKk/Kn z/Uյ,GU1-;I,ԥwx:j E|$3dɖ<ϺER_1"4bvt陁X()du|>SYeH.ِ*cסhͶoA;|"8F[Ue9e;2 +]\2nݒ< B&)B;0PdȺoycEG+""62X=*s t_{{o"L d( CVw|\d)HL$C #7ýM[D bȀd䫊 T2Bt_W cֿESb(d@3S +$5d@#UGִAPD(j # 4O4 V.֊ +}`22CH ET_IZr'@E|@A1 &) cBFub] +ATάk$d}ݩ7?Ϗ^eȰs,g=պٝM.ҹڏ _J62MǁHx,AM5N<-Od-K"#A hbe_J ?Aȣ{ihd9p RTcRkC@ATd8qg%2׷cMI"ـ hVʨ=I':oScVdY䬄,gAЬ42~Z/Ndߞ #hdw>APds; Z@ ?gf"d@Dk8d䰩T*A!d@4ICȀ h2A$DFcpЦA$@AmȀ`0L  rF;wjF:GJ=Rg.Wkܱ{'=ǟϽı^}󯾿}>WJ}䫯>}kR/>񍕾'^|S/qxkO=֧}kg}:T:uW^>闯α^E3o~}?GQqQGtQgPs*!K'Jh᎞ +Jzr !t8;bjl`A<y%ٻey ]ųe'u^ν%F4[Z=݆zd7QLꅲFYWMF}V6퇲Qܪw \.7h{FFkQ!(МTnap44FNu ;*.B1S4ty:eB)52*[:}Wcє=Ċ v}coDZ4/JڌMG[h48k7(y;7xjΎ!w\Pjy;QTHT\PM9uڅFhhcPteԄ4t(!$.d.Y>j/::fwshZN$trNY( J)0*3|$#@2d3g&#!C2G %d!#rS=>Z[u2xE2x3-A2[ !C2gd7HF S@+F$2(E S -hw_ !C2dž +o<AF  Pv%#tѰNS-!C2 !1dm4oJ!@@2>u-aN3d!dB!d4 Ei;jkmX=e:bl3V s^hl_l3dvN !C2 ! U K먫S@Rc%Oc qә瑱e-j[ᅟ #2(!C2 !#~Fd:y뚢KW/_>n:ǣzQ2&4 X1'ÜB2 !CȈLF"S Ajjb5 Cψۭ*p:ՠ-W&#sxU#cˠ 2(xai$Y*qIB!dB [ ca;v Ԅ !C2> phӀw !C2Ɠa}0Q0{G2 !Ch rQa=!C2 !!C$I&dH$I $CFFFFF1ɐ$I 0En`/ +endstream +endobj +585 0 obj +<< +/Type /ExtGState +/SA false +/SM 0.02 +/OP false +/op false +/OPM 1 +/BG2 /Default +/UCR2 /Default +/TR2 /Default +>> +endobj +586 0 obj +[/ICCBased 587 0 R] +endobj +587 0 obj +<< +/N 3 +/Alternate /DeviceRGB +/Length 2575 +/Filter /FlateDecode +>> +stream +HyTSwoɞc [5laQIBHADED2mtFOE.c}08׎8GNg9w߽'0 ֠Jb  + 2y.-;!KZ ^i"L0- @8(r;q7Ly&Qq4j|9 +V)gB0iW8#8wթ8_٥ʨQQj@&A)/g>'Kt;\ ӥ$պFZUn(4T%)뫔0C&Zi8bxEB;Pӓ̹A om?W= +x-[0}y)7ta>jT7@tܛ`q2ʀ&6ZLĄ?_yxg)˔zçLU*uSkSeO4?׸c. R ߁-25 S>ӣVd`rn~Y&+`;A4 A9=-tl`;~p Gp| [`L`< "A YA+Cb(R,*T2B- +ꇆnQt}MA0alSx k&^>0|>_',G!"F$H:R!zFQd?r 9\A&G rQ hE]a4zBgE#H *B=0HIpp0MxJ$D1D, VĭKĻYdE"EI2EBGt4MzNr!YK ?%_&#(0J:EAiQ(()ӔWT6U@P+!~mD eԴ!hӦh/']B/ҏӿ?a0nhF!X8܌kc&5S6lIa2cKMA!E#ƒdV(kel }}Cq9 +N')].uJr + wG xR^[oƜchg`>b$*~ :Eb~,m,-ݖ,Y¬*6X[ݱF=3뭷Y~dó ti zf6~`{v.Ng#{}}jc1X6fm;'_9 r:8q:˜O:ϸ8uJqnv=MmR 4 +n3ܣkGݯz=[==<=GTB(/S,]6*-W:#7*e^YDY}UjAyT`#D="b{ų+ʯ:!kJ4Gmt}uC%K7YVfFY .=b?SƕƩȺy چ k5%4m7lqlioZlG+Zz͹mzy]?uuw|"űNwW&e֥ﺱ*|j5kyݭǯg^ykEklD_p߶7Dmo꿻1ml{Mś nLl<9O[$h՛BdҞ@iءG&vVǥ8nRĩ7u\ЭD-u`ֲK³8%yhYѹJº;.! +zpg_XQKFAǿ=ȼ:ɹ8ʷ6˶5̵5͵6ζ7ϸ9к<Ѿ?DINU\dlvۀ܊ݖޢ)߯6DScs 2F[p(@Xr4Pm8Ww)Km +endstream +endobj +578 0 obj << +/Type /XObject +/Subtype /Form +/FormType 1 +/PTEX.FileName (ss_default2.pdf) +/PTEX.PageNumber 1 +/PTEX.InfoDict 588 0 R +/Matrix [1.00000000 0.00000000 0.00000000 1.00000000 0.00000000 0.00000000] +/BBox [0.00000000 0.00000000 315.00000000 256.00000000] +/Resources << +/ProcSet [ /PDF /ImageC ] +/XObject << +/Im1 589 0 R +>>/ExtGState << +/GS1 590 0 R +>>/ColorSpace << +/Cs6 591 0 R +>>>> +/Length 84 +/Filter /FlateDecode +>> +stream +H*2TT2P0253S064ѳ42VqM-R݃ ҋ +*  ă˥k4 +endstream +endobj +588 0 obj +<< +/CreationDate (D:20030406193454-04'00') +/ModDate (D:20030406193454-04'00') +/Producer (Acrobat Distiller 5.0.5 \(Windows\)) +/Creator (Corel PHOTO-PAINT 10) +/Title (ss_default2.ep$) +>> +endobj +589 0 obj +<< +/Type /XObject +/Subtype /Image +/Width 525 +/Height 426 +/BitsPerComponent 8 +/ColorSpace 591 0 R +/Length 27292 +/Filter /FlateDecode +>> +stream +HMoIB/CpJ$N /ȍs@ъ*, hRVwǎ*v;|cm9kgky[ꚮޮ>>q= + hWb_͘O1Љi 8VGZ(^$x~'ƕj~7ssO;ƞGׯSؚ  +өf)tbs_&~xv{d9WEmT6ocAmC6h6x-NQ`g.k{+^yk +F5U.;% LPY }='Na1Ɨz|Xω4?ўb >Q%2Hg=]"V3h +qe=\-pŒ&l9w1ӓ3AKK&kz1$S#)Dԏr -;D0ȧ~t74޹s@op 3nt'u.ru!DYAn>N?% 8ps4w +"M/CC'*?I qr{7M؊sj5[t3`GmHQ V`Yi)>ZnnXM7:پ4eo#Mj&k&d0v}tBf4a+ΖxG땏7EiEzUQ@q`q2և_&׸Q>iߠWýJ`o-&C

}=;=9;3݊H"Mz"(w8+*N Te SL$,?G~8< +8jp~E -֭h7@4Y(j3ZeU9S1)p`MPUڤ;a VF?ƧOIcGt51=AmXggS˙ r(E߃A2H_0a"&%w4jB',rW8$>ER]ܛhi' rE:-G ɂ4)rm7 P 8?oD e {~v,Np@ +O*ׇW%%YD{ +i+Dk0 >%/QW;ey) +%Sr$ܧVo{\&k&#T>d% h ϩ(C؂$1(xS7M(Â,OKT~O|NSсe!DqjB;.˯DY0I勒h7nH:]]cqCN2%5NЄS, D'uM 숞)BM5n"jNE -޾EYg_ +8~݄7iYfyXyAR? =nd$rWQdއ'.M[ \pi r]M8>[jvpׇT='Mt>DhT:em*5FHAEt%Ykc0wiDC$ H"M`SDGr`?Rce9# +&DP#DP_:7 B\Md:RM+ ad Oᰤ ႐0ښn"MDDAhM`l0)VVꗫ 85^p!4#p}7z!+ &F쌕e5K#Fg@"VrւeֲϬd/O]G8a.tK }Hq4]k(He+섔/+ǃ~HQf4a+E~HV'PHmjqF AF-GPqNv}ܝhCrϸizíoqRl71n]xKZ_٭1b\ȕJbi66oyQ,O! +Q̯2p)l/s/IJyTQʿ,0AH׫ٕ%⋗/ 1 > g~vai|\f~k>NyJ2 f'O^|Yl}.}GO +Zj?E.i/0x`Dt:@ h +@Bi⃟&Y>>@h 5q\iu]TkM8 D佻as1V\%wMq H(ld3Sۮi4aJM(~Nl%yYm0L~͒ $'D4@q%zp)UnN$`/hQ wSɍ37dS90uľz`佃&&\E{5)*o`!Z=#Y +X0PH47MHQtaL +wjDs;t&TE10@JMd&ݽ-\ADfǯ v }vrHw iBBhAhΣnbhMp3ĐhYOClfy|[ &DqP/DaT?Q;_ܩJgR)N +[O6Pd< `S, ;YQ:>k U-5d2LDaZ2PlhYf%\TwȟQtS)MpgMԀL{Q3ih{s佃&&\E{5Z !"|Ny7a$tfl|ccxN$-JMd&ݽ-\yi$%q[0Bj;Ĺ{vH(ld3SۮD +\र !@G : ĕ&\Eٯ#F6nqĚrC@Qq=i"35y}}Fٸk)ۈ@(5Qf]ωR@yAVRWrza׈1Qے+ncMMYLTs$T&p &ʞO RJiZE#$f:4!;BΔ̚.c&\E/(3!(R(r/HH9E,E'L.VCXH،3ڬ̆ >bfw0kWa&]?ntW3ϣZ5==r=n%[#VG +ElD,Mok~`V.D:o.NP\D|yTrj}4 ,}[ Fnwu5y +ӄ=L9N8M&>mhIDϣ|:}"5Qk_@y4ߛo'څ>M;nmZóȭWy07..l +K!4-zkU,4A$jZ96ȧK`LehM> ΒTrj}^zWIč&H b'QMB8_4Yi"Nrz.(*F +8 եO&"5> 'ߦ(rc b'}VG S\RTlYhQ&wg~|o˱G4ap?';\v-ZiVBKBmSM|X&jsSʩnr!=4h5 4!&K3c~8B2*՜l. Y8J&'G&ՄѐA$$j"CGލ(GdX#H5!=:}Vbzʸ>)( kX9d + ID^vk+5daYL\WqĨ c +gE\5q E8[7H|SDF6$jZ9600hp=_)v51ٖF -(qDuhB%ҽ'?(zLU)LGT?Trj}x]G,5))E1Bddm)AMv}.(\Vv} Մ i}~hBgLkB Hf pPMDM"9:5!+IdCeh¯jKׄ D4wXR!{oUI1d;V_)?rY! rE1B$4̀&c]D,1dю' ?U+pfM4vL!SزG8GGf(I4Arȶ&,{i67UZ_(Yhı !hI!{MB&4A M;h v!$4A(M;q(cq^i(wn@>[_!?xÇˋ3Heaazu 7=!XYp)iR._,Cܡ|gցdyq}Δ,}ΐgTw03́L o7~Um{_\LJLa͙[7>!o}wb\Md3Gsx9&ٞs7 wҁ$as?۲HKOs\x2k./.^"}#2-40t=TA&nZh`A&@C &@M4h P@&@M@zM 8imXH@} 4h P@&@M4hCh`xûF@4h P@&@MM^F}45"4:51&4 +h( @&M4 +h( H9&w88&4 +eikcہ?~R&@MY@ l4'(Dx[㾍IJ44 +ɚ8Уa&@D6H}h`r5m24+%"&(D+frU 4&@MkS 4;MBOiJM4 + R4h,MG,n',u%hʭ&Ԡw}#MB&X/k"p744 +&lZ;( {oD8M}i@^%=PB<)ANKԄ?:@^P 4 +hz +4 +h( @&M4 +8Bݓɸo8_?(4?]9ym<MBh/hhzG6}&MBhB9z44 +=U/C*)}#h,M&|K=Df(4{~4 4 +5D.&@5n@&MKM@ς& g cZ؏&_l}v^0-[ij&MTEєC먶1]tv4lP04Uv(hJ(P,a$ <66Dg0>;Oqy} bBփ&! +MX2xBd 7 +MX (4`=Mф\ 'L&MCg5mehO0"h4šeUz Ј&.䓏:r`_bWݵDL&$gz^ڭɾqf#\O!ع?F\ٶmm/ş{'Q4`!ajT̋ djX9:4:>;7;ذ%&j5\nּ<_=494`ajd*'d|WyJQD5ƠZA&4\X4 4d*'ݽ*RA 05Q*G't l|sBqlrfӎH]VVM\= Sg~xlT,oݾ]^\4vbf+1Y5D"o#ת&kH +54Lejȩ|>W(uSȪԤ gѯ|j5,~rf%zU\c@&b [L.M|]ou:FSl1"=Mh&*SƲߞ#u * M}?Jd2W{ξ}_/_ؕY)&gpBDEXi~.\<5sh6RMt^rڵ>+[_-o) uokSԧ gCtiB&T_bs_J"~\S +բ%\)&BD,xw篈)b +)};}B!/{c>yU%l6o1h9/T+g/Åk MTg`#SL\f3\6}x쬬JO42PAT@&$gzg9l^Y̚%i +&tׁ&Sb^\ S3?vʥ?JuH*RնkByB0hBӮFpibh:k&*Iұx?;(,V "&Խ]Z[X6a;? 0&MG&M4h @`@44NMȥR{&)X)A&M4MD.~ȃ]AN Y&aMM_Vkjs㲝i4FZ*kph..MBąIJ"h4&BM@pMZ;4W1f>l4Q+hē= j<54Q+h } +@+4MDM44!lϳlE̠ZAl DSDDUVުgKӄ~?~Kp]y}n4|s4׳ߧ5G@O`p_OE֠Wg빪Lׄ<ӯYĚ{lok:&;uA&~Fqq|oDFCXԢ)&08 b&P +UQE/~h*T*E!A!*mBIhU9`wus^λ3w_ٹyyvvXTbi+U0!JѡQ0WHr & k}cp`=BW(`xhXDŽ~cB"&4W)ssL"&Fo>]%[0Kb[DhEYd7Ep0pB_ q':G % 8'kieԚHd7h)F4eeԗ0݅>`n_˅(`" & ݥN`Lv}Mr@ 0őf$~Xx7Ldp\LL0^t:&D&3I2&w2U!&-pL\ܦ^;zHc ^Lpo01, +bB9&'1!cp}r &P(cp 6%c jA<,D%MjhLuLBRP 1aE2 ,&hӟe#ijUhB1aQ܏M'uLLd)Lhʦ0w! + 1ly:ً *#P(!&PlDT2Mn{B44ixü^ELp@B +O(@&D]XtЏ ڠP(X  {1|'𝏩rF(4Hӗ/EmP+ gu/#&Jt1&4O0*o/.brF012=0!_ b8b¬1(3 /y+D*j b¬܌  +lP?q & +1BD2` +@P` :^TAL 40L;.2C)L#ն`F?]D*[|ln'wQ1od[jR-?zC_&ä2H6tʈbZX"C_VP.P~ٿAK;FLtc~GUň'ݽ̣v;eg?5munMr}v0cGjUdi@ꋝ1d,iCLaAń:L鐲:ݽ{9m_Q1_?蓱e+NfOe]yFٙNZtڷ *gɚ۴A(_Tn;|e}7h +)`Ѣ?*|xA_f{gw|M#G}[CI;_iœ W HySں[W5d0i]CFkӷ4N|*n*-Wdoi%~RMʿg pղss-TS[4f%/}’ܯ˟-TKkK\,ά} /f(DDE^ ;J(u?m=2.%Đþ1nOԑY;xfwpwgk3vx3`B;CYCw +?w2: PFPBݜ1[<"f5ݸu _7yM^󪜖-nYռ0qnʅYOeʈxLLxK)#L#j~}!rVIIbB!^ԩtc{ "' \f'~AM iWufWwFc:BƲbJrK^T3 OlbgԢ3V|-L-B˴F, 2C](hHS@4~}0]}].>s(\FoDErF&Hju(eMTB1o\wmmaӦ檒%U[[n)n͹j({$c}Q ʈ%m +& +>lgDX$vR Dȼz:0AQ!Ei)9\ZP]ZZJՃo=jS$_3cE-xK5]jez/S߫=jGvgv_n o-cyM{Q/z{zOS7E}ޯM?r _{#s_2p5.}ѧVdPl~{f_7]'^ +/0wx{O(w +LLg,F0" +Fq ,<A^ +"T| h4ǴLSfl I niF "e (X8w=~E}lm6rz'(DNTiL0b` FfmUvu.qQ +YsϖANp+„݌0'/ل9Y1Op-+Brę)i/ +HQh4*ZAcPzP=+A s$Vۊ2o0z׏`A;8l7]B=}zx-pwfCކd8KWV7GWա aܝ}+ xpsd ?x IQ$+?8q>&3>GYE3/ﵽJ0!dKUFoZ:DCi ̊606yRh>%{NbCAarsKW0&&B DI6ILH쎘pr#SaG0ɝD=!)\&_UQ1 j@ +/즱C'؜nf} o& )^8Bjb O,(H?8:Ǖ5Ƭhex$" +;4'?uҒW,=KEG0jō:r$ґ:BCj`Ĩ;IcfΊ싳7@fG֌`~#~5W 0#j%QjB +W&3Dhf" [eRa4_y+#<j8p,FpW58%\?[khnņO2 >;ݢYǿ_σWm+Ƿ-&_ E+)BZ98`b<#S_p.Vtjpف⮸8cM7*4 & +}Œ?!^)]< X"V}ݎ4%aV'C,؆g5=hK}N5>JtdTaj]1 _@-GKsٔONOeq8L@ׅ;QA`Cũ֒tt` ќ'&r7rr~->k#'oAn@jb񙃉I6\OfQĖV{Aal :VA1/ gOnUJ{Z3k˄Sj[`PWguVq=Kǒ]X#9^u]Fݕ1M5X +"}>;h +#6ԧ߰1I'R:0^L+V7seYҽO"oӒaB t]8Y#9sZ;$AԠi_ӵK8y&f&p54cH20`B.Du2`(uNz$9{؁G«Ie?Vi?nRmw{_=;BL8oOܘjnhV])ErOS]CjV&Ξ-}fI&rs* +η8ZCE-KeS9}~&X1&x'b'1Ltgw(˴כvo0SCrC_ZOc3=gԞj":Ҁ0G$„ZV+i7JuAPe1b9";#uHeUFd_AQ]g?Qǩ3c5ejFGh|"EPh4$ib1SjbŤ ɂ~/{;r.7w={:~^G +rFxR4J sB`x㶟T=h֩ /Oov}*#{,9%$mZ#wYo屳r LzfZ35že&~v&u:Oҥ H͡э` +n,3Rf49Lr8.GOk~&rY$`j%hbgMjm.z&xCpZ}ݢ&~ +&PT#.( '&b/1X#ʋ0.*B'& + +&jBy߲ 3MRYZcY̻9Lh63= Yg:2Iz]ΓtiB-ޡx&pO^bCL)I)$Bؐ?ӄj͙Aф$߫&&FDgNY8 j *(V|h9rbKYXsšte~-aM-lWK˂mdɸEpL_tP7xd-ީ9>A/S']{jWr*xynl]4mASLѲgÓ̼!xPk5tİ[MzkgT5Z) #x HT9ׄϳ e/\[Oۊ.׶-m9%ޭE8'&D,ݍkM%e45-j8[|pPz_ ܑܑȋD2BA;zѤ2;"kaЄN!&'zhϱ& p!]ㄣ +gYoy*g|^֞_jK9n=`cY}o+p;;73{fF6c&a\e](zncg(1h"XaoWJQle,'M[(M HgYjejtM~vz/5pM@[|QW@jkHOɵFN n588etW\p1:AFktqVƦϓj=ML~wrp ӄX ?zT}KT} dM,}8Nv2uS(E QKBԧ̉j"O0 j0Dh} 0GM 'Ij%RgO(k؁"QF9'L7F +2i1TU*!==4`eKQM8tZ)2/Q.}&n]Qb# \ͯP~yiÖ$ 9fӫyJ~Eq 9dFZgB>̂RXlB ە&u@1 [U p#`9 QѨNAQ5$O\*j 5@1=}a 9IPX}M)twB f4[Drihd4鴆hnVi59F0rsy Cc#*9W2/ϸ+' 1mhTp4@4a6wkdx + +VD/+u'? @`9jD1M(AdFI*@*HԳ)WR +|dxl:.Ah]_G8RzT)w?zk~#jb}VƜMk(JIibSzl du2`i“x/ϟ+ +Bz4Y>?^:@ 0e*@5~"'M$RMP(xHBMxPPr&9OՄ_Mt񭟾k?CP(~B4qO/K}7~4a4sex$lP &fK5AO|S~hsヤk:* x0,,14jEwMMPMn%p^/s !x2FAvfҏ 3 E4a(0YQ:k /ɖj&2 Ӈ8l@@pa(N6˝xj5ZZׄd:U'N(++5mmmC ÿF˼O1|HM( +[5a[8M` +Ƭ7h}ȅ(jv;;fW*o+o*̗oJ-!&"ܷĕg vTnk;V[,cQM 0E̵{-U?TفW~s~N?+;F}@ք/+Owxi wO!x2F8!DHcLR%O(0&޾}ACRۛp h)LDPJ肙3\.)nYaUbLx(}̝$/]m;=W`on rMP\D޲G `BGO).^gLm0&ݻJHR#r{ 0p0A}d +xzRkb+PaW(Tiԫ@utTMv,2y.G3|5M7DoaM &ޞnמ?$#Ϝ!FL ;&P w;&jWٿWڴn+7u@8^JoMP$vL† me-D"L Pp1bbhj \O*v)b[7u7 jNl&t<@ԉRjN&~0A?5/ oVtg[1aCZabSZ:ϏNH޲1+ G0 +onrhHFh/R`BG SPs ;>K +n ac 3n1!nnM2b\܄x/ Vc:F0 RQfY]iD>Ӎ8p s%hP3ׇpccr\B2~V7wڀPDӛKL7Lx^\ +on7rv:_2pTҸ@!z2f +\v}M1 d  +&&~yvŬ46B{bj8~cDݍMPsGf;7AǤ1|% u'R`Lc"  f͡vST^U{1bbڜ{Հ=ꋋƃtM8o+D :xstE7a1&#jY )d0zsՍیƄh8jP탊11l`9=hL(PG,>&W¤] _d"F\ + u9Ls=on4X)L1b~vŬ>oIY\Dn"~&FJ= 1#rf +\v}MG?c$UWo1L~4b~cu{ۓ[˫{V8pۯ„H5&H`R#?~

}d|y?\b"LA0Hy)#ǝĿTy ._7Ub`rj9L(g}BaOP"ˈ&NBMtttAj@5/_*yL 4hq`z='JLRd` ULhyj9LW8O +1&=-$uf̙3Ν MP΂^)/H h~kM}H'9F{Gx@_PwQd Mm5X30#HR Vr/D>W n?)0&@L7>|ITl{x,ng>IUfKnB AU(W]aκńxĄd00nт1V3C3Ƒh]Lor&wiÄP8Z f&xDƒ&py:MXJ5-~0!h :1H ( `<&t!L59R Ғ9)L Ȗ1Z޲Z7o~ńuJƼLhIL0jiw_yLE# /%pcRnnjBM3•k8 MMs=ݼq&!9ILBJL `- MpQc7^#xqLI6c k0!'oq 0A m!d 0!{9 {  #)d0!f` Bi +Z~u 7X繉$݄%7x͠TLԅq ܄w&oGAa:2V:3*uzꡛry&À8]E0zwRSK{Vi̽lTSOEsf͛?͙{[V0Ms=ݼq Q,GL C!c%$`Ξ={RaJ僮_@JaB&B='f_?)^@ +`Q|bLj& H)YnB̈&B>]_c1a3&=3?7f`"iRo#'='V?gww. Mm+۹YI„d0:`B0c#/ kľA1cq'u#„ +V*o_#J&|JaBuWMII)cW{0n0ē) fL +`.Wqk"RRRJn"v")U쫦L$&~Eq=/JMF1 *C8@*牊QG#?dIN;qG"&֩I;vNL hQKn>{w,xM8gHMضf7 c 5 &b೎4a0kB8'"5sʨhIzfhƕ&vq{h% DMs?v9ҐCV}PxN- ۭNytN**L@qMTknh3؍(c\&qKM +/]M51 D&C^ljbXΊpp?41zAE& ^{EYc,rȘcT; e"2'O,.~ +&ADVy6V$.wjAA&^9\ nj5 jA n Adp lذa6_?א-Ci P8]و[Ľ÷^Kn mEY_"Ie!iZHlgdI"$dӸZ"@6֡|v+1aKkA ++ZMH?j"y67Lm$]{:l!{%B܉>čp넌,ddVd 0tv8ҟ ̑=ȐG$=z:vR xQ;GdHzd~6̦{`H|lIRy0;H{_:*#EM4p`=݀'+>~CV><+,A{Lݹ/_jʴ+R҄S'*ndMs-0y U_w.LJY!bigv!JI)"? "KaޗB=?]_akӜUBC̤K #&bH Fw4D2ZIv)HPPE]Pć>Di))-o)8AxXrëՌ@}e8/jv>b1Dَ @2 56R5qkKP1pYDKi<1IK%RjjZ&Y~N:FL7I_ߟ݀!aϪeмafSf͔K&2A@#kI߭hBG2XS@r8uJuB;::"x`MفYeu\!w MG5!' +H|c,ŏh rnUqmP{9{8;Kaw]-7~x[mr4l[iWh>|+_ н7p̝e+bL`U\lee{YKjɄ1+K"ڿQ3^̛9̼l3g~KF`$H'U$HZY!Wl,d,7U}6IeEOI}(EI477x3% $Bn#M,j#|N!Mv" YOȌDI4&Z<4psXGaaT-6~un}Zu~n`LeۺsCzpf*>r{ƞ`0gɪI&CE^ZB/J":W RJw4OHIH-4X$3$ 2ZJĺ= ukcZҫgwQ-$8# &~˩N{CAAHB/x\& @4@6]{W;n`0RD-o`mzvk`"K":$RYоJzAI{gыE麹' VݓDkn,dDƊ4t/jPv&\ҐݢE7bY1ש p +&4Eo4!<@%/%gaws/c羺ޞh@npy=f*>нa)I`0+\W|h>hݴU2Qeth>Lee͢f~ +_iKyĸkOh= ԄFѻ'Ta,IvvkuI˜]u~Wx84Xَ4!AouiB.G˅rk"E1%8vLI?\ö;p709.Y Ԉ1?PJFuĖ*i {ٸjD0:DMZrV%XISo\@y$S$g:yL)HݶH]P5D4dq7Ppib 9#\&V&:Q7j('L֐C{!9&B MTU 41 3@fʎ*>d:`׳ZVZÀ)"JB0uݺ$O9*xI&Մ{QMԒe}+٫A32Cn]JB+[>_% ;&nb"Mś. G@A 4ATU &0  +̾Í>CEځmYq5]AGUtH◪kWMWL))E.=\'_M Nj;l΄3zEH[-:"@$MFYGe!D8V9WM`SxAڃp#Pˏ +mmmiﳩlT:Fd֖*ovVyTKxԷkT1őS \SXaH3L5$dzʎѥG\: % ib WM iR{4F/PM;h"p&LT(GmM-Ç~nqԦ:lB=MgebjnfCs,?$ D_cgM'7ךw֩zkLp,Xl!3$U"JzG#\F:Aa 2B Ma8s|+̾S>ݪu*B!mDE-Z +VzsD|Р9s|vPѐh8[״'u5F n:v[ΤSh ~'Koͳί|yJ 4{qw?׍>-ޓ@8ǫ-@8T:",cUXG{.,\ȶ ܶ;4x3 -`F§%" +endstream +endobj +590 0 obj +<< +/Type /ExtGState +/SA false +/SM 0.02 +/OP false +/op false +/OPM 1 +/BG2 /Default +/UCR2 /Default +/TR2 /Default +>> +endobj +591 0 obj +[/ICCBased 592 0 R] +endobj +592 0 obj +<< +/N 3 +/Alternate /DeviceRGB +/Length 2575 +/Filter /FlateDecode +>> +stream +HyTSwoɞc [5laQIBHADED2mtFOE.c}08׎8GNg9w߽'0 ֠Jb  + 2y.-;!KZ ^i"L0- @8(r;q7Ly&Qq4j|9 +V)gB0iW8#8wթ8_٥ʨQQj@&A)/g>'Kt;\ ӥ$պFZUn(4T%)뫔0C&Zi8bxEB;Pӓ̹A om?W= +x-[0}y)7ta>jT7@tܛ`q2ʀ&6ZLĄ?_yxg)˔zçLU*uSkSeO4?׸c. R ߁-25 S>ӣVd`rn~Y&+`;A4 A9=-tl`;~p Gp| [`L`< "A YA+Cb(R,*T2B- +ꇆnQt}MA0alSx k&^>0|>_',G!"F$H:R!zFQd?r 9\A&G rQ hE]a4zBgE#H *B=0HIpp0MxJ$D1D, VĭKĻYdE"EI2EBGt4MzNr!YK ?%_&#(0J:EAiQ(()ӔWT6U@P+!~mD eԴ!hӦh/']B/ҏӿ?a0nhF!X8܌kc&5S6lIa2cKMA!E#ƒdV(kel }}Cq9 +N')].uJr + wG xR^[oƜchg`>b$*~ :Eb~,m,-ݖ,Y¬*6X[ݱF=3뭷Y~dó ti zf6~`{v.Ng#{}}jc1X6fm;'_9 r:8q:˜O:ϸ8uJqnv=MmR 4 +n3ܣkGݯz=[==<=GTB(/S,]6*-W:#7*e^YDY}UjAyT`#D="b{ų+ʯ:!kJ4Gmt}uC%K7YVfFY .=b?SƕƩȺy چ k5%4m7lqlioZlG+Zz͹mzy]?uuw|"űNwW&e֥ﺱ*|j5kyݭǯg^ykEklD_p߶7Dmo꿻1ml{Mś nLl<9O[$h՛BdҞ@iءG&vVǥ8nRĩ7u\ЭD-u`ֲK³8%yhYѹJº;.! +zpg_XQKFAǿ=ȼ:ɹ8ʷ6˶5̵5͵6ζ7ϸ9к<Ѿ?DINU\dlvۀ܊ݖޢ)߯6DScs 2F[p(@Xr4Pm8Ww)Km +endstream +endobj +582 0 obj << +/D [580 0 R /XYZ 109.858 727.97 null] +>> endobj +42 0 obj << +/D [580 0 R /XYZ 109.858 703.064 null] +>> endobj +579 0 obj << +/Font << /F29 416 0 R /F28 380 0 R /F8 369 0 R >> +/XObject << /Im3 577 0 R /Im4 578 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +597 0 obj << +/Length 1354 +/Filter /FlateDecode +>> +stream +xڍWێ8 }Wjז|oEXt͢>(cG`H'c:")Tb/؋"TrE,6,@ơR0ĵ0'i;爌@*kg@Gؕ{qYȕ7/ϣ^˽QՙC?\ +rQc07Qb=Tv١g~hS.}peg9) l8(x::)mCEBAOԀ jp{UAWN ^S{DT44 ?Ĭ E+ArBLz˵&а[0ߐi(|]ErKQB;comRzHq@ȩqϛƂ8vHczQbBpxAk$0@P:ݻNGڒ zRxDew]ge-#N ^b'{j5nĭ\M$ʹP\]_!r.Hj) +"Q΅ϾOJDp;`cLn/Y2:RMBk);8SbR'/Qcb;lL)Ҳ)R6 baa؅xi^*?חEJ VUHre\s [mTᓾyg")k^T¯؋Ϫhendstream +endobj +596 0 obj << +/Type /Page +/Contents 597 0 R +/Resources 595 0 R +/MediaBox [0 0 612 792] +/Parent 509 0 R +>> endobj +593 0 obj << +/Type /XObject +/Subtype /Form +/FormType 1 +/PTEX.FileName (ss_oxp.pdf) +/PTEX.PageNumber 1 +/PTEX.InfoDict 599 0 R +/Matrix [1.00000000 0.00000000 0.00000000 1.00000000 0.00000000 0.00000000] +/BBox [0.00000000 0.00000000 320.00000000 256.00000000] +/Resources << +/ProcSet [ /PDF /ImageC ] +/XObject << +/Im1 600 0 R +>>/ExtGState << +/GS1 601 0 R +>>/ColorSpace << +/Cs6 602 0 R +>>>> +/Length 89 +/Filter /FlateDecode +>> +stream +H*2TT230V0253S0630TqM-R݃ ҋ +*,-  ă˥k{. +endstream +endobj +599 0 obj +<< +/CreationDate (D:20030406193456-04'00') +/ModDate (D:20030406193456-04'00') +/Producer (Acrobat Distiller 5.0.5 \(Windows\)) +/Creator (Corel PHOTO-PAINT 10) +/Title (ss_oxp.ep$) +>> +endobj +600 0 obj +<< +/Type /XObject +/Subtype /Image +/Width 532 +/Height 426 +/BitsPerComponent 8 +/ColorSpace 602 0 R +/Length 22821 +/Filter /FlateDecode +>> +stream +Hϋ`Xa0 |I >9qBs٣vEc@ '!y>L2LԏW׫>>==]5ߧ_prlw&ܴߐCf,~f2`k1o|Ρ9}KNy}& 2Ԋ$7/q;!K`amӵAvxn_~94 ao8pSÉTˏZ|uՇݴA]q)cu0ѹC$"OʧC|Op!BUx_|wpʭCܱ{>.\4q/UIIASw4{{қp~򉅦7]Tps|2Cb_i3y횂;4Ax\;>1T֘$s=aowwNf\ܘRIW2 f bGjǜ++cYw[xv)]7 ]gsC#&a +51zЀ3;\jOsE%ݡ>nke@ħ!B<1x*P_GL;.C;֒Y*Y']֯37Lx;㎞ cӇl~5stHb:<}GsGU^q~/}@_ 53ĠMk]b̪%wu0PцX6w7tSOCWw }Gq}Ǡq@Z`$ZiUhQ/]S "cyvFIN{pA_9>wlCt?;ix +P;Ԓk=^TgCi;NԮ໣G^iC j"}TNG^ oM]e"\g5;Dh?8 wL& CAx@m\g5;D (:V +8qqP!grT `(pXoAAC|'I?A|xEcAsp Q3 ;N_63T~(;4M ;Ix Nd(aTT7|oQꫯzqu>oLࠜrծ?ZO2r|*X_GkۼXJ>=~ 3'C.^X;K_QU\.X8Q S͖'a9!~7;IXDXҸȻv.+q6 DwX7k9ewY[\$wdrmy;^#L)@ZH`,C3UBk1R^12sL`m0˺8BofsQ^ '"^XHw +Jwlom\%ȬZ0J ʉ)o̓Zm~˛4pпHUs]nxee%a9g8ztB|A;\kN??Cz3F|j!^XHwk×.&LLL'aP )b8 ]֋w8|Ds?]W$0"s7+ +:IY(뛼+?/^;&;@m+uO3V uw%!v?:}ІW$0"sjUj01+֪GVA_ϗ1 f,>#M [o,Bd&VvG"|Q qΌ(l ",DBftG˺f@&Oݽ|+5.68'X;,ɬlݱGgU;IwtaO;vؾ2l=<ti +b&P}< 8>L*t>twP%k=J#xFr=;ʀ;@aϕ )wПv!xA_X +MqٳgGכ!^XHw,}{F=}BN m-p%G0W8 m_dw6.!+ N5L!hK˵Uqyw,ܥXw}r=a*ͮsG }GHGVຈ86/Tw,jXűӇw0H`,$;MAF\ a3HÚL պIsw[}8 RX2vܱ`LC5!3Fsǭ;/C[wn FɊD#yYsǢqth-Fɡ9 wq9t}Gn:Qs`wXg+|C"uitȊxEc;jF"w5#^X 1>8$;ts?p ?-4wL;l W p7gra$$$Xs@v C2=Zztwl}g߿>|bm\}S7w_ }7bivo+=pBsVmӵA7Mӈϡ$Vw68G8Z}M ;.gR ;=B j;NfpG)LO AB|Vў~A rwpp\1@ vP{KC,܁@ ̀;p{8;114܁@ ܁;Ѐ;pp@ C@q>܁@ qӗpV(pDŽ@ C@bh@ w ~Jr3c5ٹ7nt |DBP$ʝ&.D!0c@@6D,0lv:S:ϩ>\v whPK;(oDžKv\~;17hPK;v@|S;Nvvt];U؎1ChPK;v@-@;ZCc/ӏ9pvoC7Lm5d;4ooi1:e߱J!ӎOh}Ivw%}X ۑ:}v\y߱M7'x5d;}vt~lS8]gqiۃӸ2Ku5d;ZWUOK}=/8:~߱]72ղ5G_<eߑYWmʚ:ka3x߱ɇ@!v~#hǍŃWc5|; ۏ}̟_iPk}GWSO)@]X:vWӎuhZ~5J;*Cp|%5|;u>A?֬v1I;Z÷cm%RДahPkv0)hPK;v@38D; OLNphPkgy5>N!jێUz׎hPk:hj=-vI;ZiGHсv&ҎUcgQ4B9 ;AjL َ"_wt@QQ;ЎhPkvٗ볡@)ahPK;֐`2X;̑NK;L~iɏvxvziɏv^ڱ^IɌv;whbq/۱+x+sr|_ܡ<η +3eR@lv, +=ÔvۑYlh;t;ZQr]&5ĆwdoM'35< 6p;Kw +f hǍŃq;>o"l?n=Sb@SbSnhba@L;L~iɏv10 &?ĴG;vhba@L;L~iɏvڱ^|63h@lv(,ȢyR{M0nG*;'#8lH5M0ĎO;Lj َ| fڱFխe&bюJڑb'Ўeco>2^`4qy+SnGFcv_׍̼k?>{|+;G/ݾ}{Hn&ROL;;u8^}/̟=|_O}#_}oƝ;w/ `v4qjcGzmv&3>۟'͹j}d][nz<ՎQ懏237vN`[;n矽eۨ0sڡnvivt36jXx'63F퀙A2 + X,Z.GWt ύ^nHebg>Z<:|w>:;4Վ`GPҎ@_툻PQL|$8ѫƐQԃC#|8Z:db:`юlG܈m;2( G>Rh0}׎5q;vn=R`lGk> +|WI_R^k:vdN`jG8 hG|~E͝Hq6$xU;q ܎M&zKcg> +۱n1t37|;6I`.zvQގeb9 +LM7lX^|TcQ;`#fvhf2mv\Xj]g2m9ЎQ;`C;:F퀙;ӎSOhv2nNj/<7@;;:F퀙RGg*Zڡ@/ݎօ=>oyvh/j[#s5`vds;v֡}vh0v?w<-|zC;^hu;َxtӎ^nv؎xZ|NTtٶhK;S^NsfՎHi<;?F?@L nmԎWv^aq2Xދ6 59jloc|кWH}s8gf>Cꃥ~֓[WS6sϿ8o8jЍE8H;NdSՎig7^?r{/?~U22'v)r< "ڑZWg0^e…[Ҏ}.; w'iǐW?UVXbU;v~_`&ҎGՎҎ~,sF{ƪv4նczzcHC>mo)~UJN',lGJ;I#Pc oN8UGO9겭c̒?܁GR"i8)lGFB-ǻ(u]Uw{_7N+A +%'r鱺Pl$>.o*BvP"@AءI(?mٶ͗UfJ~%TPjb VqQvhbx%S> +;8J^4w,_2aǵb;IC@ɣ|Jʠ ɒƵz1ۢKީ|:ߗ'$#$vhҤ%ےY]fوxgSSnR( E/bHOVv%52w@8^dt"[찋NGRD!%JܑV%{KtEH]6}%s -C q^`!&]չC@G>| ~ey_%WB%RW"(}y(˖$ݸ +|1$RN~;> NH[;4gpLtn$vK4$3p_(%3@ vxv.> @. vLhf@ClZ`mT#HA1;$#D UiŽ a`쐬$vP:(9w/" HPOL:sS@ v;Tl:vP8@(IawN%AJ4vx' ^<1;\=;@ /);Rмc"v4A,cv@^V&(A"f.;@ 9;(U]+vPQ:O @ڲp; H+i:Od#vhˎ;7CU Qm;41ˎ?wpTW`? +vxxQZ!`hȨ7f:^ǘ+0JSl+AJ+kFьUCCkɢǯ99ۈqE z#kCn3k׊rQ mO۬U0}ge6aқSxE\vqR#󹤑iO̎.;<]PߋybQ'(KzChG@qӥVG eB1Þld]-Ÿ[lh <6 Ìq#ߊ[l^d 0~(_&";8k(<ʻ` 9b"lr;뀽6c`Yc΂'Ktcxn,PK>p9={}Cv`p/'~7ACM0Vr +)0qGxIr{pNp>Y~_}/bXک_Orzig"2̳adɸ\@9CEr6r홺xI0t%Unf|&L;8XĈ%p2>_qSyؠ1_bl>YsysjJC "nai;{pqp\`>zkc1E-Zfj.l[u~aEyE,wtX+|[g6vZP揑kOʬIIWW̮˘W].k~}ײRCU/0E4HmXܵxÅXH& hd蹃_õb^dq&{Ubppǜwۄ,8Cu6yl{wQi}%'Wv޲FYJ^kApp3 6n4. o[91\Ԓuӫ  mq؎ y9:WGtunM2^[>y1I08s'-;X|xܡ!;vZ|܎'B(D ‚acXDZcF M x39*lڸsh|uvkhԤCrd]n7O,08فð#[c9d |;̙cP:dBL--fɄO"#l}pe;|noBr`K'?0ԯ {FWο=nkjcvt'dM?}6bM678F \w6`nwC~uP2/ikٯWnHj?sn_vGIS?@e斁RU)mnmƯl;ƴo#lI +Gn6l[^cת8UUkO]Iw͉݅=[ݫ;M?WL wv,WйCiB%APS|6;PJd,g لLOafNX( _JGqOl'vol%ㆥ7$Wdvpn2?-͹#X_m/+4*L4P YP0"XB#fAbdyV| hh4f mDd X< ||r! RΟ;}0l5mC\x[6,C#"cO7;45wVYY_Z@cFG]ܐ+ +dgMসg+ȭLNeo^aygS'3 s"FUllV +U %%0INޙ q B9Ayh=QO]}9fv@Q옌c2?HEvPaJ%ED6M;T*J>8j<=&c:!|rl'eA?/>z|'R'9Z $\πKQ0iCR'յ&yWDc+:]1Z:4U3^FdUhWzo7*ek;WN?m|"J+$(^b(R”(1$} 04u-B)C^aS1'7&jc^y~O$@ e(f;HqccJX uZYZ Ro25y'82<Kcu/pɐtk9IďWW##ȃ3ä Y$׵t=H.Wӕ^JpSn1JAɻUJ^*ֻ(g|U1-EI^a`G2~b;j7F  E)T"y ‰q3y y.G{i3;Th dǃ;&iwv5†tbE=.#}ojo5}NQ7Єcu/&?,\RR3;9~[iۇ);8=s{p=mk-nrNᑾiΨq7y!it94P@b5aP%* EV(pۊX֭"|mX;$$&Iљ %k@ÐmH'%nUnY:Gja f}dGcǴfQS#:u*gcy |R<[_^k~\ɟ\Ե}Dby6Z9VCOrv=_^[M%k0:`4\;*\lһrrl]M,Whl,S +DQhX""Y ##GwWlkI0;l'0 f MrCat,PVHKt18tk}u:N⮓<ߙQ䊓BZ1;4Rއg;cZh8LŞߺQ'eVi ZmCd na/P|ւm8h +nJX)ef+j5JƄ3ox 03{Ǐc? $0D3g+[ T]ACXP H<;._>'y +Gpf?5qߚ>?LEZ Ho?4#"8E,t R?GjWt wq:z& zJ3IfD.A@vbם/LۜSMgA> iLܔU~6w&>6k/MD1PD9R*h9(x2Kl.?5+I`h' xI5T|;M;d|.2(8dh^ NɢxNWtIs’W,cCԀ;;^>dfUvdwaG^R_sm;WjIzvk׿n9[ä 7L|vXXolv$-.`Ic=Cv<"e??6޴MvVZVoG+̈́0 +R9B.x3}rn BvpIuHU׽'jb=ݰRGNO{EϑnfvcFCK;iWvL%;~w̎cvd2O%] keEŠZ:Y#[e]N 3ܫAjǽAA$ă6O2 9a2b@cΓ(@/p?}xKCW4IRc*~W74+ىb* )b iON?9LQ\I|C%';IF١ϗUU uyk1WŚ5cHkKYvQ{$9mXv8=vXddx`CaGߨρԚ"l>D"L̉`_SCDRdꚲm5U~h*yהI|MFULD~IAn/>[KrOvP?=6cRBBRPl1]`uy +Np @<$M\c%`*#`糍/8E +Yy޾}tڛۙ}xkۡ7t_{k1)X/>y~bt}„/q=z#:*`w& $3OwIu{³|aiw'k_b :t9sS<,񙍣|"vGXwGƤ)#[]ˉ,jZ5)cfc괆kƟh!n|+w|V`1gKFI_A2 2T bw>YHYucTOޱGzrޓf73W`Z]s^露c\zy۔7w +Gaokݟײ{m`GN@ͯhޘ`R_n\Ӫ9,QE%vP;攣>Gn4Tf Zg6k,ɿbwB vwl>sl:޳(~;mwޮ廻wv-,S?wMmz9V9x%ۏn-Բg]ˎ@a6Gi͛y,ѣ!qyc?ky‹#l;IAީDw&Z%>ii~AW~/.i%P4XOƁ]]w-9{s-1<7LZ3!Տ_XrC;w͹H}b{f7$>]^Д9iܦLctx&4,Wn&LީSϋ33a['+@݁^~( x_""dS|o~l[^p}΍?|)Ct_dOCcEsh)@qnMw (O h0p!`TKQ|&jq--3x|3͸c"c;h;1l#s:?y<@#fUOfkTf˰L&D(e!%|U1=\`r Qt$4]UNSQqZZRQfOFn|>a1~:ȼЙ`5:)=H6 !*ɰ^.*w?v෡m+IlAI<1ֳ0 (=O)u;~ⰤȪQ^۸>_q>8@NloI!1ٹSn #?ŠR`=B +ܡ D1eFAVYxML+qgQU `[EPU ~GcĚ5(P`!n]b ;Π%Q?9Ϣ;!P=҄5*P~Z̀4x-!X߁mDxkXw}Dbw `zq;bSSCnNچD!,.]Cyw؞`o[^;}so`S~ wKj;E +nCpGyٙ+n\t/V\GbwOVLtfR8_Ru­ꪆO+.A…%|,]1f\{7$:1wv]0w(ⅲ#v˷9Lx*"xv;*++ h#3Ը/pYq ^(;wT~ZN oJr\ʎm2s\U<((@5ǟ^0 #bZ;eLrGup%.#Fa +zpEL?5 CWL$Mk&)b +sfm7)Ms8;}'y+4q\=wH +ffY Tׂכ;č1Qs\Ċܡ6Ai50"܁,$;";m%q l B*rGC;Ԣ"wHC,yְ,hwȗcw>.!4=]0(O۬ܡ Kݡfz&6rnjZ)5wH!ʐ!,w'o;w 7>.ELVb?#gsyPbqܾ}[~M\n;CЕ;," 3l;ljcs{c`uP[A%07zFh[S.BqX䘼 +CJ$L9u yC;$Rܡ Z]]M!49 ;(KsóC 4"awhN~f>D0J ܡX?D~S+~RA 9˚,p2wH,vlָݡwGPgЛ;tpXMw8~w;\{¿ xwp 8#|P\CgEApmCsns; t.%;uG\\)7g248/8&c11{g>4 =XL;lxf.sgМ 䝜A%RUW5 +w\|ƍuuuwM_id^;~Fq|ΎMd+`$1L,75!`4`e UU/~hR*Uj? hh( DAMԤ8Qg3ow YݲݝO_q;>A' qxl̻LgwDNwn̐,TA_/TkqW8A|<W׬$059DrGi7dFHÒAOrV>py +f4?-P\ސ-`GHK}΢ +ZTp0&/jy߿i>0;T.yrY#ؾ Թ!u7Y7DyAUˣvNw4˂xi0䡪 jehEeMw M!ϓw$I%cZW{T$l#d7w;(wBRyTey{@gɩ;iu{`7w5C+ y0\ܡ ׺w0Pl;B^#C[~w(vMLeihޡʫd'Dqwh?2Swd(_EAޖgw XE;T߻yk;;FQq;;3 wC9c5Q#tɨ;tq)8/- yD;8Kwhm;TuWՔ܁ƆzXԃZ0)a,nd-{Sa!sYtR]Op +w; Oݖ<]qCz&^;8};vhVh'qNl)չ!a8)}] 8 )C^`pC(J6r0~>w<q Rw i6oѵj^DŽ[ 䎰3R~:)[RwoiĊ5 +K %k ^,[A}$ĥjXTM0w +C]I eIeZК%;1.-$p(GF)owD! nvG";uGuZ88KH$w<]پ;̓Bp (ؾ,~unu\ c.-@pDpp{݁3,N:4`#JwO"#F1q EVW @w;0J\7w .aU_%Q #8x'Ϲc׮}@,0;N=HV9wP>wD;#QɼC ege';p.ul'*WPazpd9Vdv5G7vPtP#h% hatw0j8GOu̸- aV7՞:;HA +p+h>-wNwP5_a+C>  ;tNgd:{ +HZr(]@Y uՀQ3tZ?U +$,C:7Hå\`=_0‘F+(EYp ~v0/`nWNBgeoG0;8;VΧZۿAE<ִd2ny˄m9խ׺'UNiPJM۸ukW/!`oZR0xe%xZhW}#*w&}or +}@NN7=J'(9t<?ƴ&ʍ{o/wR$$dG +DȌY՝7so.yLy]? d7RVL}B2v">* ]cZߨپ~a\ӱi^Ǧ9KnqvuޝUp}FǕ~)x5I3/,ٺ>[gX\\dd @" D#$ Hnu|t:uڲvl]X;T-*Aj 71 2w>2{ _vl" @>P$Hv +wpP8&.B;֋55C} _CaCBw!Ё0Y{aͭ7_1ϊ@7e/:Ǽj/*?/<'IR빔z΀(΀8! z'3ƀ8Ezg`aZ[7;d pGc~*uSH-llthF C3,Brx[,+w=/fŝ_xn Ih[#L@ |g„W2){Yw u9\a^̳?Ԇ+$Id (͈ (рVP c" z' I 5[Rle hu"]^G{z%y5/x'kXErG|V*Ԋ&USN Ezׇ jÙKow P3r$~雱Xa kC~cI8{S~$P^bjX)HIZk@hEqa\p7 rL6䉖' V; ݸIJ#V"u +Zi(oa{V=c.- L 8;$!L!pjC"c2w`(0pP]2@50=_U{L}لbƆoυU/&N + pjF7%*LT :6>AQ>GPt ؃*r.HJQP1RJ~I`;eդeYt&{Y6Ķ[6YMdNX_@X~ZЁ1CȾC$}D66un=@yW fDf0aqU%I&A?R]7PҥN}lK}+a~\){Ywfu?w}dKЇ Npe0H;/Pusc[ rG8%4 ܈lMa׼VDF·Sy㱒L^;}oN{M>]uYRUfUZv$YTk[c{6E8;>P7Njs7BTS 0j {8`ot + <}d(Pu >vq(upT}i +8~E0lM7Z jkk["&&fFjW[,P7 c[ak ЀܛTk_j<9ǛL,isp8h/b7g6~ZUe㋘y" 6}m֞TC%FOQmܱ!p(HClyڭY(Hpj80/;JWltCho/6 E}"|H]DMu;a;T2Ha8B;  Y8p/e{ky]O>}u|x},,jFO]SBO71dob;CN>92L ʣvMlp/z_˲]+Ní;8WWT70ewofqw!̄%| ŗYI\w9y֚_K.qs`6n>6DOGE}9<*PyOvK΄r;{:Xt&_nQz;yP ZQsu|\yut J;`C;vlzP:1D9p巊o'gU@~KKv) ǐg~B~=vXuyhpԎT2> wVCEq/^ S'M.?3rU;I= +BE7 +pvdA׳FGv?S,kq 3,IՄzäDž5&ǫ?# C'zѻQxn lO:QYXзU~г͙̔нgYSC59~[bZa AaE'+r%/abT^@^N׮?GoO$ޙL)fԋq\v^Mo 閮E-wJg"|pпU6xw +U]C3xǹW2ݺq7էŁ"<%NRv'E4iDȉ~ѺI"ivL%# 'm.\ئߣD5DLN6:/ pNpd/rN +endstream +endobj +601 0 obj +<< +/Type /ExtGState +/SA false +/SM 0.02 +/OP false +/op false +/OPM 1 +/BG2 /Default +/UCR2 /Default +/TR2 /Default +>> +endobj +602 0 obj +[/ICCBased 603 0 R] +endobj +603 0 obj +<< +/N 3 +/Alternate /DeviceRGB +/Length 2575 +/Filter /FlateDecode +>> +stream +HyTSwoɞc [5laQIBHADED2mtFOE.c}08׎8GNg9w߽'0 ֠Jb  + 2y.-;!KZ ^i"L0- @8(r;q7Ly&Qq4j|9 +V)gB0iW8#8wթ8_٥ʨQQj@&A)/g>'Kt;\ ӥ$պFZUn(4T%)뫔0C&Zi8bxEB;Pӓ̹A om?W= +x-[0}y)7ta>jT7@tܛ`q2ʀ&6ZLĄ?_yxg)˔zçLU*uSkSeO4?׸c. R ߁-25 S>ӣVd`rn~Y&+`;A4 A9=-tl`;~p Gp| [`L`< "A YA+Cb(R,*T2B- +ꇆnQt}MA0alSx k&^>0|>_',G!"F$H:R!zFQd?r 9\A&G rQ hE]a4zBgE#H *B=0HIpp0MxJ$D1D, VĭKĻYdE"EI2EBGt4MzNr!YK ?%_&#(0J:EAiQ(()ӔWT6U@P+!~mD eԴ!hӦh/']B/ҏӿ?a0nhF!X8܌kc&5S6lIa2cKMA!E#ƒdV(kel }}Cq9 +N')].uJr + wG xR^[oƜchg`>b$*~ :Eb~,m,-ݖ,Y¬*6X[ݱF=3뭷Y~dó ti zf6~`{v.Ng#{}}jc1X6fm;'_9 r:8q:˜O:ϸ8uJqnv=MmR 4 +n3ܣkGݯz=[==<=GTB(/S,]6*-W:#7*e^YDY}UjAyT`#D="b{ų+ʯ:!kJ4Gmt}uC%K7YVfFY .=b?SƕƩȺy چ k5%4m7lqlioZlG+Zz͹mzy]?uuw|"űNwW&e֥ﺱ*|j5kyݭǯg^ykEklD_p߶7Dmo꿻1ml{Mś nLl<9O[$h՛BdҞ@iءG&vVǥ8nRĩ7u\ЭD-u`ֲK³8%yhYѹJº;.! +zpg_XQKFAǿ=ȼ:ɹ8ʷ6˶5̵5͵6ζ7ϸ9к<Ѿ?DINU\dlvۀ܊ݖޢ)߯6DScs 2F[p(@Xr4Pm8Ww)Km +endstream +endobj +598 0 obj << +/D [596 0 R /XYZ 109.858 727.97 null] +>> endobj +573 0 obj << +/D [596 0 R /XYZ 109.858 651.313 null] +>> endobj +46 0 obj << +/D [596 0 R /XYZ 109.858 648.56 null] +>> endobj +574 0 obj << +/D [596 0 R /XYZ 109.858 205.556 null] +>> endobj +595 0 obj << +/Font << /F29 416 0 R /F14 372 0 R /F8 369 0 R /F28 380 0 R >> +/XObject << /Im5 593 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +607 0 obj << +/Length 512 +/Filter /FlateDecode +>> +stream +xڍTn0+xb/]AZ +$9xQlVHv}l؍!{DZcQGpCAhKR0b->GL8Ÿ{$E%':|)(Z5TIg+ĔpP[H767Ŵ1ĜA#ICJeawU_Ca_=Hjyo٪ZRH"-_SԹ3C$B;D1۾y,rМU0#DvZ7P"Pįn,7O01 Ax>Dr3[?P>34] {i\SLI%yc ڏ5}tpS[fMD8Zp],;r%\ ׇɻI_x@> endobj +594 0 obj << +/Type /XObject +/Subtype /Form +/FormType 1 +/PTEX.FileName (ss_stripes.pdf) +/PTEX.PageNumber 1 +/PTEX.InfoDict 611 0 R +/Matrix [1.00000000 0.00000000 0.00000000 1.00000000 0.00000000 0.00000000] +/BBox [0.00000000 0.00000000 320.00000000 256.00000000] +/Resources << +/ProcSet [ /PDF /ImageC ] +/XObject << +/Im1 612 0 R +>>/ExtGState << +/GS1 613 0 R +>>/ColorSpace << +/Cs6 614 0 R +>>>> +/Length 89 +/Filter /FlateDecode +>> +stream +H*2TT230V0253S0630TqM-R݃ ҋ +*,-  ă˥k{. +endstream +endobj +611 0 obj +<< +/CreationDate (D:20030406193457-04'00') +/ModDate (D:20030406193457-04'00') +/Producer (Acrobat Distiller 5.0.5 \(Windows\)) +/Creator (Corel PHOTO-PAINT 10) +/Title (ss_stripes.eps) +>> +endobj +612 0 obj +<< +/Type /XObject +/Subtype /Image +/Width 532 +/Height 426 +/BitsPerComponent 8 +/ColorSpace 614 0 R +/Length 25743 +/Filter /FlateDecode +>> +stream +H]k`S(J?ie${eC^r;\HI}U +)-.qIJPBpE~ò#'m[16u+'s:G;3swٙgDy= "Ͻm?pabe!EQ xeaj!;N|S+Ĝ>GV w|wfk7~<>O= Xv7a hF"ee_j3?43ף[uw|>mݻG -}Bngw ;JRyAaJ=ɗcF׳O?."7] >;J̩{kiG|51;ѹx0AQ +1C(wTt`ʍ8zS (XR#&(y3Xg5V); +ֹ,`ڑt**E%ЛU(7 +7+=Ӹ uH^˘Y[cƕjƻpƩy@Tu.}zR5v+`}@ޑ)$#;R+S+dE:3=̔-fw¡xbkzMHV1b#Mx_ޡaCc p𾃟Ŏc;,PKR 2vlz3z*eLˊ=>ⲽ#FvN]x7~ݶ=R= ^k6wg l y "MQw_R/7wC E5 +v@2}?gL"KR f 6#gCJQIx}e;.m_1m}peK ;U`!ۇw`^0/ ii5o [^{82+/+=#ֶ!6l%z~i^Ln{w Tkv5^(;+l(͂/:.cq06Jh#z06P;YpcPx;|^wKұo{Cc;w6ʚH~1Q;C_r~wSd#(*{7v*exG{/(C ;v_-'mGU! ";nLAD=v.x}A "+6NDRDl +lޱRzlA yf&J wH2@A̩c lwHVcO36vH.0(=HLA͹ia =8A0( +mLAIF ;A{p`g V"Z#R kW!Wo#zoK/(fDƦmJhc<u6NoJOL tz0}JY b˺,Ad{ `>M/Su)ZwI` +3-)r;+a7#_#Y,ʰ|[l5`oq!` 0&++6`%ɻ8oOQj91e𥱟!z whRQܴQV㈼J n]ˢ+O.]`R[* REy$zRz,<wwh`hђ{xg+ +l46v- JQ zRۋzd ʡ\RT*j$ˆf+?kK +CѨ @fȴm1wHRwXd@ {CW!/ Xppt*#' {q nwYitҳPQߛxIKW)Y! zG^d17lb<^ +l9 +=Ħţ@W dowh`hђ{Gsn \`+|1Fb[}{GaX1l.ź[s*h@6& zf0yGըbݭ#UN26Iw45^0zG$rrW)NR  :[26 >wr1Q!>&Vf h]R@{G;ɢ 6Y.(J}h!rATdn2`3k0YsgLڒg.FbMC97mMKqq(@'a8@/2*bp/0:( lmr)l=8jK5å`KBLA:4E\ z}`TFQԧRs=B8wƳ~q8[r9;$Ѩx TVE\A}P"dzV }S8^L xU;$wZhQ-F$`e*bxAlعNvr;$vI~7#_'i/QȻbjdRQs.J֊I2[whzGsnJZl8PR`瘼@zw#la/=yV+-;10ЧPpC^k@7Ȟ@wx;ŘF25yixFNNdo?;߅,^51a`1ܘ/ũ(󣇳ǎ5|W><7q~\Y;c~l}<Ʃk-)HNǍ;4yG^͹i ;v [~޷O~&s}q|bdً7]G`5W.ͣh;rXQ2NM~Wߒa5i1 թYl# YʒZrOf``o3cltınd }\IC6{_0ΔhkƱncEn>XyrdXM>qܿwy~⼣c5Y({ߎ/):7Mh1q +qcȭ;JwpGw0XOn2}z#tB;$Ka Thk,5҉;k<7ygǎ*8$`+//xqyC;yFrv,@3_} Oμ,\vk7^|K{ї&b>alBiXM;xr-Y޻{# ey{.JᴿLxlw 8߾,d;==_n,et ?.Ll,;4jrZS4?]2UځֶwD0da\_ws|O>}ۇ_/7,jcjcZy_ڳM-}Gzg?ԟ_}_:!ʖpgs(G2d?~Gn"kUDcˊ<ύR\<ٰC&m^t\b=\[L|H0_vʇL+/Qmc1ގx2bf"Fdnh$q1G|}&OԎf8eTNCMF mdK;.A;Ҷ45XGpL=kGd"Ŷ#2ƭrW. o=ikε#nj8ZH;,hϟע=vמҮ=G 4ܵ?g73}*+=\p?>p2˷BuYx:{`R?'WYX.MUځֶwDXY\|408pЅҰ;:wlэ^ Wx-I;25^9pgƵsӗ&Oaۇ_rҎl>Uxkũgόߜ9/WJq}^:r)Ǟrl-mcj0xT׎KS +aAz /aAB=Whϟע=i6ہvma;kO{Tum,"Uځڷ{^ځ@Ku(гEjlG`(-pOڴc}3Gͯ|'1MvȻEV!Ҏ!:ڴZ`Ec f2ٴ]x*ZF p2ӕ턹^'qi|-ځv4ot>ϖ:+yGU?-Qׯ僞u2C\nv {ij;O`ϟl<9J>~x%̄;Aě:@v UhGǏvyNf4 ++![ +vN:h#s;w 5dnAB:24B;v+[1D; + +oǎ2س Vvlv0\@;\@;\@;`72A;  + +iUpv};v<POB; + + +v lcj0xv!\)Azcje W +i. vNp;W6$Ꞵo`#@uPʋێ;h4ҎJh$B7H0@;k|՛*W +iG]?k0HmzPJQH% tU;hB;v+>qЏG~uu)f8/L;X;Vm2(7@QA;ˍ_=cbyhK;buM/W?b[w@ڵC6Vwێt_AlG>[;Pȼ2Pȼ#zj/ۘ\?+f-+Ct[Fv^3﨧Wh?K;^VѷCsydM2yde-iEWhpeK;}#Fݷ$w'9hbߎ]ݰ1u7÷vv+Ŷop{'u7ݷcp{ab?Wc K~v+vldg; /y?pvh7hKbgCWv@B; ox;h4hv +@Tڴcj0H;Z*Pɥ&v@[wY*PlG+4I|PI8ʰzfKBtus;\`(I;@s;j[pہ6PÛܾYÐ-I;@H}Wo6BT; &ԝՍGrrixnm8%X;V!ԍ=-K;:$its;B;,ځfi4K;@vY*Phv +@ThB;,ځfi4K;@vY*EC^>,H$ò AWc+c1!em>d$6b)ܒzNLH;@ElGMN;P'0Q5FԌH쉪TzlC'hG-60?jIq9C@`$2" d#N%qI~B^0BHH$|` AH|P\8sbHq%5;}NSkժ}9XlkWUWWw˯Q[2pHtǕ lq\GE~r'pHvǕMWO N?pHr1 $wwvA؁;@2;bHرc#PFA_L-GODR2Kwר! $Co;\Am-XAW;p$3r闘qUˆ g lqȉ~E_~٭F3c'}~qSv쎷zϝ!3O?8Սp  a0Qo::7'ݓ>,:kq=Lj;@2;F:3w +* p0q&庺c)BPYOw@&TrG|\;~((# UU_s:TTvGLI}+c5~Y6kgBap`G㎀>Xrԩs̙3"Ee٨5pDBPRm+twlllȭG]Wn]1%p#[{qa QQ}tsr`38Tݱ쪏eHw+/jܱLFv1,H߆ ܑY"w,4N:uܹK.u3g_KeٯlKeq ;@e`w8MWƾá>MG]#f9c:;+c0kdcpdj;gw9;Q"ݍF Sw +*p ;@;6; * p0;@cw2pMQgYDp ;@;;ڂ;@emSX4;@;b5^JWh-wwʪݡ&v>jdK*p ;@eh aƾ,;sHڡw |w<7GՃ;ڂ;@%Ꭳ;{1dP)_;-"wwԏqf3Ǫ瓜FAU"Y;-m7=vvGAѓs q(7ubݗ˲qv1otz]lq2_Eи +ub0kM5y4P.K3XfP2Iv!vu0SrQ6'[V㥙@2]>J!̚tGAGc2Nz#ֽ;g7.U&cc =ߦ;6`Œ<Ѯ1&fkl%gVji`Oƞa`?xkd}N|w؉:6V 3ѩ9-LrnJk4ZA^HPN.,+].M q; v32ߥ\VCV+5wjbܱ(AX"P}:5 +Nm1gݱ4VN|w1-36({i  fTpwGUUIaÃ1CN8v p 5wtk  V{q5/+WFv fmm;:3aT5-aAƫ,)>R#g d w䥭V9E96)3;⎉ Y_}FuP1F0ɟN jll^˒s+UsԞ, 2%Y˘@\2&ə?c#H6ג\92;#鎠}#s߱npZc䐜c&9CWTjd{eOhf+VvON۞}u44dVin&GAm鎥&ߵ- :L&CaԨ{qi2o} 3v {>soR+3ewȉhK;~Asg/rN259r2 c^oB|0ħg0; tt!oRm$Ow:ecFOb9c#룦܂7kzƉ?a3㎛,w<"w-~Px/0Njںc0ƵbM.StqFn )w\(;#7ݮteW˂lٔ3Puː=;U;5 +<*3C[1wwT=L,#MȝEs0Pч4k)%# 3E9kPt*p'?;r+wCC%V;d9; $k wݱ$pPkMz"hKwԙd;jh@7wA}G,v"rL:X@ +Pea|wF$'>d?"+gu;`\Fs#r>pܑ_i%9hK;wH)w}4aTJGS;2ewwK(wwJYwBaLwRRjOTjl5NhVvAkø#?:tʕ}w@;XXb;n|vX:qݗlGH$-5DF s#>(!w%ꎣ/T; ڦwwQuꮗ=/]+%D"Xdn?_ݶGwֳWo WS~qk;nvͯmS뎕F/_s'^xz[\WwaT||;W"a7hST~?7߫_{:vԅ{߭~+4q[_㫋0oV~x}Or5N=ڳ~N|xW}_qݫw_^Pnx?z7~5ugqTea@PyA@(SEAuŵ`?:3vwf8QTZm>fm+I P ^ɞ/\yɖt$gswϹ|~gt_vtI趲jf +a[<Qlԡb^+5T"UV*Xs)担]_/^u^c&\_wޘǽ>Ɯ61zﴫکnHTj|`s! j.ͻX`_?6bg[NwX͘b_'S꥚Zge%/`n, | +E^"-B @'aJfImD+IZ$b!'_ͼGcOcoc_cҦ% >^\86h lMY7`G+Ǝi3̰5$;JG+؄Ռa/ǴVY|V<(+U,S 3gлb}K]܏5WbU?yaV +C9!œ Qvx8[]Ĕu Xmۼ;#8xX +faapca(v`[;H| XźPcAAc6ezcu8bD9d=}=AuW7bF'RrLbL]L#Ӕo* +NxDQ +=41S+#r =բA"eH2Rޯbǣ~Ö Iv,;@z7jBtezMatT(v6#dz 8#;0 +K0O^Tlw~"K1:vd97t=/S*99S K d&7C +ʇ ʅPt.-CvX97o`yB"_lx2`Ap:EkVz2sVMO*(WP%cKR{UOp7]9>d Iq.x8~A,[ NKHKKmQ@jZiè쵈P Q",b(;T{CvZ9 X8;Xv7j`;55XM AQc8,§dʆp_;ԇ(;g.55V#+8OQBE-}~2>S@;O*s󏃌Z]ڐLͥ7V_r\Iz!!Ye(*YK )QFjwjVᾏp ; +`T#xJ x4vLY +8BdG,M;YI8Z^At׻1 jAA?a_*vXpKCI^,ۉ H +23W:X68#[Qv T!7N=JtJԯ"Oŧa8!k=żBA{ޱ f [%SmWTG#D_هj<WE'<* rmuĉ  A+ܰL5^Z&ȔUlgP߾J!{Rƹ^ yMĎ jC?Z7B7̌XČklu;Ɏ vz!#S asx +z Y~T ;6%b]yO 艚)֕U_ImLm RP9#{1T.j~cxG=<6hhԆJ3?pʪi)ʔwUYGG (5xһx\5}_y<#|* +s7K%aF 0$(+T3E'KV#ߓ j_4Y,G)M\ٖy :Gx;daO>;Q}Gi3JkTA,h&ّݍb ǎez8 +"erP>f<ݻvۥ?A^2BQ>5E_0^Eqj +ct?S58tqZc[u_QM\iZO=m5(RlQQ*|@!@ y(.*XzʱUO{ĵ帴V֭*.@Ƀ<$w3ab{~ιso 'PLKoBs/:.8q~{Ou_} tnn~7zX}ԥa?ıKCɍ%h?ǰbRP@!WE ]əiTrv.QNYv: +:=TQ-RgnTIT<9F<|.t3q,y_ͮ^:;4!w,;/,w5q X.b Ɋyunjc0~3&D,JCӄ; +88ڲ-ށ_e=w[lL_8EiI koܪN823hى1[uы9%½蕶}΋70~nKXF?{L)tTۉfʶ2 8x)dEdA*d݄.'"<2ۈ9$/t)ݮ76  E&7Z3Z%Rei!$ \?GS\Z׻ t~/Ipx>aSvG`AHG'#ݡE6#L^uڀӒpt?Qn^f;pu7USOF^#s`g x5^FUUV`9G +1<ÀNx)y/7Q[JTH>!|2 /~aBM&\db{A͠ANe R`A-5Śxt٢F0{_傹 EN-̸u;! +7 8Q]_&Fk5,qNXofH`|j\)ꁢ/[@xYl1p xBeY;߲3p>((UgrX̖/̐zĐ!q%, ;LbT^N +LO"%GJ{`; CndvA;Œ}ڂDMn ^Zش̗ [B=痿eAuGmGꎎ޶dIeQNv؊V7Y!#q| EbB0H qFv f8roU]̞>0[nլ ,mȟ Ąa ` 8]I*;GVf=è]T }ɀ"( ۿ@?̰e?QD $? i)zba +nJGvr P +tRf1.((c->H>}-(86 +W!72;H;aڏfRFDp>~}R{^a,ܳ1uCl);xf>2վrmXbk%@U܁pզ䁳¯Qa'TAJ^2 '5;,H{bGfw~U+F-RgDCqI. T&QW*|Z"-ap6W0[X=,YmVb1j,ƢDk>= Ҡpc!Ubu;ceM$' Y RPqT4( Gs oi[b%vlο:W i?[w($][,$j{4њ*# O V&ny7]2 AcQNw<鎉k;l1! ء|zQZ8l.;v7TT^0Tv7HAΧ*PΏ-bQ?%p/.U ӺD)<~Mc!Dh/uE飏+Kt;JmmaCɋ"UR!.YGˆs䉷 q,ri0LrvTp;\#w4!pDuPl8.)IGJ'RP@~XX0"dLջmϊJni_7\;6ArpGauOkPvXA*>RƭR&Q~(V%p[Y^JeHQE~Q[S5 +k.rC,^ؔ!L `f{?dh8yVO5[AtUKD`@>!V7"V6`A@Q[s}Nkض`tp_8}gw<|2lA[c.?H@}]N8IhG&ĵMVBPX/Sh@T-d22Q!PƵWj~نFڂ+`%)Gjl)BK,Ȯ%]ba[FXhqLjILE #iF7m3o|;ν39/sϜuy/}`dP#=Rޱmlۣtdf˾ٺ_?>pJ,`ڗ{y5/>q^5 Yǿpk^X~Nk^t #職*P\@[AZpy ;T*H=__| +¾ +׫mO< [p8,I=e+JW7KX1۸wT?=*w>$$oV5?Tٚ`M:, +7W(UTWJ8׾=w;mlAj0YwT\d\{Oum*2´]g]{:;>qXCǏrz~VVZmVB^~Z;Pw;hN*nډCݿҞ;;aѢpy#w>P3=)ضU5FLo9N_/4\y=80(J/p,PYUCG6i;^{usG4K+ Ti;SH9(y XQ u5;.EhNS|͉Ʌ&%H2w$H8w pU%lpX1;h;;tB8y+ӓEߡߘe1A¹.cI*d;P޻t5ӓBHyǶX#?h.L.豃=vӧ`} ٤KOuަ/? 6ȍ aA1;@;}R%,:љ9FvaYw$\i[r٧-w;P:Pwt`G9w+=mKV;2#v +;CZN%>>TyxthZZ6(ϕ%2݂Pp˼$t>^5@=(@D[U%ܡX.W;qq@M-o$nc@V BGB*X KwF,QBW̆b-`pyG};m{u88M%鐢98_xyl<= h:1\,,դN4;6!(b};݈6v[ඈfn`X"*5XkT 玠;46*wx@ϕrtmD"6\3m?f }c$yؿd#?^En2j4i+ ';/IȐ>VCpXG0XJmip;*+jVbv;vL A_,s;6hs^5f_> +Ӄ8?bGA'=U4C)n)ow7?m؟;&CAnd-sL"=Nr,jAV}}YbFn""E8ޜHd~(A@cl + B(&hX6}(J+z\MTߐVw;4>ut/wqmeK/׿O;Jm4yop#ϕtmL1 >y8]1^0;ҭ[Sxr hbఊew>x|q'W_jU$R|-o$nd" nܸQ 1j( XܡTZA#YwDJO/?PO&QBs@YeQ"<&TO_o]``G9w+=mK;ظ#72sG$Oy4Akޡp?Wzږ8w8,1\1cɟodVpXi;(M`U5lK݌5yS}lRϥ=uƔ/?w;q. ^+;q?zgǮ OO0F ܑ A*DX[C;7<8ߝH|GѻEQjwtgљ9t… Uh:]Mhc̓;AÑ~4yGiQ8;عTD#p8RN w?3 +%>8w |͉ɅGpp(SsGЀ;y+ӓG0Z.{"who\ C(0X~xz*wv"6FPviqGnd -$W#鹜L?뎤ߚwGU)wGCsGЈLVC'tG&amɣS6';yXYtG{9qk@#h@sgnN\qwm9&d=^0ۛĿB5 +d.Gp?lNHyJa_٬l8M_@oVȑ=@#h@<{Ưf{Gj|x >MU W\}BTN~؜߫RW6+X#72ĺ]_T3pSb ХC%;7<8~:6Yֆ)KGh++K{5kviuo.`eoN>:asoeH+}eROW!uEW!~Zm=aW6n܀0HYaFwpR5#;+^aǯ]= (.LV6^Y?fNd?-pWqU=ssG#<t3. ;10 Vr:]D1ZӠѵ+Zj4h}ĪAT(ciӿi2d6V(ň(D <w,}{˽};g={9 Sq$Oqj6P|Fnp*Hy`ɵ!'/T9I%Ԉ-*C;x0=yw}zm(,?duyG̼npV^r~Qŕg((3hkwPƓ#hj0b6u,[rwUǽWw_#4_' +JYŖz U|Zռ5j(0f Gf^M`AFpW|~FwKhn{zsSzZީW셣wSdc^`ukQ$_@om~?_*$ 2;.S0qGsy1I}n P HZB|9);,JX]UNwg0`I:^A@ GAwKI݁@`p; ly݁ ҁ@w G;AC-ZdQYvGoWwRm8. ?H8bB'?pշ&{ܚ^ߑAA˶lc3OLȲO:>!x|ֿO{}Gϧs^Le-×H;@䯦{IP~ "H(`s#ߘպWZo9-ujN9=Jmc6?ݲ˺HCf~|͢ɵSkYkͨ͞^lWϚ\ӧ-wmO\NIwt,8Mq>_ fvq?wvJN};iWw7{vLz7~Go\^ܞM w o3Wؾe-/iYڲ!憤ZoNh[1gmKn/2?r2i C쎧 ++;ݠ>`)S%Sޕ; D;?$6$? cRJGJ,(N +|eS}%>?Cr*ɭ5/01)L`םԝ ӷwo;Ǒnw'?iw7ި햌 PW81[@A,DxV;Lk2u0vjD3U(iyc .(Xvwwﳿg7vCuw::Wr֚ +s^%o%/ªs{{{⫶f77NccC7f K["&zvA$5$IB'"Jl1ǜcqAevMytk#ԟ|x+3XLum;?s덣^”*.vsGO_ i u8IO$Jz~"=JDV05cOWP_TLO2Liz<HN*Sn9?4X Y b;t[6M=7;{s=a>ӱ c쐷84QavzR'ch4$!#. +E;+A1zbzcn[/uDž&+m{?^?{7Q6vApK&n'J$Iҳ *bPnj5WKv2sY1sóIb=PQE='I@о~qWV8RQ<ݪ]O;lkqh=q/݊{r1v&Q]DK9a&2^W|2]d@ H!Aг VLc7>v 3 aU=.a$M&b$I)}Ҁ< jUw7yEm{1Έ+$&d@zGz7YwI<0Ki-MoѶp'8Rؒo PCǪ6"cP9a!z|@hj4Iq~;|1[ +rO!/}w Pû{=GcRĄ%ux x$I7RISP^VdJ=J="D5p zNhM +k8jna|-Hb&U?VYKtY*]fթ(P#vgKYHS>D[ާV<7";d-[1;Ts$4 ^ r'S m띕|W~ tORsyAẢR1jD qv͎j⡒$I +Z$g?2rP)J؏bPt- +ۃw*ί-Cȷf}-`Hb&]顖$Ñ6Ffv];o|% $I +cT (G\;|6 C1{QT V+Q`/EKВbW ?Ne 0^e3Tʉ?:3߸.$IBAڰ?5s9A1ldcK׋eN6]\ݼ0霃L } ̺$Vljlu:֥0Fq+ɿ +HYq#yʼn pZpƎtU`L_ gTxX'g,86Ϥ@كV\a;L ã$I$M)k/1.yKG{Ѻ +6\ǼQ®,b_/ddh0(T dA}^_`s֙ +SV])A*u*Z1vM+;"ID]Hķh084 c._N4e堦&zLpLPpWGDSCB +08.~䑸W$I*+ZT=}ȗW|;\DVelX)R1"6]U4(nY|WlO&SXwqvXCb27o%M9]ÜH nO]u\M y fDz> V_ v&R:p ȵpa(@#BfJHc#!i8~X6 A@RJi<"(dcLFF\1q,Y-/6LH}Hxh/ R:fs=v#v.+OUOAWPt s<#;Jw%׻N/]enlScq~YlܗA+(>KyYO 'Jsx{nv8ۖ <>8mo49am +P(cGa-IȋQVq8vv[l9J +BC$xBaC djۅ}poOwfz}BG|YH@;{ ьԻ@b+Ƶb)v>=7C;tܴ;fK +急:R`4'&L3!O]2zfp8"ޤ3>t1$0PEE3̃ާifp_4$v>eB"(7@V`  +FT2ѽWkv(.آ*8 ք8fm@>vKF> +endobj +614 0 obj +[/ICCBased 615 0 R] +endobj +615 0 obj +<< +/N 3 +/Alternate /DeviceRGB +/Length 2575 +/Filter /FlateDecode +>> +stream +HyTSwoɞc [5laQIBHADED2mtFOE.c}08׎8GNg9w߽'0 ֠Jb  + 2y.-;!KZ ^i"L0- @8(r;q7Ly&Qq4j|9 +V)gB0iW8#8wթ8_٥ʨQQj@&A)/g>'Kt;\ ӥ$պFZUn(4T%)뫔0C&Zi8bxEB;Pӓ̹A om?W= +x-[0}y)7ta>jT7@tܛ`q2ʀ&6ZLĄ?_yxg)˔zçLU*uSkSeO4?׸c. R ߁-25 S>ӣVd`rn~Y&+`;A4 A9=-tl`;~p Gp| [`L`< "A YA+Cb(R,*T2B- +ꇆnQt}MA0alSx k&^>0|>_',G!"F$H:R!zFQd?r 9\A&G rQ hE]a4zBgE#H *B=0HIpp0MxJ$D1D, VĭKĻYdE"EI2EBGt4MzNr!YK ?%_&#(0J:EAiQ(()ӔWT6U@P+!~mD eԴ!hӦh/']B/ҏӿ?a0nhF!X8܌kc&5S6lIa2cKMA!E#ƒdV(kel }}Cq9 +N')].uJr + wG xR^[oƜchg`>b$*~ :Eb~,m,-ݖ,Y¬*6X[ݱF=3뭷Y~dó ti zf6~`{v.Ng#{}}jc1X6fm;'_9 r:8q:˜O:ϸ8uJqnv=MmR 4 +n3ܣkGݯz=[==<=GTB(/S,]6*-W:#7*e^YDY}UjAyT`#D="b{ų+ʯ:!kJ4Gmt}uC%K7YVfFY .=b?SƕƩȺy چ k5%4m7lqlioZlG+Zz͹mzy]?uuw|"űNwW&e֥ﺱ*|j5kyݭǯg^ykEklD_p߶7Dmo꿻1ml{Mś nLl<9O[$h՛BdҞ@iءG&vVǥ8nRĩ7u\ЭD-u`ֲK³8%yhYѹJº;.! +zpg_XQKFAǿ=ȼ:ɹ8ʷ6˶5̵5͵6ζ7ϸ9к<Ѿ?DINU\dlvۀ܊ݖޢ)߯6DScs 2F[p(@Xr4Pm8Ww)Km +endstream +endobj +604 0 obj << +/Type /XObject +/Subtype /Form +/FormType 1 +/PTEX.FileName (ss_aluminum.pdf) +/PTEX.PageNumber 1 +/PTEX.InfoDict 616 0 R +/Matrix [1.00000000 0.00000000 0.00000000 1.00000000 0.00000000 0.00000000] +/BBox [0.00000000 0.00000000 316.80001800 252.60000600] +/Resources << +/XObject << +/Im1 617 0 R +>>/ProcSet [ /PDF /ImageC ] +/ExtGState << +/GS1 618 0 R +>>>> +/Length 67 +/Filter /FlateDecode +>> +stream +Hw6TH/*2643P0B#S#=S P@a 3\.}\C|@.j +endstream +endobj +616 0 obj +<< +/ModDate (D:20040529162831-04'00') +/CreationDate (D:20040529162750-04'00') +/Title (ss_aluminum.eps) +/Creator (Adobe Photoshop Version 8.0x118) +/Producer (Acrobat Distiller 6.0.1 \(Windows\)) +>> +endobj +617 0 obj +<< +/Length 41431 +/Filter /FlateDecode +/Width 528 +/Height 421 +/BitsPerComponent 8 +/ColorSpace /DeviceRGB +/Type /XObject +/Subtype /Image +/Metadata 619 0 R +>> +stream +HgTs$*ĒT]) .E)3JU@쮈 H,dy:3L=2{{}λoaFD"֚5k֬Yqn.0 `1_aِߝȾpȉ~< +SA4)#4uִJwt=Gݠ14GB8 +΄tV?9=$B:es:N;Up֎[;M b !~Dp㤋/(NiqeLųMN2UNj3qҬfEa W?K\3kFqNǑ\h~9Z\ cλ)7nyNuqm>DŽ p!9"pċ4N/:.NnǥpT Eٕ8zyDaFGfwlyfǬκZ<5fw(y:2\^pcMo~"-=߀[7^P?[w>s}߾ 9:)67x'n.{a < LP<8#xh0| <24ɰO;=*F|؈cdy]F9G}^\yEW_vPsx| DI^wOMI2S;3{N_з_1xaQ\Xg:\<`c%_t<=3/2xeX>_]!R }}Uzc5#୵05guo/=wwc* mއM0y m?*&}&}mc϶Oq옒1U9 >]]e_v|y'_`foD:f''_ |a0_d" ExH$C> |a_n~gN!ѨCɊbX,b0_/}>?۹YrE4Pa[TZ-E8x|a0_/~M_o/DF#E9 Q-./|Ef9/~/-_h;苴C |}'}"+5"hyyImm(6P}BU},}B |auM}D>r3DH$"0(*- ,*#QEZ1/Ep|a0_)#/D/|kIP}ᕡ {ꋽHB |Qg/ajR" />y" |q EȢ6T]]T/'o_?yB/ "?_5|eeѲD>_d"UY4)H)_dѬ|a0_$e_=X$SbY}[@qѰ/|k,8Gڟű-{9N0_/ߊ/k?[_l/$ 6P4 h4l/93x_zrd}H,Ú}qMEf݂8 +~Z_` +/=cZ Gp/ Ea"/y~__:/":Ma0_/}E<&_~giPPhD"W]B |a؏- x|a0_// +|= |a8H|aadb{쩵f͚5k}[xqeee}@555k֬Ytive˖)׭[|rrŊׯW\rÆ V"W^I$9d ?mRUUEnܸMr͙>d˖-I%жnJn۶ ;v;wk.wLY|r^%r%F?ɹNK !l0n1$ON8sIy$TzR$Krj%%9Y<}L\yeUAͫ9s 664-izHd5H &M Gg޸e%s%}6|Jf^`2&OMOԿbJƇ_1OƜ~?:HpS\gk#N)͹6%[>#?^p4~!S4nߧ>yK܋N8#9cs ǭ_h Ӛd+psSN{P\m}XCW6Wհ/輲2Hhm fVJ'K2V/Zhx{U~}}2ѱԁGĵ5d SZ1I{}2WJ9eʧ/^|=.Ouh~uDkB?O$U9P<)To3m=W}֙J gMbқ>˼%Ӊ^^նcpcذ/555lkMϬ;7,6J$Q*$ ]/0. ~| +\_eыQ5 |T7'[pŒVwMif C'IUqTUJ>tUU8 B}9-pun*-uAʭ2[lGg0 K,޹AJ9M5{jf@|2,Ԫα@ѕOHL M i6m'OA3Og,ʥg8{KOx.%Ϛn}9I$6l>6E5$HFuG0k(,"Aj05dO_Fщzz܅yUTT,\um~G&U#5{%2B>|.u\l^jv qE*}H"kY`j<}'Q6϶'bŞop qL${YF9jʛKe PKZoeZJ0}NDHE M!Dbfz54pJ}9Qs2]SjUZoF1NEN%Jo&i/_$_`dPorrƙl] +;s'~h!^R'$SiKײUv||eJ/*i_0R¤eXJ & +%XA & )#:.'.AM]^(+~ņWWSy F#Y0g4=FX)٨9R=jc!w_= /~(0_j>\YYy5g-ml'AHLn9:꧱`@)ߙL(`m d#PiECIhIXUI020:;g]D-bŒ3"| AD b 6*1Hixy3 >33_ ̈O5AX@ja___|HɃft` UobRV;%&e ݊ܫyMzgϞGn⛣"ڪ23q̩*Fm[ă_ɾIN883vxYw^j%ql _(r$ H7O* rU5қ/VVV{{{\j- {ܮbwF/~ս///S .mV2[%gh.I9E:*_]/IwNw.sw>~xssS[?B Vޝ+HUf-= ޼y_ +]%{Y_=^$t!k6A#̙#sD?U   JhN+JVn/D/z$ßƟƟ?m8_dhTBwۚU Z-',`yyѣGd;p lzڰZ"g/Dmm&0}" bsTXQn// I3gZU8833dՒT)4}f"WV UVA:X9 lR?#^!ݪuN,)+J_ZDjxևl݋Tuo+ffիbUVݜ/Yk{ed Ek/6͜[fFTQ(V9`eԥm7qTPAaR{27fg!h],\䄩Nr Hy*h=|ˮJ+ר D9ƇƇI|u۷'y־_!WC&M\!YlmmMggg^Al&M\ 9::/HшFxvL=MP }=fЮvv qQEi4J|1`( ^K޽KoK-A\&+Z_x`BR\Z4^a.<, A~w!|߿?|~1xrr<=="zd_m A d Lb+FbC9Frbxuy:)_0iAW1%907##^+1CmnnzX>^` L@8JÓƲɍ8F@f4F~"YLiH)CMB}3x*0ł3Sa|Qz0{dyާrD|h@:S?>yCmmmՇ7;Ɵ ׯ?}}/!,3Ru;قT<_w{r!IRΙ33gLVVVhLe\m&,afI`cuvR8xٵ^o1C?ӧ|IL+oSl 70%E$uډgxV1S%9$~{"<7QwPiBCCC~УT%2C9Sel}c{&qx͛\0awE +;ۏ%L< pNC gI^m9cх~cXй:jdL.Q.WWWsѬm'Е4Rxcc|Ɉ^Te`1r_z2G}gaxm/E!C~4AngnX6v8\ EITB[JFBoE\*0^m|e!Lk@$ z(r7"Da*WV.(>͞LVJF͓,,h.bw. Nӷz ^vm^D#:qF3#SN=S dkyZ@Ԉ(w).\e×P'fVmW$`^iDNn0f +{L +3g++A[ḨfUqb.8;3̞[4N +\^:ho>:'ᰢ9hZIЋ>=/lW֋̷ڿ^\uBWCqU-p"̄'m|:("4t0d>w;x/bP/"Hϝ|˂*N & +M + (KEG͏h"@!`^)9@ +ORh A j6V}8kcN&Տ?ŋv9Uvh :Qj7֩BZBp}]T-=>E[w4ca?oU/ i=nx+o6[$ IꎄkeUHf#[wBHҹv%ޮ$t|K.Ik_MDAK&?aK}qgyzk3$[ny)2Fl! +ZNĤr7^ƮKA/(wr.VQK8.E2ӑW_}Uq!tvyMM~1^SНK*>3$yppkhp3/]@D\y,O!BЩ4xoהeUY0aԳ?# CEPjTT~L߯DĶ +`*F&◎${{{wJMu,v鄑c3CQb@XjL}`Z#WHNvw,_Vz 7~PtWP%#4OPr:H˂,/K'O۫ѹAmmmoz9(Ύs" ^#w/nd/ݪ+ { y&Ȉ0HLن4Q%.rˀ} ݃C:vlr>R>{ms|l%vUV.D 4 xs$1_9$24^V6 1۶02d-_#*Ky(aGPj`rY`W)NLLmW Z%F, D HiŋD"YuŻtOU|a=ArZ#$*ӎ9A"vbp.]jEM_:hGt"Դmo߾&2DkSXEX?ʟq_ A{ )ib +i=c@a{[$06;&_uj[{SBp rSߤ5w-P"FBno݋duoVm`9fWar[^5ͫlg0d^jR/>zOj?0,]KlӾC\__[£9>P Q0Z%*F+CO< (C85G]vmjjjvvvqqБA;bQDg k.w^S`<4_q~A877Y#WRuʂfP@䋚&''o߾(}6W,h+hY/|8SbDjP dmcQ4~:PBg( 0DC :AM)8͛nݢ\ZZ2,8 %DXo_&Nχ؀@v6gb!ȑ7m1` H >{,$Rf]L:*4c=-Tq/(N3Q R>pފ|Q5ʲ^Z#@DY'];%xP4+Wܹsݻ8CX]JF"|SDQWstmhSc8yᙳJ4 ye/2^ AeN8~0]It1,`H5699XYxԩ)݊CtK.lfucǎ?~ĉ}i4 +޽{eɓ'o޼ywTWE~JO +~[#42LQ/HYfMiDZhm$ExLۇ=HH˰"8(?&z~]nܸA-܎Hѓ7j+d-]>?qix@1 ~C|%+ׁkkkEDO Z,A~}A,a|Y@|~W|(HnOv 4elåͯ|rO?Owə?b;k"ːcǪ;F,/e~ {u9“_m"hD@ Z47(00x5E4JBM@m*7,7H_~>_kU N΅q][1`+ :M:7H8A¡ ^%bT H233ׄ_|z?bwo<|Q_w=_8L}IގJkbf8>h]Q<~:ĵ=/#|_ +|wIە2|Z? ;~H뱨@L7 D& Sl"_ M)/ſ˅7Q G֜i8UkW~5ݤd*Ecp3UPu`V2n DN*VVaOX%ZQ"FhEaxps;zF +r{\ݻWgڢU~Z/:cu44`R6m9,6)4_8RW۳k|r.(A :@\4|裋P*!%uD9rX2·#3* d\J4Dujjk@"! rFv%_S3{8`> 9rjjM92|0&>-2!6Q/؂JaN0YT ݢltԙ:V'cWhPguw1_tWDfj|V.@c0'o>wș >%|njQ*B,Eoa0t &3-gB5X+̈́IŽ ?Q}9`$> {Nߋiwd^t4/"Eu2F8hz1C,)Z| k{B'_*,_Xֺ>nW`y A~*vxiEH @I! F]0^}Ao&pvMCgd!+: ;5 zY_;0!NӔ"m)@dddKLJx}" (+Jii"W:_x<筭hZ+i"8_G"IDISpi`<"8hb`ep?%pkAS<-|g)gD4JD;3;D-Vĸ|@EҞ &::@d >& l`0@4QNPXNh>!!/%Hc3h(6D#* 3b֭JHh.ɼHgDm?Qtl|3)KmqNu@9k;S/Ҟ}q,_-:|C1Khl1V~BG_n-VfG9As?oIA (I.  0 Pih8Sus06L~YCޭxkVz`@pC +$g9g\|n"ІB0W7 7P՟p;ғ0!uJٱcIF_M5&- +8'5)#bM +333I+Z9c/ZdժeZɆ*j JE bP+\eU-]eT:QkUF+DO3H+Q>{b41yI")c81|1%/T)ݑJHU9XE*a<Ě*(QPL2ǿ)y_ZZ#672Oژp3AI;c!٦_y)]^k2~Uf.rt̴C+mB8|V/ +`b&_i/JqLݕ9r^8/6ѿ|1Ey/OV x=#V" +ēA$F^dH HC+ b3 "ٍP +ezID $*"RCU%4a60߄ƿh];&{(l5_D1!S7U4ba2%U;x@!D/^pEA,K~u*}1l$sIYV zZG, +Ed7 l-ˌ~2+G!(\45Xd$/8/`,,_<~soa Yֺv =/찮|B,"_58@t0O0tp3B$U2a(C Zwar6 SKeZ=»Lb/vX ʌAȑ#$RY2d>qp/v^۩), x IzLzd7^\Q$:ygOt^@r4v6%q/{/y/յ"^B%Af([0ee^/RYuTH_OIt$ |Fbm+[3'$._qaiMKXr[\nqT|?q]}*Kg!Z+2"AD p j)lL]msoJ?o* ^F9\ gM\333`elV/Z76QmQAw`\MeIhAf`[@wJ իWBC> fsAذ>}7"YT> +D􉜝9:ga|M|D\@#5١/l|`m*+Z_9|WFKґogU%|n":MK}S_FOݛ*~$uoW?a&_tKWשggg +VG/H _쐺7ơ6^ZVi#vE'GveX#UxRrU~$^ףYJs0U_RC_q^W/ZʑUm<0Ϛr +ݴ4 kI㋿vu +/BCuMh%0M"!$٧*tuX:o%/UnX'(,yV>M&V3|BȂ9Dt~,T9GV6ֳ +29<?b,kW|1Z. _|1p^sN^'L@܀qAmjC_E*hIIƸ) A4%eEh%Ró SI@xU9VK7έaV7تcUVk1&d̞vcq$TBI[KvNhec<Յq~ip]#{=pC=z|RF/(ߍ_ #5cB(B:=$jʭ:T`1]i N3nTKKKK:V1ݡt\a>ոk_|ں`߉~^}Ѻ:+_:XtE302 O :,?yO[O={B@,|#h~ӛ9  s`U-<'zZb_aE1 ŋ/]tΝE] F1/na}=A3n `8 @M@6d]!Dv t &QTX\i Gf^ ĀE` @>|$U"+&S +;X,^؄;fwG§swgC)<FxgɆZ8#@xpM*}Y#z``<0Ϛr|Q:8y'|rU qVDҊF(ZD䌩3{9`6U19ssVdM-X&ŇA[9gO8v0ufMxH?NÇtō7.\okJҷ.عs]v޽gϞ;Le*+ŵkzbʾ/m;32_Dl_V5Mcǎ>}t2LCk_ܾ}ٳg_o5iST_I+_Ob~~ܹsoOe*SJCׯd͛ω/^z3g΄/3} 59/oA)YS.}Oʕ+ey_SMMlkZ;I/V z$Q#I4Q@]EX¡DZmj./3C!}E_72ߨ~vL̯!c}.(m  !w/Cv +zaҮ&~r 0xZ%{^$Y!LCA>7i<ȁ@zAO y삔)BS-:,N8m’ K'.͘,G Y9y%$k*ȱo8ddXsb[!kO}jd]>,gvX9ys ysן{+wϾkh,x<$ .,tqfȥG/_`iTeхˣ +H압mWWABdͮ!%kwMmHbҰ=ea{ +b@x7 Rށ 6xɟB>HlS*77UGUG߂lɨr&Hmu1u1Y[!bC,۲-qٍq'l8uW.g?m}ڞpx%\˞s{̭{6B.1A.~/}?ˤ +:Pg kݔwS} 97K/Qr?o@JێBd?*UvˆTD'?|wr>'$Gypdzd-/4 rߗ ' +(uPSS#wI|8^ԕ+W*++]˲\7 E/fŃ@]%B!._| `I0c^%/ ttu]|Q[[+@D_(^TQQוKS ]!>7Q@_/9 tu]|aX}m @|] +||WC|QQQ, PeL] L `^sHS/HC 7G_/ FAK/@|_K*,,T /݄gd`Y j̆rx +|AΧ|/ +|!X" RT R! c 2_7}A@_x9tE---=TZ 4j5vCIILg'ѡ@AKO|U8_©/_po }4%_}_ @B2_ܣ^TAAAyys_tB55vdd$|/_ x u/3pԉ/ 2_ @_xE&e_xxQeee}75蒘:>C#&bh _/@Ѿ /@_/}+_Н_XV_>QɁK~3 _1|Y/JKKe)V N"/d羠A_/z/20&t)#XU/Jf:4^T|||RRS_Eg'ѡE _ MQ_Р/^_eIZK^F X@ץ *NASGrxQխmmm򾀘s^%_sAŘɴ/tkYrxvx_O/R ;V璗dAV +WFhC)ȂeY0._bPN/&|1}M6P BBR8/v1RhllپpA/ 2=p0nEQFE/~b/8>N_/& @|"dޗ !FŐY!z41rŘc_-L Y<ń%/&.Y_L$*V_Xs!kOrЇ%cY7!_6_(9՝Znl_h_8xƴAh_ ֊n!Z(BM@_/¤ E=neƒx1U}_eKu]à/ u{uH2͛  G_/j}C / ޳} ,444ERA_xA +͆赠/V*t/z a|; /n_Bl/ЋHFx<&||!_{YНYK4TUɢ#"R|/.܋쏼^߭o%{~w3ۊG&XzKza)5#)z1úEh/\M4^DZ{d4R{!w'I]I1ȟy#ѯQ6.N4I"R|/>C[ħ[rB:hq3e]>8KK&B^;vX7G/" {Lؘ01mZvK/j𠅽㨘~bd(Ћk%VX؋:2i`'Db4vG^mM^;p D/hd(xXjbFUz1kH/V F+â42 i^{ޠ}Tj3E$z@#PUU|/d^^^0 {NЋH LCYa 7zLCzLp^4eI/i(1{?\6^4'ӷKESw#ާ6.=Gx%wLB/hdNԋӷKzqEC/ds^MzGFx<ҋE/hx^4eI/i8Na 6 +w DdHڋo˗fn^dʲLԋ.V#2mϟ?~@~9W9Гi*E/RF EEA~9Ww =_,Ōٽh2~C~9WD/d<_Z,:v2;|FѼ{yKrlr6 i8N[1=P>@\E'ÎE׋^p4y 6z%p\RJ[QPr68sɽ<z%PUU^t-_ +I . z%Ӑ9@C/ 4eI/ C2 /// 04Kp8 4LCQI{mRH^p4D2џ +Ȳltz%Pu^p&#s1'K .^_ǠK .z/Xtdx;|=Hp&$z%Ӑ^zarv ]?_|^p4{ɰcјG:^p4TU^c"bׄ^p4E ѣ2;~MǺ/c\2 u]'Ei +z_.m+Y8{[ et $K&e#A/>AGˊ *KyV@JTp8Q MӬ;'7>o` '%b'cHk,|X/_ |D5"ZtՃ+h/ iVy?S,|X/Rf6-Eՠ*Elֽ|ʲ\/:⋕/ d<_8Z};%ެ_@>Q EQ,i 'i|հ{Ᾰm/ |ѓ _@>Q hPk/PUR}aM?ĝ=[dž/ ,7l '(Z; >K6vxfl EGˎg/`)Ɇ/ `$_ī | Q UU-i:P}qc_/`T% M0EO6|D5u}X _|D5L&b焸K_@>Q pIz); ޗ~/ t<__)3}+|D5%"r {t0orQj[/ZG}{f}h/ `Hwbl|D5uᾈMd/ d$_Q¾| |VeG[ďSE&jz_@>Q EQ/ d/z|=_@>Q _|D54M<_$ǙB1_@>Q eY.xa 'a:F+yG |D5u$_J=|D5TU<_8;9>m8/jF싙k,|T%~ _ / ,䋝iycKS|V ,|D5 |P |F jN' 'aww_|D5TU/z| j_|D5E/z|=_@>Q _|D54M/z|ʲ=_@>Q ' 'a0/ EOOTh4=_@>Q M\/`cITC] MPU#|jL&ݾد[/b`Kџ_@*&_`jhL_|;XVHTp8<{CKΊYobY"Q L_ bCX)`ccA;x [ `cc{[苿~jhuq ũ/Z&I/Lg`^66Mޤxl|`>|uV5su][D4h4ԴSYgYdnCUU{{{ :}Q,}SH:Fgr:,OF1+5lZz4վG--g::aLv?LUHk<_H?~xŋ>|G?~'O>}|왧NWDNQit7ox}޽=uNT >|P~Q;>}R~Yϯ_z~-ULY bK :T{zPJR23=S麖ƣz +HՐ*~Vz1EҔjKt=cg\6K_++}j^Z[ڶ`>SRQm{u^(f^1]KN,u\Km/wf6=_?=Gkv}pOEZ7o޼{Ν;nݺ}|FbkWGgkDyʕ_y~^zk׮)5`,?uX<@YΜ=yu:붙S%Wx)U[2ՑR=[ZO>*&A강\Ε2]):60yzNs޽MVLWJgKj=; =޺z~~}ˢ?Gq|^*86/$0p 0(DBs qh`fr)vҦ$!L\Ok[K`'[j9j1J& roCE&3a~8r]m6<^:qИh|-JvUS +ɝA’;Vf9ϯVxNOyulW޽>ٸj _r*x]ں~z| ˸3v},,bu}}٭=VEt: Gȱ{w4,2^?/>f䴬 <XyV ,[»VݓZbӉ Ex*eCO e_FA,?~|9>!]G9`XrT*9U3C]Q{#GcdFΡ.Il27Pj怏=2lhp48ssHNpsGv/;f~cr<}hr'ߘz*mUh{EĊnݪ= Ź޽{\v-b[D xxPPX0fa¿U@o6pxh8L^JJĞ`d-YdrexY߅_,.xw@27n|W;/CK -"|wnltb"}_]~g$^[#xb +~a€ -E`2mY2%GhR_8Mͥˀ%̯.Z@79)ڽqҼiߢ + w1iۊ|2 +<!&)fޔӒ2[G^*1c?ٲXY.1irCY'/VUOKI"ʲEXLlĶ`WW@R}_EZZwM/f31ߟLdF(3?'zLmWt_uR;hoQ\i)N{=c&S%}1٬kb_ bFKL, SЀAlmmvG}eQdTG{c<w xӉ3!:<<!Ưʢ阛ńYtݻ/3/"G{İ+'sꋏG#ϪRŦ_?ί_oF<ۜ?\m"Dcb^UzzbvV(w_<׮Rxh5O;|S֯ [-5X}]ܜ*젃?\'woLϲlBFp9ιG(ZhU~jF~Q36l4+2f_T_?F$`HQ~ra?NILfUV6͎V@guA!9\H~Ѽzŵ Nd-BWcF #b}}Yj +v'iZ)6~ol/ +m';IV ڪ|/%uRqVlws{PxD?Yď#891sRuew#`IR_%AXҥKnKD=92nxax8xj+ϗgE ~]_TL"l uk]& Ws&:wނ;Qt +7QGH-.Q4u:Lܹswi2iq`<4ܟ8'n@/(8Ppܑ;$p Hi~+EsK4$TȄ@iDHlIew\i+6/;M{J'r<6<;{m4W"+aX Q`V.ɋIpP" H@œs$ z?qģG\|!2-^x 5A>Xw5K^ ϢI˚a%4WTd*$81pmmMiq+G1~98HǨc$2OanV& & +c/w0qs!^gϞ$ ׏0;֠!_Ofz|TJ):d.P?o{>_OB>6+؟]$C?tﻄ҉>(ƮuESW4 ukW]7kWBcW?0 B,xiԩS^ɓ5 {Q3$Oi ɣ!IPÇ#<&!fBcRJpsG,*rLNT,-7WzA'WVi[̦uVXZ6N&.HrOwtwq}:@dDĎA&ۧfE>JWD& y)>GC:=YgUbWZ@/Iu_&Հ^PidHlllPHNعC|<XC 6JpWΐ'Z5^Zvlq C2RNJ$t"5IA$CLa{^՗YWKCa 0uր \*J$HXN$TD 0(͂$fHb9HNB _o$X(1`};Γ| ߷"Z BXet(WwVe+np]8p`Ћ`e "$EKl\kmm,KWN OgwĽKJD6y< AMD'+~n3- r{:ϊzaPK+ӆu,$ H}'I 6Nd=H 1A⋒Rr <D ֜ArWwdҪ m/^D d&"X]FIB\0 :[ws, ׷X2ytVB$zVZk% ԃzԃ_-o A^8l&@0b=pVЋ)2D}&VTZE\$$Y;g3_43Eȹ/7 IJV$flf7?*ڷzAq/ϥMx+,c H1\ѭq OʣN4 kın t֬Rg:CIȄewThhOnkwL$ O 7}׊Dp?Ar&ZPV.+[ ]\/ⷰZj͸Wh$5Fb8\3V4h, QP RQ8ߋ!狸ɫ.uAII颞 +$J(.DJ$)Bbbtm*IqN qN=b>uԕb)2Y4X'5DG$R*dŽQ?iʬ. +-1E98(rWWWiۄ+ +uPT5hտqvmJuk9$:ԶlF@_RDfιӳ J/ݡƲswWg(uv5rz.)t+uWk=U}xcŤ]b]qiQɰ֪Zku=g?kjfjU->+]殦lxD~ͮo~r;A0/ 7SY!=~8R $8HpWJ:kBw ׉\Q¬*VW*F@'`4<)rN 9DFnIomf5 ?ٰF +^^ʕBhmw=Ws 0$⿴? 2%u_;I8BM_Zu+O&[hf)*2ܜQ[۫{bOGr:)bDғ%CPb7əxDBN&2CdW"d`-FPuՔl؀XSJoӅᕝB*7`o?_'O?WmrlbBxQo[8T=H*AH1:A:w GQJRkiJ h5-G3~˄+A )t2UAʐMke뜾V$G䲀VJdN8 A.$ƈje3ĒY(" +M8a c-Y1{LVƺG0dV  2B#DR8AX>nO_T썼A|oO+4CwK'JDl ֕=^`r}N>t\h'?{37EzՐ?cuP/HW^wx1wh$?Y 7QGJ?ʊF.&'AҘCQhw!I. SlVaO䬧._qW9G?ƸJz숥z'b_\M~)|]F*~Slըq=Yy<0/$-@JID w5ye#`w~ +1 H !%I\PVP1m NRYh   +WA)" oX3>AA^id +zP/HZLg4E +J/Cnt^_D.l?GۊCn^[ (50z+ H=O@=7<8 QՈQU؍^l/'L0o9kTqT;>jGc<=O[m&WoV:Wg4^%WGTFi+UF5\摫ؤ^45݊ZБ()AP+Q +\wѺb1(X-"1懗FA NER"bMLav'"ڡv+)D$iQ\Y^F{8IPr@' d,6+:A,ޭ۞x8l !\| o^[Ϡl`b-99%=S숼qD^ v9F,O0<Ġ>t+s&r&g T挥m݄8g@?Ę^Cw{aa=$vZL_kӸ&:SD5݄ +F %&I/P*E䂳Lniy6CΠW-*e)5?ò۲G/Ŧ(س4A&\i0}v^x$ oٲ_?c7b H" %6AV" \R +MaMc8$J<ٜr ix=| JwP~<>nz(:)I'KF@l_GT||Mb#r^LFxea5,åz+1jj7q71{˟ֻ]b7c(T~o%V\{{.F!P=~ !l 8W1'(h8^4trN\\σ$DC\19X0q/y@)'GH#Xk\ϙsnSg//߶6G$.} +QM7wMTӸ; + DwG5^qT+%g:ꭹD\Kǹ깯Uޢ^-\2TQ7XBدBzMpG+2ylvLl-Q+'ABhߝmۃzA٢$ɯcńLI\ٯU;\JlaG~) W ]+rx B+zĥ"ְ X9P:'+>;\v Qž$]_Hא 2!hJX@~3"vhSDNgF'ޑWǙsM^)ƒ*yHvm:ݼbeͫdUwa]sVflCt +%>t%ujlΒ*A<#Hw Ԋ,d~18 G{ӾeuSz./6,.s +IqbRQWZ{B4­XLVX` +#9d# j̳6 &^ZژH#GjֽV)Nfag*`Z&42%{تۍ:}JtFVdDx,nPKJL$(iY燭`w mG|o4ڟ5/U$xȉʤ5FD;"d>mHJ>eW3)f6 hZ8U,3QpM%ly"oaa![$]W`(a_bg.``zuS{ +ۃzEXN'XFsOMeJEwXI#rVJ Ue]:3#^aSyx-Q ]CHvX!baa'e[EDa^ip6l!x4ꁶ 6ƴFzbM}G[m:ʛy"JpZ:{ +5g r52#3W?$VLS4;?Vfb#3vigLgKl}/%`\VApo +ʪ'ߌĉhi1S#7Wkk̀DbF/m .?. AX?H]Sbe2uW>kboc^|;Zc-dq5_pF(k +ŽLIdy8 m%|s- o0nG\m2OB5PG{4IrCw#AWDkO @̮hRS΢һx`_آGI*?+P'slŹ//T_uWØKC9^"&YC4z=s򔿬4\kKZm;rŬ5g/cp.`2+F(G\:-oR_W)|E3ƸZ_1&_uڃj "u}ꄢ^ *9Y*˒ $XR8VS^dGd9qѫ:O+ZVT}Am<ğA|ܷ@sg@d t]ML(Ś G2\p3h&_*Z*GCDJP k AĒ B !J4oe^O=v:lT(l\L&̣ok ]B UT)d=[R=5Ȗ`eJR5< C!^ZTѱe{pZnXu#H-IpLIs, ΥȚ"yo0C;E%]"Z#hVn/4uڿooӬ-8r[e匭kB'x6ɯX]{$\@1Rz Z['WV^^}G8hDDHFDE+J2g,nu(,fY ՇOlbGbj/hIh0F~$)ܚRew؉ 41`m\**YeUVYe"sUVYeA3n,*@%sUkQۺUnܷ|qY2/>|[͛7G;GGG cfw G4ׯW^XKx%5lc.@LNB$2d zW@ eQ-Y D0135Y ,fpp<,<bl ~BR/<ʬZͼ/-_ܖܗ|sloUU d# 1 Թ|Az#|&ЏOA>hO䣏 o ^1]{AHG0fY@) gvh1P{~)nEqkϞ=Qk\}bw+"Eŝ)o+|j._`uWa$Nd%G4t)D`1xDVDrYڠU" !q!44]Y%\14VD.d0c+ `*Z2g!mvcEx#A%,hqt[̰ +cm%f~3c +"1m^m$r\༌4p|z+Slਿ3lB`\gE5j#x@)v>ʛI*(͕yw豕9.*(VښYJSxI+i(VJ%IhSWX*TyO?V 9^œͫ4jkHʰzWQSf֫ԫofem٫ xի:z=yKUXհojU^aU"GeF[lUde].VszX%J/#ʨWZ5ƶf]f*m,1C[lмMgE\aWxu =hH&bWz%L!qU %|e6x91ɱT)Wy$+vU_|L_RA}5~ꫜlŅ>CWzI3_͞+=MMHXf_U\h+lj+"G/2ˍ#(6wE |5+y +Ur!i6Kf03LY苖#>WxI^ϟU}}ѪQ3A0p՝b-ai6a٬tbע.B,HtGױ7jՁV$wcPbg)X +Aڀ~cYi {ķ&lHf?fH`NuhZn1b/cͿ_&3@/˿5YܯB`y}1&}lWSL0w5_VΈ5DLõ-iBİşN>8U$^HY2䢡\gyxu_ -3Kʿ֮Af|{9B?~|1nZhLmIy0Y~a)BAs`:"8c{Be̶ɹ-q6ɇX+ҙqWbX ?闚F:r/U'2>GR^[ߋ>/E H#gH/ՉϊczbYmcv3!.ZZeI݁s@51 }v9%֑6cyn\ jvHyV'?)3_jYxIa!}_X@؇?{MOSJϡ4VP c_Ozئ4k׬6 _Z|6 6 ŠXaBA`uw93%30Y$bYWfkF7kO_ԫ~CsצHp_OU+p1 ڶqbJHWYǍL~T3cIy7ՙ)2Ք9el ["b3'a$M 1hR!Muf)Iߌ&q#:N>7q;qrF/';VQ /P~%i:8<͌oگ,ZG_y>IdfpyeOT2!+0HN*g鋌əACAݛ#y3#HT)^ ZY*]ꀎYJ;&hhSqJbњ*sZhBCԠi0ԪCʾU?`ˋzZt;XuiSQUvU\ժ0G{^[xg>*\j_ڇ{L'?KxE[3߭AWHLkTV&9[̂1K *8wFeaXSj[aWᕞWI)*Q;JzՇŕJʥ^ $ {1W0.rZL$9A9$KYP\b.lI*􂜁ՂقyD ArB+N '1>yDqy+ dBwWr/nX +mY6RdqA.|W2(B5˴{;;#_w%_~hG;юvh"nL +endstream +endobj +618 0 obj +<< +/Type /ExtGState +/SA false +/OP false +/SM 0.02 +/op false +/OPM 1 +/UCR2 /Default +/BG2 /Default +>> +endobj +619 0 obj +<< +/Length 6424 +/Type /Metadata +/Subtype /XML +>> +stream + + + + + + 1 + 528 + 421 + + + + + + + + + + + 1 + 120/1 + 120/1 + 2 + + + + 2004-05-29T16:11:53-05:00 + 2004-05-29T16:27:32-05:00 + 2004-05-29T16:27:32-05:00 + Adobe Photoshop CS Windows + + + + + uuid:64f454d8-b1ac-11d8-8c90-a1142b67d8de + adobe:docid:photoshop:3d8f39c6-b1ac-11d8-8c90-a1142b67d8de + + adobe:docid:photoshop:64f454db-b1ac-11d8-8c90-a1142b67d8de + + + + image/epsf + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +endstream +endobj +608 0 obj << +/D [606 0 R /XYZ 109.858 727.97 null] +>> endobj +50 0 obj << +/D [606 0 R /XYZ 109.858 703.064 null] +>> endobj +609 0 obj << +/D [606 0 R /XYZ 109.858 404.031 null] +>> endobj +54 0 obj << +/D [606 0 R /XYZ 109.858 393.307 null] +>> endobj +605 0 obj << +/Font << /F29 416 0 R /F28 380 0 R /F8 369 0 R >> +/XObject << /Im6 594 0 R /Im7 604 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +622 0 obj << +/Length 2770 +/Filter /FlateDecode +>> +stream +xڥYm6uHJT>ݵE$Nk˻jd˕loHQw"Z"3U,L I-aݟ'N򈢫#a7G<~4NLH@ΆtEtGؘD3v| K̠8WᒪnnRP*' +*ϣ-Q،W"5F#, +1_^CЮ*/\4;@..RM G3rbQ(VT>ΐrFљc:O .!M;CǮ*9!ۖ) )M+Ih; /X5դ6;Z+98~  5 hTMd@9 >"2gX؞,bDGK)zTA\;6{ +K1Zc ^`!z{T3[M"A%I8W"OcUP3 9re@LUeu֑I& RS`Žar8ҏ2=cclGlll3,*䌘XzW9%^S`u7~y6>Ԋ&KG[oȳ8/GP8E +=9O#e,{Ήiχ ˔ +r>t +y^|Oe8d; dtr|ȃb9M{.R8eu A, + TKQ4"\$7S]__Nuq$Nj'NK.]4[;, < W܁i=h K:Fe+H6{:eXJn `~+ (cw^9%W\ɾ[Jēs,Pއ [-?sqgD77y6>- +W2YEkE_+,@ugڥ[io~<ԀNs=g/K4P]͢q4^ E%_5BaQ CLݍ@Z| ] 2 3 ^qc2Is(s>" .k_H[M5of^>?攮У$AVi3gE@L(݊Bs$6ZwcRGRfn[zSޅ&SS'fGM~F NvPއN߅xR4mޣWYP#h񮅧8Qlcy|g (ÈYPRsY4%"+Yߍh+j݄{ <(V4e ϯ1{KUL^ +pgt +uǞNgZF;g_hŸNxr0P7ny;kH'*ZnG0L:XJ*0,@"Q +lJSQt =PU-]3F>> endobj +623 0 obj << +/D [621 0 R /XYZ 109.858 727.97 null] +>> endobj +624 0 obj << +/D [621 0 R /XYZ 109.858 658.287 null] +>> endobj +58 0 obj << +/D [621 0 R /XYZ 109.858 643.274 null] +>> endobj +625 0 obj << +/D [621 0 R /XYZ 109.858 422.045 null] +>> endobj +62 0 obj << +/D [621 0 R /XYZ 109.858 411.321 null] +>> endobj +629 0 obj << +/D [621 0 R /XYZ 109.858 125.798 null] +>> endobj +620 0 obj << +/Font << /F29 416 0 R /F8 369 0 R /F14 372 0 R /F28 380 0 R /F20 385 0 R /F41 556 0 R /F45 628 0 R /F19 516 0 R /F11 520 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +633 0 obj << +/Length 1619 +/Filter /FlateDecode +>> +stream +xڵXYoF~ׯ[(4bxsqI6 +" еHIi!kIJEDcfvkמ?Q?q,\k;,;˗oփ4vT~\_ҋKߵv +7ߢ12ovnΆWE7֟Mߡ!r8F5u4Q;55 +Ǐl5$3cNdu"hoEk&Jj'B@oyCtBK,5/KϮAks&6p`!+Tkii} _V"i+t]0E!LkSdeTCNXcZDa>*t'.Ⱥ-0LYbI G ;o)6S  +X=]"Ю\7 [hfn%#,7LqEf){_w$PD1$LyB"<>Z Dž'toKCI), +Tg?Ż#?:}'ZAI{ 'NͪXܵ:Ö&6Ёoe5'8tfF]*(F qw\!\ `@abvoYԛABBRxR~8 t!&EH:rU;qr쯗{HpY!pHJ#뺼Ij4-Z87t\'!2h`V|8aoDՙt~đu8J0e[v%G0|`1mCw.Qno@N {"\] v?N{zw#\X%[&9N(b7%+7rC@yn21!_=ȾIKBBõBE?0|p{C> endobj +630 0 obj << +/Type /XObject +/Subtype /Form +/FormType 1 +/PTEX.FileName (ss_converter.pdf) +/PTEX.PageNumber 1 +/PTEX.InfoDict 636 0 R +/Matrix [1.00000000 0.00000000 0.00000000 1.00000000 0.00000000 0.00000000] +/BBox [0.00000000 0.00000000 352.00000000 261.00000000] +/Resources << +/ProcSet [ /PDF /ImageC ] +/XObject << +/Im1 637 0 R +>>/ExtGState << +/GS1 638 0 R +>>/ColorSpace << +/Cs6 639 0 R +>>>> +/Length 94 +/Filter /FlateDecode +>> +stream +H*2TT230V023г4P06531P XXZ(r+q*srUXZ).D! 3"9K3P%+ , +endstream +endobj +636 0 obj +<< +/CreationDate (D:20030406193451-04'00') +/ModDate (D:20030406193451-04'00') +/Producer (Acrobat Distiller 5.0.5 \(Windows\)) +/Creator (Corel PHOTO-PAINT 10) +/Title (ss_converter.ep$) +>> +endobj +637 0 obj +<< +/Type /XObject +/Subtype /Image +/Width 586 +/Height 435 +/BitsPerComponent 8 +/ColorSpace 639 0 R +/Length 17165 +/Filter /FlateDecode +>> +stream +HKk $HrA8J:DokNāx-0GBp(l_>iZ]6gUzw~B!미ewnlb(,uU0*4fm-1t{w|{y~oo}/߭U /߻?5&118SQIAJqjdysU ?k>j'u~O~/?!B½}nWi$?P>,r^vT7Bnd!FՍ,$R!sD!dT7Hu#́Fn9PB"Ս2YHB@u# T7Bnd!FՍ,$R!su !,ay'*BJBУn{1tȳ4q)qST7BH:խy6$WڜN6.6lPtW:fğf -_*ՍB6F[ZMu˾k.0+~D.R!sn n摼-[_nCBBȕ~u lk<(u+c3_$1T7!Qꖶtl=evS݀R4os F!W[]7h~wT/3[z{ /_قL\pfbqʐxޏL +GOGBЩn͓Hu#̡G$R!sBݞFՍ,$^ջFՍ,$R!sD!dTNgy FC,oK-@$pFC5ϊ:|t`Dۛ}j?A<`6$?T!R֪c#CMsaz3n9 Q7EGݪnZu*ՍB0^lUDݲJ]zr +궜#2QJ@:[ŖHҐw7m)Yb3Xm~s!cu6iwmR= rPBb ^Ξ Ս,$G!FW[4Toy hPxFnZݮKtfS8q^96 rjcؤnӅ:,I?͠E|Cz֋?q/خJ䬼y^rZ9 +RZ@$8 Nf\wSX8{ҩnͳ[3.O0r,=Ũp lNsmMY@{w<Ⲡ/ͲF{135WJ$s^gZq/i|#dOI2JʶlڔC\'65/J u3]]|Ӿ + 4[5k1q5mAZZSSjaAl\pG0DݶYU0Zݪ+]UݶIGgP|3;n TsHf\ >5v$A),pYLЯn:6X^`<3aI  u{wnt6{g6OG[tQ #1;V,eb ,oz)js}g3J.(umv<1nU5*#Yߞ5$דx*SnhGUUZ+gC-̛jnB[˟Lbv1юRHl&6V7AӖ3g<5}b3щ+mU1W7k6ME͇ ľw),p 7puZnȄݭ#!M!gayfOM6#!GRp8 Ma7Orp"IlzԍN4u ɵqmsXS8ن xزV꯭/gq-e6HtD6nd!q#/#ZͰv3lmΟ:0EkX}*0&2Vnd!q\li owz/w9۸Ej ܦnfq|U5@T78S@giͿ>bȌęEC [փD!Iꖍ"T78Y@gv׳6lVvi1[z\"]Ӓ*TPrs4N7nߌƵٚr{7c7D7"7jъ 2{ +!8GCs,XiYt/1Yѝve[ ewuK]#!g7]-8R&&Vo39NLu<)6j^A+ζh!q>fpfYsmg$ftOTuMmvOrqCRZC /,&NS7Dʦl/ڲ~ع=$4*Z(#`Sn㨺@z~A+' ]<*Mu 7* Ayj.N#3 +3 <anzQm_͜6o{k*6!fgByz?8ӌS0{#9;q A\_4l5Aή]!џЦ}IInKϓs$ukkx l~u=y-|n䶉ݎXu{HmlxmDZϟՍ,$1!dT7;XA(nd!vx(pPFqr"bFt0]_6/iW 3,1Y Zf$Ǭiē9 GnVuv#InD;Hҿ/ 9-̬9#IvOX?ۋe9b +v[29G|R5I#XP,W^FT{k/WtT)<7 KnI ((Vuȓ rZ.sM!=?ZZf }FQ-t-CV=IkN54=ή%F7* +kî燡_^d69Gvʋ%0O3Xe7]|>^532[6p‘4[UIV7k1'K<XQKYU:š`76kj־eX}Q<IޭT :K\P*v;R:u^VC.[Owɦ}ųr^hb[j/=qV-;{#+h*UlՓD"v+\p\Fn9Ms~˿)U|*7a/_5N?E%ɛQU%ؿ4Ku^,O%ZdRs݆3VJWRu7\9?enjZ#g|7=w_97ٍYnW5n,P%_\pFCn EZ3ΉrRW1a7rLInwz|{ݎ?x})?T]r3o^|_ܦ?gp%g,WEn2sngz"[%M4+`k|:iNջzi8#Ɯi-<u;9jyͱA?V3v{D٘vs*1 _:gnT9i҉ndckV%k٪fV9\Mv8 +b|?ۗj~gըvuGMnF6[>W߻lD-ndcΜ۫{Ay܂PsM٘snLe!}a [:i?a7fnUA*yrR\a7 UU}ȋIu3R-k햽`n+ɱvUnkpRݾc7en5v^0vnp76Lc7I^y `}n0 +vmw`}n0Jnw< v "v#$/ 2ndod`7n2`77 2ndod`7nv#{ I}x@vn%@ vjE*~ٳ|\ ϫp|6dաUkXu}n*ɪn7+vguڠ"zm% %v;Rɰ[oWgx<^ X:2"3p3nBl,՜MVa}M0sh( g UvS»vSuPu|iL&M] 2MVTE[`e]gOBIWdU|_R,+չ*M$Ȏ& ~ơU[^{3nA"Hvg{$7v &Fdd`7nv#{ I}x@vn%@ vjE*~j3zo([[}[U֙nm[)M)86z2Ӑn+@gݬ۹V,um  ?Wdne+[4{5ի{o+8is)헧Ӑn*|-RϝBw,|Mn_]SNC v MT~齃eL_enA^5з,ಞW)3j;O? $-Jvg{$7v &Fdd`7nv#{ I}xsrTD y 0cnF!`7`dUM!y'|XE,OSU zU*@:hݜtSMa+ p&wZ g[H˖n_Z -v\v>Z_ v+ ui7)fm'2WC뼑-c=ÅG:ZuݬR_UU]UƭYU{\-yh]g(8y3nz[w5powP}Hg jo+ٯ֐bulϰyJ# v i ͻů~pwG0o7?۫1yd0i7B& F@؍ v Lsœ< 2p+! rXh8V+rT(lrjiNpVdn~,[Wo`Wj4&8n_Zls=47>v+<`7`ʪXis)p*r;KNc@Vׅw7Z gEf'OCa@K&+v5X֖2/\m$ބ?YkfW6` `0lYȺ}.Ԥ(hpf@n.-=㏴ׅiT5wLzfuXޱ/ vvyI2 +Y +Y +Y +&2c_9W; +6<&j`7Ph76{fW#)5x> ٣r8 vQv=s Ÿ6g5| &Oխ`7PbL1'nկ[6[Ck;+O8`7PhnAv,FZ>*:zw_ݒNG3|@Aݪ5ۭ-wV_5W&:p@>|@AZ4ͧ=LHg, (h3Hk:=g8 3KȆ@ü,ovI&Fd(ndm(ndm(ndm(Z?˛'x(,!v vK)9UH(F{7_D@A݊f^:ٕޕB5{Xn nbOfZv+@Aٕ9nՍ)n nonJ:n{C6ϗv!v8n{tc=ܷ[ztvxc |X};vIDv%d{ yY<Ń@ v؍ v؍ v؍ vvXgy$vv%dn!n)%g*I|.hٝm=ɨ[/!t(٦6݆_6C-A*DU}C v!vK~vsnli5C-Vx_e vv+d ,w֋u.^tC vQvvo޺6j9%ãv^zC茵߰Lb7ۨvꪞޓUu8n@aG햞Gl'cmcɭ!v"(~`7v'I2 +Y +Y +Y +&I. +62UbϩRn nEG-fg-GlVU’ +Bf?Y?vko̩plj8vwq!v+i;_:>6BJjv;nHݪ"vq +;pEWt`7Pb7ۥvjb=ɘg]3@n-=o]P3-]@n=l 4I. +&Fd(ndm(ndm(ndm(Z?w˔ vc7P0oY;o 4vUHpsqC}Z9~N} [WD٭BV\ yg-kZ޻4@ !vK~}$;/C>6_ߢ`7Ph+~v}so7?[4 D٭ݜnUU~9ڝ\`7Pb7ۮOpm*2\oao@n-=TWͷ3p}ozf ٰh͓\< Lڍ`7P`7P`7P`7P0i~7Or $v%d@vK)9UHpV7?\a7eonv#k@>Y<Ń@݆g ٰh[JəmŮGR!>${h ^SŃ@Aݪ +[u=Tft\9 -=SYb\ic;< @v [j^ +=-| +r([nlWVۺ} +x(m'mt--/dm(Pф}ggRy\! 3{N^F +/SH +gy$gLڍk?/ ndm(ndm(ndm(ndm(ndm(ndm(ndm(ndm(ndm( ɼ[?˷n-ƛvi:햞?tqst3+>UB[?oa7n_S?Ton b9n)=RL`NZn`݊;)Uݻ6{[(VI8fqfzv_pF5I(:/_E(xe2(@AFFFFFFFFFFFn 93 D`70W[ř/27[rrf,# 3l>/H WTg[;o/y΢Ѳ[zw~ڋ]RdfSe=#^Co鬱gUY =nUCYgn-FȍZ}YY*p$2oRnV`7! q +<vC$N݀n);R@"aOb7A1'X=4\#[s@ +h7GB'z~K չ3r9 n즂 I_Hlk׮ǮDB4.K v "H<2=#*v;>cǎ1QB!<( vz.5-" TuDwj3pfVK@N.9 A۟ [MMYpgwga74IHT/pīбOXFLa;54̵$;/qlҬVNnn~ؑbQX"$$˗5sbwcFj BxP,b+8J"o7Yp\,VB?uoݷ*EDOGw=͘Y|X^NFb + lY}$˦5ssfY3vcFj7;aDvuo-_cMһA /b7Z5bƝ= q>oWd_Gj5Ͳ&ڲ91ۍZ*nH0?M#>nkjt'H2$˷ۇ$!ݲw.*+8e8nfEsQ)Q#QhYḵҝ㱣\)oqJe*k#f&vqFnjF +gXj+e'p:jjjn;rl-n 1W.b,ͽ%k<> Qb Bag.sE2ᷖ"m_ ei +M[D{7KH&Fzuvsw[\$+ZF*M=}c[_X!|z(< 9\$:Ɋ֡KdQ  "[OVxIVt ]Ld[zT2ҷI`?<d&cM"L>Z֍7;2^f˨޻mϷMWqu Tji{(kսYtv2Hߡy) s{:z-٧f}0U~`dفr*>ڡ凇}TmZ߬Õ;y֍E]Movc15 */jWPUصW5i9{E=KZ|5/snb}L9G[W6nn^܉u__1XC}Ҝ%Og';O8ٍɡHMI)!jyPzan_ͷlmZVX^bm^n{#w[ǘ9[6indnQ6BF' ߜ?/Ұ|j†eMn\:iq^ci3ɬi?'z#Tmf~3FֶSނ;w?ۍ~(| %jZJ@Jw34g 8كE5"R0Կ74g +8cZ^縸~87y=hmѦvS$v!py]""""xd- 1-)prO0ϩb8=$KA(FzF!p3d@aشw{8͜Eɚci]ӟCf{NsWr DvVmqn&*1z{`7kVib7!8k])MX7>k7Vƍ +sD`1y8$)8[vO2=f~Ui <rǢʙFVV%܂rΧe^̲=׌y-JQ= +BgHEwR1;ʜ`+7`Z6rjKY`K1ϻgqxme7ݢv3ST\ +F)P 2G s~U21 ۽^s:O6*mĄ']iv8EZHyAHV%F=AkQ.ru'BIBgM1 E]qBXi-NnE1;bK,߉ݤ=Y&ivS"x]ܷ9@FG_9!ήYɝm,~jKa4τg*MNF^vD`?0CVN^&@2%=םrtY Cl\$Q![6@aQ>Xrȷ0;-/%4;%YEoj6Zf-f+IY!Јn\g![ Ⱦ_ "&o~g>eRjPb+6 1(dWhWe{  5&{ڍj3D[_HA_M2ݯhʊ2nw N7%[|K԰i7Ҹ ?Td+[jW`7-\h5یQL«D"ڦ|Sp#nτԅ120[] 8X7"""@!2'`/y )=(Fs(I؈b6 -dBL Ѳ+/'_N2װ928uFqѭXZ*lMEd}n+O*Vm<;@dnoƞޛؚt8ڝ ฮv(vgJMbIOR1ܣizDCnpBoDi#j;TL!&81=q>2qoT8N57s]͈c_e{[|{*rZwe'ιzwnO|dn"[{fpCcYoe6[S< +Zm%Tf/[纗M! Mcf9ny3,\Dq!X6_ow_&??*8^&Cave> oΒ.7c!m(j{Dh !A5*e+@TiP#KTD +86@`pucQHZR6san!O6(Ku&@KSmDO, vXG&[ r9 E;}@d yp(|!D0|v0$.D/ie.͖@AϰS$u. +vWhEeJ "J_zzh#YMB&Le,:ayjvR)0N]Y#4dT$%}>'ԟF8lEcMfM$&( ,st*_V|(mDmggI> +endobj +639 0 obj +[/ICCBased 640 0 R] +endobj +640 0 obj +<< +/N 3 +/Alternate /DeviceRGB +/Length 2575 +/Filter /FlateDecode +>> +stream +HyTSwoɞc [5laQIBHADED2mtFOE.c}08׎8GNg9w߽'0 ֠Jb  + 2y.-;!KZ ^i"L0- @8(r;q7Ly&Qq4j|9 +V)gB0iW8#8wթ8_٥ʨQQj@&A)/g>'Kt;\ ӥ$պFZUn(4T%)뫔0C&Zi8bxEB;Pӓ̹A om?W= +x-[0}y)7ta>jT7@tܛ`q2ʀ&6ZLĄ?_yxg)˔zçLU*uSkSeO4?׸c. R ߁-25 S>ӣVd`rn~Y&+`;A4 A9=-tl`;~p Gp| [`L`< "A YA+Cb(R,*T2B- +ꇆnQt}MA0alSx k&^>0|>_',G!"F$H:R!zFQd?r 9\A&G rQ hE]a4zBgE#H *B=0HIpp0MxJ$D1D, VĭKĻYdE"EI2EBGt4MzNr!YK ?%_&#(0J:EAiQ(()ӔWT6U@P+!~mD eԴ!hӦh/']B/ҏӿ?a0nhF!X8܌kc&5S6lIa2cKMA!E#ƒdV(kel }}Cq9 +N')].uJr + wG xR^[oƜchg`>b$*~ :Eb~,m,-ݖ,Y¬*6X[ݱF=3뭷Y~dó ti zf6~`{v.Ng#{}}jc1X6fm;'_9 r:8q:˜O:ϸ8uJqnv=MmR 4 +n3ܣkGݯz=[==<=GTB(/S,]6*-W:#7*e^YDY}UjAyT`#D="b{ų+ʯ:!kJ4Gmt}uC%K7YVfFY .=b?SƕƩȺy چ k5%4m7lqlioZlG+Zz͹mzy]?uuw|"űNwW&e֥ﺱ*|j5kyݭǯg^ykEklD_p߶7Dmo꿻1ml{Mś nLl<9O[$h՛BdҞ@iءG&vVǥ8nRĩ7u\ЭD-u`ֲK³8%yhYѹJº;.! +zpg_XQKFAǿ=ȼ:ɹ8ʷ6˶5̵5͵6ζ7ϸ9к<Ѿ?DINU\dlvۀ܊ݖޢ)߯6DScs 2F[p(@Xr4Pm8Ww)Km +endstream +endobj +634 0 obj << +/D [632 0 R /XYZ 109.858 727.97 null] +>> endobj +66 0 obj << +/D [632 0 R /XYZ 109.858 703.064 null] +>> endobj +635 0 obj << +/D [632 0 R /XYZ 109.858 137.014 null] +>> endobj +631 0 obj << +/Font << /F29 416 0 R /F28 380 0 R /F8 369 0 R /F20 385 0 R /F11 520 0 R >> +/XObject << /Im8 630 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +643 0 obj << +/Length 3292 +/Filter /FlateDecode +>> +stream +xڽZے}߯dQlKL*cA, /P(f>}{uJkOOOC3sgIb/xoٚzzꈅIBE14DoǑlib䇫_~uf+- +dvc{A:^aj{qՏg3̈g^/חw3_tٺ/ARI?e'RibGI0]E%wu3w]PKE%XBbQ~Њzj~l{afș̥7X%Jb;\^Q v'$'˨bAƾ^|˶P?  ?ǥ?@e">HG$w@K> |EOsB/>kiW^ +@SѲaSV5rшqP%X6z_V)vvs$ȉ޸-"Hnڊ]i%& +&xUR߆H+uUš-8֍| 4FmAΉW@AR(!A/P@Lk?#(Э%{ +1p٪-uq`5׬5@qPX_&nifzwc+5DH_ނz$-1=*ǣo8VV kxQ6[N!! ,Zaըܝ'thڑh.lp@k-dEo(G 4)g;%_h|DlJjAmQb7[mw;]jG^9vZu@nrg)$gǛh>r-UJ3hc8P~0܇JgrNʨ +"y#tȕxa汑L>"n[]o?/cľ?eET@ ncO_fL$p('wrQɛ^ub# P,O) K?E, +TDzƘEydQD +)|PۦIQRirHRo&zȲ0ip5AO`*lU,=U%2}_I~d@bnK\)Q ŃyXּ/Z1f_)0Ar>z?w RJ%sKeO. PQ +w͞ nT 'z)p /dG| +6{M_ #{~GlflD*u.{-\G蹘BqFv}(3%p&bn~܎Q T3rU0kVnu@_)E ?@3/)gQ1*-SJU~Yo0av $║2^(#U)$-T? W&~㵪3+Q] $i)?ኒYxg9FReKDT+]e{ d8-vZ^e2W1bGFm #= %@d{7AU^~$W8FDdnU؈Re/)td D'\ү9d uyi.A=ñi's!b2,9#0('rznT S 184l93[n`} B@*Z}Y_S EU$c^jvy򥈂y9Ey̻r]*уNM{oZE܈INH77 ٕ<8}bU* T"`>!R)0dxs̚(je[p|*&D\XJ5#biG[E*Baz:<= l'4|AzgJ[UQTz9g irn SaD>ӌgSj +dEx6 yg/Nj:}03O a7뽼>vB`:)N@3yFq|C<+WLRP8_)8QqJ,9B7RxuIv +UēDd,yLҚ R0צ:;D:2G9N~Ao9䡛:4SA{bF=ƴic%4dU 朼B1N? VMi7>7@$W>T23M4=1YD(XHy~NZ M /L=dw Q|UχY7 ĻY5nj%> endobj +649 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[0 1 1] +/Rect [441.227 144.658 562.273 156.613] +/Subtype/Link/A<> +>> endobj +644 0 obj << +/D [642 0 R /XYZ 109.858 727.97 null] +>> endobj +70 0 obj << +/D [642 0 R /XYZ 109.858 703.064 null] +>> endobj +645 0 obj << +/D [642 0 R /XYZ 109.858 444.305 null] +>> endobj +74 0 obj << +/D [642 0 R /XYZ 109.858 429.529 null] +>> endobj +641 0 obj << +/Font << /F29 416 0 R /F28 380 0 R /F8 369 0 R /F20 385 0 R /F49 648 0 R /F19 516 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +652 0 obj << +/Length 989 +/Filter /FlateDecode +>> +stream +xڍVoF_"-KuV*j{ 4΂FU3fv>~b-7 2q*vJxD7D\odD[c=J5KmJ'fqBkY0zЄ!Ee9W?K|xWP{euϞlM}T'`+kxjroRa$aJY_vlHyx Eª^O0];`lα6MѳV1WVC Uq$?AQĖ*.b61 X3k|0P*5l!N ![@ )n!;hv#Nôha3D7EOX{%`"Mw8MwSvYO5[(&|,6Kӝۉ֚E+t4UG)`XHqATs0}"V 158K2 .L ԭkHK9엯Z^Q_O?{.8QlJy3mFOPD#)y %D(aCC&u[95qEGظyטnpx%in(K%ȯsT^?H]<|<8$-F܃Ž(lv㖏u[|f8ۖ-pBb}&iHchP8);faȬ +k:E,ƙnˢEI=x6k0R}ڊ:JPcɲ*JáSא|}}h4ss/c+=VQ  Kvl&{j Ǟ]J2Hkҝ^.2Z#{1G1|օ&]K3Vd᨟Ola/8掓u8:Hs69=1\ .nߝWOT_?"4\rpo endstream +endobj +651 0 obj << +/Type /Page +/Contents 652 0 R +/Resources 650 0 R +/MediaBox [0 0 612 792] +/Parent 610 0 R +/Annots [ 654 0 R ] +>> endobj +654 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[0 1 1] +/Rect [339.905 603.492 486.274 614.341] +/Subtype/Link/A<> +>> endobj +653 0 obj << +/D [651 0 R /XYZ 109.858 727.97 null] +>> endobj +655 0 obj << +/D [651 0 R /XYZ 109.858 604.489 null] +>> endobj +650 0 obj << +/Font << /F29 416 0 R /F20 385 0 R /F8 369 0 R /F49 648 0 R /F19 516 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +658 0 obj << +/Length 1738 +/Filter /FlateDecode +>> +stream +xYێ6}WQ~0+H-h.. ̓bY#l|gx)[(`]8sfC& LDdd'xӄZDo8ʆ^Δ$'3!Fh/x+"'TRf> AD2_%@gL?_%"B.,Ys (L*ԫHC[q撑P7YL 2QDqS˔ItFӧiA +EG@:=tn GFŅA!*y`Nd'ON +eq7Ⱦ:^po.NIɯApWgڋ#ȌabD$e,7S&/p^V#ROgALk~0.x-@p(6̣jglk3X>vFFdx9pyW{֘i4 $z^Ƽ B)(oU/N d~Ĩi >6 +׿mLTտWSBqO35pp(<mNPc QJQОqz%@Z_&[/КoVL`B 8;LXbU8h=y, Yay}]oP/@9( t'PXB0l߶Uhj#MoCpUgF01 T|mL)FdO[*`aBsQu@7CS\)TE-_Ni~׳{z0Ћ]?hVG< שѳQJG +GŌFC5pp(<;Ç[&HF3"s#At5c~\YpbFF3C{ɬ۸ R`& B!DUUwfzMuoS}{ +}YBA)+(&6Dt3x LgCm ZE0LR)X +~&0Nu8\ap +4{i@oendstream +endobj +657 0 obj << +/Type /Page +/Contents 658 0 R +/Resources 656 0 R +/MediaBox [0 0 612 792] +/Parent 610 0 R +/Annots [ 660 0 R 661 0 R 662 0 R 663 0 R 664 0 R 665 0 R 666 0 R 667 0 R 668 0 R 676 0 R 677 0 R 678 0 R 679 0 R ] +>> endobj +660 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [133.768 412.657 174.698 423.506] +/Subtype /Link +/A << /S /GoTo /D (tbx) >> +>> endobj +661 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [133.768 392.732 215.711 403.58] +/Subtype /Link +/A << /S /GoTo /D (tbxdkpanels) >> +>> endobj +662 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [133.768 372.807 214.743 383.655] +/Subtype /Link +/A << /S /GoTo /D (tbxextitems) >> +>> endobj +663 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [133.768 352.882 195.426 363.73] +/Subtype /Link +/A << /S /GoTo /D (tbxlists) >> +>> endobj +664 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [133.768 332.956 195.039 343.804] +/Subtype /Link +/A << /S /GoTo /D (tbxmdi) >> +>> endobj +665 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [133.768 313.031 222.298 323.879] +/Subtype /Link +/A << /S /GoTo /D (tbxstatusbars) >> +>> endobj +666 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [133.768 293.106 212.086 303.954] +/Subtype /Link +/A << /S /GoTo /D (tbxswitcher) >> +>> endobj +667 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [133.768 273.18 208.516 284.029] +/Subtype /Link +/A << /S /GoTo /D (tbxthemes) >> +>> endobj +668 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [133.768 253.255 212.252 264.103] +/Subtype /Link +/A << /S /GoTo /D (tbxtoolpals) >> +>> endobj +676 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [133.768 131.335 193.027 141.297] +/Subtype /Link +/A << /S /GoTo /D (tfontsettings) >> +>> endobj +677 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [133.768 116.391 212.223 126.353] +/Subtype /Link +/A << /S /GoTo /D (ttbxcustomitem) >> +>> endobj +678 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [133.768 101.447 183.115 111.409] +/Subtype /Link +/A << /S /GoTo /D (ttbxdock) >> +>> endobj +679 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [133.768 86.503 181.198 96.465] +/Subtype /Link +/A << /S /GoTo /D (ttbxitem) >> +>> endobj +659 0 obj << +/D [657 0 R /XYZ 109.858 727.97 null] +>> endobj +78 0 obj << +/D [657 0 R /XYZ 109.858 703.064 null] +>> endobj +669 0 obj << +/D [657 0 R /XYZ 109.858 244.289 null] +>> endobj +82 0 obj << +/D [657 0 R /XYZ 109.858 229.276 null] +>> endobj +656 0 obj << +/Font << /F28 380 0 R /F22 363 0 R /F8 369 0 R /F14 372 0 R /F50 672 0 R /F51 675 0 R /F29 416 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +694 0 obj << +/Length 2152 +/Filter /FlateDecode +>> +stream +xڭZ[۶~_GxěD8Iڴ)"h]bђ(u,G7áF4-*YNus +B(fV*"<-3SSrdTx9L($Q'Hv>|rN=Mi0Xn@AN,gށNY}cN3Fa]cL}fpm:m3dĨ[\ +M4&}|97ðY9$zOa&2V+4*.>3E Ѯ914Y¬!XmjFKJ'|FG +>:*=!I%LŴ1z zg`ξov(Wlm0Ӄ;J(#$ٖ;$3;?v:(<-3s n;NE1m"`*syKBAؕ=y[ZHhyT{Ʊ9z ĜaE[n|XNU ^jSq?ؚ[~_d]%UɟTw۪)-a / +<6p\a{ш\bjWu 1Sm|ki`=6Ł}K1}KVo&G +)]耛|ޭ5E,_ca=A"CeDq$,Px`#lvuqMY.Z+A/p[ľT`Τ"N_YtC&uRjZ/j0U$K #=U_[*uY4.ϻ = Bxw5jeqAU\`>oN-|U@^ +J_a3q?%^m\t`Ԛf.hAqOrmxMbRZylTd`U@3*`i);> endobj +696 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [133.768 690.361 211.019 700.324] +/Subtype /Link +/A << /S /GoTo /D (ttbxpopupmenu) >> +>> endobj +697 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [133.768 675.417 220.152 685.38] +/Subtype /Link +/A << /S /GoTo /D (ttbxseparatoritem) >> +>> endobj +698 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [133.768 660.473 218.319 670.436] +/Subtype /Link +/A << /S /GoTo /D (ttbxsubmenuitem) >> +>> endobj +699 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [133.768 645.529 193.76 655.492] +/Subtype /Link +/A << /S /GoTo /D (ttbxtoolbar) >> +>> endobj +700 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [133.768 630.585 213.704 640.548] +/Subtype /Link +/A << /S /GoTo /D (ttbxtoolwindow) >> +>> endobj +701 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [133.768 615.641 244.223 625.604] +/Subtype /Link +/A << /S /GoTo /D (ttbxvisibilitytoggleitem) >> +>> endobj +702 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [133.768 582.765 227.919 592.727] +/Subtype /Link +/A << /S /GoTo /D (addthemenotification) >> +>> endobj +703 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [133.768 569.564 207.402 577.783] +/Subtype /Link +/A << /S /GoTo /D (geteffectivecolor) >> +>> endobj +704 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [133.768 552.877 242.389 562.839] +/Subtype /Link +/A << /S /GoTo /D (removethemenotification) >> +>> endobj +705 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [133.768 539.676 214.781 547.895] +/Subtype /Link +/A << /S /GoTo /D (tbxcurrenttheme) >> +>> endobj +706 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [133.768 524.732 196.309 532.951] +/Subtype /Link +/A << /S /GoTo /D (tbxsettheme) >> +>> endobj +707 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [133.768 490.112 235.562 499.975] +/Subtype /Link +/A << /S /GoTo /D (ttbxitemtransparency) >> +>> endobj +708 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [133.768 476.912 175.462 485.031] +/Subtype /Link +/A << /S /GoTo /D (ttristate) >> +>> endobj +709 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [133.768 444.035 194.945 452.254] +/Subtype /Link +/A << /S /GoTo /D (currenttheme) >> +>> endobj +720 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [145.199 197.938 183.66 205.465] +/Subtype /Link +/A << /S /GoTo /D (ttristate) >> +>> endobj +695 0 obj << +/D [693 0 R /XYZ 109.858 727.97 null] +>> endobj +688 0 obj << +/D [693 0 R /XYZ 109.858 441.046 null] +>> endobj +86 0 obj << +/D [693 0 R /XYZ 109.858 434.307 null] +>> endobj +710 0 obj << +/D [693 0 R /XYZ 109.858 277.266 null] +>> endobj +721 0 obj << +/D [693 0 R /XYZ 109.858 198.934 null] +>> endobj +722 0 obj << +/D [693 0 R /XYZ 109.858 133.3 null] +>> endobj +692 0 obj << +/Font << /F29 416 0 R /F51 675 0 R /F50 672 0 R /F28 380 0 R /F8 369 0 R /F54 713 0 R /F22 363 0 R /F41 556 0 R /F55 716 0 R /F34 719 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +738 0 obj << +/Length 1836 +/Filter /FlateDecode +>> +stream +xXKo6W(zv6=hF$9+&n%mw}Qp2O2*D 3Qdru0ۉtD<&ΉF[ q#ecQRssTX<HĪV'J"rׯOO\ OPir;]&./G𽹚*4ifyɯ.2'y@(=j*SyEc{n-N?M١<Ez% +RkLZ?'9'#-!#IemlaiRQ;PQLem3IXXR"O I|B;6%] )(\oL VrX(U [q6O +5RОeo~ry!TI1bd.ȋ9g|twIۺ}7]534ם)x'!Es@Ngf(ۙ uNT@psΆ^^9ru=vj3s fL('1ʕy.%JDV<-`ag`wnz;bz6.2+ vV +άB̍i<#z7ؐ7{mVl TVnb*^APKE *v1``B_sK5 \ڭT:b%lx"ca(uI@+)G!E}LA:bD{}f +S ]rG +G5c-wuzo)EFiMѤ - '~Ǭ+wNu4=4Ъud`]r`vi竲=p'O8?U5 +X<)iLK9Iw-.m~p +&-C !p,8{aMecmˡ+`H= ]I.EM[YP!UMZ#*bEꪆ:wE;ٶ׫=pZ- q,/ hJ +))ZnQwaF4Uч,+bIh1P.閭ܳS JhVyPgnB+_b`C<\2ٙ~1?;@0 uJp##q ƢL#N-'6Gj1"|J,TuWBC\v̨-qBYʑa͚PM$T5ɦea[ImK_nЦls}dq$VCb/K*VuDg}UV|1(Q(88K(ڝf-/wd+ݗ;;LQͦ'W7qG߻>)?w˫5endstream +endobj +737 0 obj << +/Type /Page +/Contents 738 0 R +/Resources 736 0 R +/MediaBox [0 0 612 792] +/Parent 723 0 R +/Annots [ 744 0 R ] +>> endobj +744 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [385.598 93.86 436.711 104.709] +/Subtype /Link +/A << /S /GoTo /D (ttbxitem) >> +>> endobj +739 0 obj << +/D [737 0 R /XYZ 109.858 727.97 null] +>> endobj +740 0 obj << +/D [737 0 R /XYZ 109.858 645.51 null] +>> endobj +741 0 obj << +/D [737 0 R /XYZ 109.858 571.91 null] +>> endobj +742 0 obj << +/D [737 0 R /XYZ 109.858 474.838 null] +>> endobj +743 0 obj << +/D [737 0 R /XYZ 109.858 399.739 null] +>> endobj +689 0 obj << +/D [737 0 R /XYZ 109.858 326.577 null] +>> endobj +90 0 obj << +/D [737 0 R /XYZ 109.858 315.853 null] +>> endobj +736 0 obj << +/Font << /F29 416 0 R /F54 713 0 R /F22 363 0 R /F41 556 0 R /F8 369 0 R /F28 380 0 R /F50 672 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +747 0 obj << +/Length 2005 +/Filter /FlateDecode +>> +stream +xڝYr6}W xIqNI4VI@[/*IUv"ubq s'A8q4vY+N,Ic,ֽ-PV2pI\}8sh4q6X(S*eawyuw`Ō`j8=zv&L={tHf/ y{f]2,D|aVĤX_00LOuћ3[eb K%O%̇a0n!sy:>Mk%帋*55tةxlp Ce㙦5.}Se=)u\>,ڴz/3Bг34+Y) 60Bnm<_Ei+% po"d0XuE6HiK=mFЁMmF&cAPe(76+m_FӃ:K-•;C;NcmaKc񢗗8vCS!`#Th }^uYf{2/23PŎF^W ? 1Sa/Ew8T2c$|8q1L|1s8 ; ?J + [ܾ ^fx*="nϊbfxl 1 lgmj6m/>;[é":Ѡ@V/L_jؘ]!{V,2 yi댒F VA .lu=-4p-I>#8GbX<NKZF۔/_wcLv"<`2&f9Nl?R1< +] N-INɜD,1Fo)r]Z4 $"])w% BV3joU2b<Fp8i#Uܻ›2"U{j~ R=f CN6aTi2JY L2d:[MǤ +Yɪ#cjE.`w&:k S>$b?+mDyvƑ9gk|Ty2mZݾAxCD4ؔ `X๮' +F /oԬI~Sh:ˆAK8 L(u_ M25h$PxQmM?%S AkkCX̷g׼X,:>Tg#cnE.+m ԅ;/ex[R5KdjU_QMHSϑI$U&FFMƬtq\v>+DFE)lH0&)rq~̼)>}ӬL )ܾAID/aLUB[ *t̯bA,΋𱐳"]zpdaʬ(wkp],C2> ڦo +8hjdY=0~8 |Txi!Xu' g)R-AW|O| +aվ.ƾHd%ĺʄP|s! ?[M[Z\A~C]N)B|d{$s +îbK`5OCZa`RsVBW@X'aeNaٵcܡC>buEe_gz hU 4?7endstream +endobj +746 0 obj << +/Type /Page +/Contents 747 0 R +/Resources 745 0 R +/MediaBox [0 0 612 792] +/Parent 723 0 R +/Annots [ 751 0 R 752 0 R 758 0 R 759 0 R ] +>> endobj +751 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [126.02 510.55 190.473 521.399] +/Subtype /Link +/A << /S /GoTo /D (ttbxcustomitem.onadjustfont) >> +>> endobj +752 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [145.199 494.001 222.015 503.078] +/Subtype /Link +/A << /S /GoTo /D (tfontsettings) >> +>> endobj +758 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [247.204 130.259 321.509 141.108] +/Subtype /Link +/A << /S /GoTo /D (ttbxstringlist) >> +>> endobj +759 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [325.605 130.259 406.745 141.108] +/Subtype /Link +/A << /S /GoTo /D (ttbxtoolpalette) >> +>> endobj +748 0 obj << +/D [746 0 R /XYZ 109.858 727.97 null] +>> endobj +749 0 obj << +/D [746 0 R /XYZ 109.858 681.914 null] +>> endobj +750 0 obj << +/D [746 0 R /XYZ 109.858 604.136 null] +>> endobj +753 0 obj << +/D [746 0 R /XYZ 109.858 494.998 null] +>> endobj +754 0 obj << +/D [746 0 R /XYZ 109.858 411.546 null] +>> endobj +755 0 obj << +/D [746 0 R /XYZ 109.858 346.027 null] +>> endobj +756 0 obj << +/D [746 0 R /XYZ 109.858 282.445 null] +>> endobj +757 0 obj << +/D [746 0 R /XYZ 109.858 208.73 null] +>> endobj +745 0 obj << +/Font << /F29 416 0 R /F28 380 0 R /F22 363 0 R /F41 556 0 R /F8 369 0 R /F55 716 0 R /F34 719 0 R /F54 713 0 R /F19 516 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +765 0 obj << +/Length 2167 +/Filter /FlateDecode +>> +stream +xڭnF_G;W0퍃8;Q,_IPH&LDєd$e:I;91<,d5L 00ejnvW=ڲ5:J*f2F'1 +HzeHxKzF.1K*cY8/,l&5FI bWuWŒEJXtR<ܺ|E ?Xvf1Gp#&$?PYk)QLq>Vץ^=Vcf2e),a^7z %1|l-~Q{=M5/aJ"op Q7.CwkIagldžn <^y*+rȃeX+h/BL5*` cˬlCi$a,,k YbYC]W0R->%݉kXBմ@ݼ*]USk2Pݿ!^KU&_!u`M|k4jtUgtVA҄"7~k#HL;]ƾʸr8#(1KFe32k\BGiB hlT݇'U7Usͧ%@y&l갻3Y)r$lnr +H7:je +e$O\&8&;EP̓ChDTN30## }~׷W#vQȲlv.9vN7ozGkRd Gp9%.Nz!Fl:^0zaaǼ7兎;xaB,煞X?,N]1 bi[W>Ű5cf2{G>!3{O_Bxy:v\b UOpk ?v)terFd"rz|-;v0~akL7e;B,gX?|rdRM7g̲(t‹O|+CCLIaЁ_CP/Œnh8x!On5dɱdq">0Tちj402910Ч:Ǧ.y_ h5ef`ph,hoZ_|hb@H15z`? w> +Pkm]"Yݔ.L{/|$@xhq. v(kjͪcb"{~C$9sU|n>^zN܅ı߬khnva~p p2arr=n3CTܢ3 dˠC똃N<Ȅ\BW&k3rQJn~9@ZV&_z0[.?}(HeG,TpVh71endstream +endobj +764 0 obj << +/Type /Page +/Contents 765 0 R +/Resources 763 0 R +/MediaBox [0 0 612 792] +/Parent 723 0 R +/Annots [ 767 0 R 768 0 R 770 0 R ] +>> endobj +767 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [465.496 463.663 522.2 474.511] +/Subtype /Link +/A << /S /GoTo /D (ttbxcustomitem.fontsettings) >> +>> endobj +768 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [469.344 451.707 526.048 462.556] +/Subtype /Link +/A << /S /GoTo /D (ttbxcustomitem.fontsettings) >> +>> endobj +770 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [234.031 206.69 298.484 217.538] +/Subtype /Link +/A << /S /GoTo /D (ttbxcustomitem.onadjustfont) >> +>> endobj +766 0 obj << +/D [764 0 R /XYZ 109.858 727.97 null] +>> endobj +760 0 obj << +/D [764 0 R /XYZ 109.858 681.914 null] +>> endobj +769 0 obj << +/D [764 0 R /XYZ 109.858 296.235 null] +>> endobj +690 0 obj << +/D [764 0 R /XYZ 109.858 207.686 null] +>> endobj +94 0 obj << +/D [764 0 R /XYZ 109.858 196.963 null] +>> endobj +763 0 obj << +/Font << /F29 416 0 R /F28 380 0 R /F54 713 0 R /F22 363 0 R /F41 556 0 R /F8 369 0 R /F20 385 0 R /F19 516 0 R /F14 372 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +774 0 obj << +/Length 1750 +/Filter /FlateDecode +>> +stream +xڥXK6W=I@ĈIdMΡH] Ak˶r$9ᐒ6$5f8fҋ\WLLRέ?)" a 1aQҰOEd'-xbof͙$ع :;RuU.iޓn\* 0p cx{uw*Ý\M4js(%=]uV:fexWoIo}(,牾 XG5~C_4?z H0衹 C"Z#ZكRSlNDŽ֛_@hBQJ.(V +ÃO>2Rފ |l}݌f83*RA2&5*ϩ ӷ'5vƣF4q~Z$o{1NLv&tc>~ Ec< N +\93lA4E,K,uyȳʡ'z-R@$0H7A5pnWǀ@usa[2Je,>R*WAtYߝl<)N +</b4H0\T%dpUݺe.|T8mY:NY 'gQjQt63\~vg, +JՖYI\*O(}@f9[[9 `zW76cdK~/zLB"TaTRVp؉ Y:.|QӬ:iHt|2c:Nk{sexv\!9e \dWmAeݶh[׀B:[8.؅ 4κT.Ӕmp 8+QίL@fK0?j^v&xUCZD*T7wʻc;W +x}/D 7)/d`gf/s7Ý%/gWP@D0Y1ȄkG>돀G00?1''҂/}_3PӔӂ,Rc&U<>X9Нxn`lh->`u!g5̱ 57䪢}@hD$(a3 '箂`hl!&-CqxD4qQ.6.PnxoiRݾxѢh{2L P]NSh3҇9ز zP!5IW< +&Rf8/NӿҒЈ4YHendstream +endobj +773 0 obj << +/Type /Page +/Contents 774 0 R +/Resources 772 0 R +/MediaBox [0 0 612 792] +/Parent 723 0 R +/Annots [ 776 0 R 778 0 R 779 0 R ] +>> endobj +771 0 obj << +/Type /XObject +/Subtype /Form +/FormType 1 +/PTEX.FileName (c_ttbxitem.pdf) +/PTEX.PageNumber 1 +/PTEX.InfoDict 780 0 R +/Matrix [1.00000000 0.00000000 0.00000000 1.00000000 0.00000000 0.00000000] +/BBox [0.00000000 0.00000000 15.00000000 15.00000000] +/PieceInfo << +/AdobePhotoshop << +/LastModified (D:20030406201243-05'00') +/Private << +/RoundTrip 1 +/ExportCrispy false +/SaveTransparency false +/ImageResources 781 0 R +/XObject << +/Im0 782 0 R +>> +/StandardImageFileData 783 0 R +>> +>> +>> +/Resources << +/XObject << +/Im0 782 0 R +>>/ProcSet [ /PDF /ImageC ] +>> +/Length 784 0 R +>> +stream +q q 15 0 0 15 0 0 cm /Im0 Do Q Q endstream +endobj +780 0 obj +<< +/Creator (Adobe Photoshop 7.0) +/CreationDate (D:20030406201243-05'00') +/ModDate (D:20030406201243-05'00') +/Producer (Adobe Photoshop for Windows) +>> +endobj +781 0 obj +<< +/Filter /FlateDecode +/Size 2550 +/Length 785 0 R +>> +stream +HVklU>wfnmAT(A( ֲRQ4eݝ-ha\Y='4dp$ya/'F2,彇8uQbD ,^( z݁*g+bvY!Ηr^O(ByY jO%l ԰ b( 3IxPQ[sA_J=^k/[,U<2:q/Y'9RIOl#{hTu, .1+a_8V4hBgmm* mRu3uA[??{MHp,*Q +(^609_U0хӱhNGqE$u3N/<0^y|D@)$>U^QBl}s2%vk` W^X zFZ1NgLN'L&DO(>..h0$ Y f)o1( (#H8N P!FDxs +JF2&R RPJJhSEԙZV[U]ŏ'Wpf+QOX| W 7^(}.;ϛp|]k!xq|_C'. ~C56~}+ ,o۴?]ihZ%f%)04Һ,"8P}zvMGdW 4@{8mlI\C?F(A]绞5Q3`cg_I)9{rN(>Os_5fw\_\}2w֬Ǡkeh)#=+imIvIqys76\jJhwe^N*:Rn(t΍M=m-|ю}=wJ;Oj3M}rlwx\k+o U϶y'oq|HaߝGG ^Tyo_*pZꪩ-Y">0 {#!,wH#a3C ( @YMN`oB>CLn?umif<ƣVJ:uQs|gZjdXr +,yVKA '$OP-t;Jh*?JGG΁2Hd 0Fjqendstream +endobj +782 0 obj +<< +/Type /XObject +/Subtype /Image +/Interpolate false +/Filter /FlateDecode +/DecodeParms << +/Predictor 2 +/Colors 3 +/BitsPerComponent 8 +/Columns 20 +>> +/Width 20 +/Height 20 +/BitsPerComponent 8 +/ColorSpace /DeviceRGB +/Length 786 0 R +>> +stream +H쓭 +@   Z76lϲ>#>u6=0+ {A{=˲Hjyqa˲(0mۦi[ei*Bx$I(Y4-2 â(,c +DY>Xl׻!MDZm+,(cخN:-J=eY@E33u]߂" _ŧΠX|*m ) endstream +endobj +783 0 obj +<< +/Length 787 0 R +>> +stream +endstream +endobj +784 0 obj +34 +endobj +785 0 obj +1387 +endobj +786 0 obj +246 +endobj +787 0 obj +0 +endobj +776 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [318.548 543.454 417.234 554.302] +/Subtype /Link +/A << /S /GoTo /D (ttbxdock.useparntbckgrnd) >> +>> endobj +778 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [108.862 311.216 187.316 319.335] +/Subtype /Link +/A << /S /GoTo /D (ttbxcustomitem) >> +>> endobj +779 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [365.794 209.866 450.449 220.715] +/Subtype /Link +/A << /S /GoTo /D (ttbxcustomitem) >> +>> endobj +775 0 obj << +/D [773 0 R /XYZ 109.858 727.97 null] +>> endobj +777 0 obj << +/D [773 0 R /XYZ 109.858 506.297 null] +>> endobj +691 0 obj << +/D [773 0 R /XYZ 109.858 440.59 null] +>> endobj +98 0 obj << +/D [773 0 R /XYZ 109.858 429.866 null] +>> endobj +724 0 obj << +/D [773 0 R /XYZ 109.858 198.908 null] +>> endobj +772 0 obj << +/Font << /F29 416 0 R /F28 380 0 R /F50 672 0 R /F8 369 0 R /F54 713 0 R /F22 363 0 R /F41 556 0 R >> +/XObject << /Im9 771 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +792 0 obj << +/Length 1447 +/Filter /FlateDecode +>> +stream +xڵWYoF~ׯ# xlT%= $D[(!dN€3̬OxFȄ[ܻ?IJ4!Į &IԠۀMØ3[0n^.G+x@ ^+xjwi<;_zN 6m y΃ϫVEAN%9lyPt{P*z׬:`Sf0LI 硪(#0EϡDNPLxp a{]f]@Inͻ +OXST&> + +,B` TJ &_0JA\{;gU@:zű,x?7qM^]@HT8:ՐJEfp_s8FML /'/x'r+ +A*s#f3HCn [̘p(*5| cCG?mS0BonM_@r"p%v=zϲ ):fmޔںrG=m֭jy\h\ z!ljWyNG +uyq67fK~7 +84uV +% G5PuiW79TJ` @_ke9y1@B,JļĜD'΄)AEDb "i~.uk*(n+#38Rk [yVr3g& 02NU[PQ7ctM 0C[lt#̙!%Moj?K1i^pka*a" j9a۲ۅdi [RhyY|Bwb}O'j#c8:)2>X"8,:xr5~Xa_ 2,Bx1,ط;#+Kl-?Qh*ApiWc J(F^(0aڑߔE"i}yYC kȿhr}Q]nῬvemF\>)qw邝;+X) +HfuHo !M7mw3 +M|KqgeuױӟͯO$Rmendstream +endobj +791 0 obj << +/Type /Page +/Contents 792 0 R +/Resources 790 0 R +/MediaBox [0 0 612 792] +/Parent 723 0 R +>> endobj +788 0 obj << +/Type /XObject +/Subtype /Form +/FormType 1 +/PTEX.FileName (c_ttbxpopupmenu.pdf) +/PTEX.PageNumber 1 +/PTEX.InfoDict 796 0 R +/Matrix [1.00000000 0.00000000 0.00000000 1.00000000 0.00000000 0.00000000] +/BBox [0.00000000 0.00000000 21.00000000 21.00000000] +/PieceInfo << +/AdobePhotoshop << +/LastModified (D:20030406201303-05'00') +/Private << +/RoundTrip 1 +/ExportCrispy false +/SaveTransparency false +/ImageResources 797 0 R +/XObject << +/Im0 798 0 R +>> +/StandardImageFileData 799 0 R +>> +>> +>> +/Resources << +/XObject << +/Im0 798 0 R +>>/ProcSet [ /PDF /ImageC ] +>> +/Length 800 0 R +>> +stream +q q 21 0 0 21 0 0 cm /Im0 Do Q Q endstream +endobj +796 0 obj +<< +/Creator (Adobe Photoshop 7.0) +/CreationDate (D:20030406201303-05'00') +/ModDate (D:20030406201303-05'00') +/Producer (Adobe Photoshop for Windows) +>> +endobj +797 0 obj +<< +/Filter /FlateDecode +/Size 2740 +/Length 801 0 R +>> +stream +HVyPW PQN[C2c)`8,ry eH$@dG-:TG-GjiUD)VJo_6(N̷}/ScR!7M>>_0aW D>`F2k\>Hr;0k3 -ȊǙѭvًD09?zg-9>mp8hA5GzXC{{yʬ5> ;z+y + PnH&ŀ:({'6L ۠]gja@)HNeLS*J*ĶLR%uj[d"Rd1#j 5DJ˜M62C>(C %i4L|P.:S1 &) ٠gBG(B/l50bdfd:6ђbT~S;$J$cbfJ$Ch3;;iHÒm)Wmf*"?Ϥ@ m3;8RK4WjMM;Y(Rf9ka#_$]b͋|IigvbF(`hoF_oI`pJ%1*RAƥHT˘Jt XBI(vrKE"X9J&FIňex\D"D!H<Ú"7oTc#p)F­s3X4D <@,^tbۜnb8 B.N)sʓ/({UaS / g&NDwĜ5?ZRӷH椴:^ lQ[Ej{MNeY]׿;Vi.? L{pv m~4(Z]Yuj?wSV%hl1?Ge x9r TjԚ!_VD7~Y\1@WX}L2و$=C/@0GG'0% b 1F;u\M`c勅+Y,.\U``!9ъfL IF "'న)QQ!PC~;f}Mc)p(~l ~g(~8-X gY 0kendstream +endobj +798 0 obj +<< +/Type /XObject +/Subtype /Image +/Interpolate false +/Filter /FlateDecode +/DecodeParms << +/Predictor 2 +/Colors 3 +/BitsPerComponent 8 +/Columns 28 +>> +/Width 28 +/Height 28 +/BitsPerComponent 8 +/ColorSpace /DeviceRGB +/Length 802 0 R +>> +stream +H̖10+((PAnfGGutk\P:ABO!m=˯RJAr:|߇ST2<HIY,B!ϧi~Ƕmyb1uF^7MS& X{!-S32SI:ELB$2Ryr]\X<&c*SA4N-(0މ lVVbVj\.aH>jؗ u mV}?=C/7[uģgJ{68/A&:Ӳ,lwTZ䉵ei.j5j|K LiyRZMp8ACeKl;a^oL͆ݘvK/ ‹dEbU"X׭V4{=yw'Q 2^r9̬F:#ENrx?4rP`>Ϙ endstream +endobj +799 0 obj +<< +/Length 803 0 R +>> +stream +endstream +endobj +800 0 obj +34 +endobj +801 0 obj +1587 +endobj +802 0 obj +513 +endobj +803 0 obj +0 +endobj +789 0 obj << +/Type /XObject +/Subtype /Form +/FormType 1 +/PTEX.FileName (c_ttbxseparatoritem.pdf) +/PTEX.PageNumber 1 +/PTEX.InfoDict 804 0 R +/Matrix [1.00000000 0.00000000 0.00000000 1.00000000 0.00000000 0.00000000] +/BBox [0.00000000 0.00000000 15.00000000 15.00000000] +/PieceInfo << +/AdobePhotoshop << +/LastModified (D:20030406201309-05'00') +/Private << +/RoundTrip 1 +/ExportCrispy false +/SaveTransparency false +/ImageResources 805 0 R +/XObject << +/Im0 806 0 R +>> +/StandardImageFileData 807 0 R +>> +>> +>> +/Resources << +/XObject << +/Im0 806 0 R +>>/ProcSet [ /PDF /ImageC ] +>> +/Length 808 0 R +>> +stream +q q 15 0 0 15 0 0 cm /Im0 Do Q Q endstream +endobj +804 0 obj +<< +/Creator (Adobe Photoshop 7.0) +/CreationDate (D:20030406201309-05'00') +/ModDate (D:20030406201309-05'00') +/Producer (Adobe Photoshop for Windows) +>> +endobj +805 0 obj +<< +/Filter /FlateDecode +/Size 2522 +/Length 809 0 R +>> +stream +HVylU޻v[@ԲQZڻUj1=ےa4H4@AD\1D +rSkA{3{ۼ{~ۉ%5 h"W[N@Ħʤ6s4hJ +T*?/TևeP*,i [x+`k`xL)X &Nיzh0ZRMĔQVk:b,J0 Ifsl6d!@ ގEXkAiuFAEQR +ͩNo0F 6&R!Q1jFfM9haUi]Y ۊ<26n;gB`RmFg3}`,,[-%mlxTw ykм'꿚xnGܩ?zWJ06^*wr_=)|Ӌ_>VCWnuǏo 츙xl=pZ坬ެ%~輬 isnMl*:رE+;r6_:!I}r~bǍ/;L̓(H6 ?{!ƃ"釕YSc +(@ j'?= e k9#rx4)2]iڧlwx8DŽG($> +/Width 20 +/Height 20 +/BitsPerComponent 8 +/ColorSpace /DeviceRGB +/Length 810 0 R +>> +stream +H1 +@EP" k#خe. (Xh!h`7ReϰogqDg}u 9y3۶mQy7M`%IRUUQQg,(!>1Ʀiʲbmd0\lE]UUg˲V쫬h,N{Ea wDi$=뚦Abl& {X23 +q|sNVAwŮy|`; endstream +endobj +807 0 obj +<< +/Length 811 0 R +>> +stream +endstream +endobj +808 0 obj +34 +endobj +809 0 obj +1354 +endobj +810 0 obj +250 +endobj +811 0 obj +0 +endobj +793 0 obj << +/D [791 0 R /XYZ 109.858 727.97 null] +>> endobj +102 0 obj << +/D [791 0 R /XYZ 109.858 703.064 null] +>> endobj +794 0 obj << +/D [791 0 R /XYZ 109.858 486.461 null] +>> endobj +725 0 obj << +/D [791 0 R /XYZ 109.858 420.753 null] +>> endobj +106 0 obj << +/D [791 0 R /XYZ 109.858 410.03 null] +>> endobj +795 0 obj << +/D [791 0 R /XYZ 109.858 189.984 null] +>> endobj +790 0 obj << +/Font << /F29 416 0 R /F28 380 0 R /F8 369 0 R /F50 672 0 R /F22 363 0 R /F41 556 0 R /F19 516 0 R /F54 713 0 R >> +/XObject << /Im10 788 0 R /Im11 789 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +816 0 obj << +/Length 1292 +/Filter /FlateDecode +>> +stream +xWYoF~ׯ# And=h$DE#$UCDIu13;7Ah@MT$2XU$ 7?Ψ9%J4#eČhç$Xw% +a&tPD wo)NQ<+T%{oQ8CDLEWԫ"x7~qH<ɍG2W?2E1c*.Z̟HaWDg gCVFϵL$,MoiI&Z +EtBRJk?öYhԘʕ|fDqdBxHGēFCG/jh:zA6J8$M"`r9MA)bΨ" )[?iKcG&F18<_{58I/%>N,Vp0s}z~Yu$=&$ Ccq9I3 -1x=,QDA;OŮU7!٣lp[Vk{[iߟ;\qT%ГŊ7o+ʂP!8CDGYV!u/~*)/ևirlؼ ˳08CS吝 bXZLg@. *l bK(*w + %iӌ |˜Z+ߚZ Y0?) k} iOS{hX.'YCѯʦ6x9X3 +Fx'l2{,46Srnݬ႞ޚƗ$<"3&\jˏji6he5( keE#!$"nl]CO9+ϡY'u_C}O/K^&IsLM+;v .붥C?_ . > endobj +812 0 obj << +/Type /XObject +/Subtype /Form +/FormType 1 +/PTEX.FileName (c_ttbxsubmenuitem.pdf) +/PTEX.PageNumber 1 +/PTEX.InfoDict 824 0 R +/Matrix [1.00000000 0.00000000 0.00000000 1.00000000 0.00000000 0.00000000] +/BBox [0.00000000 0.00000000 15.00000000 15.00000000] +/PieceInfo << +/AdobePhotoshop << +/LastModified (D:20030406201317-05'00') +/Private << +/RoundTrip 1 +/ExportCrispy false +/SaveTransparency false +/ImageResources 825 0 R +/XObject << +/Im0 826 0 R +>> +/StandardImageFileData 827 0 R +>> +>> +>> +/Resources << +/XObject << +/Im0 826 0 R +>>/ProcSet [ /PDF /ImageC ] +>> +/Length 828 0 R +>> +stream +q q 15 0 0 15 0 0 cm /Im0 Do Q Q endstream +endobj +824 0 obj +<< +/Creator (Adobe Photoshop 7.0) +/CreationDate (D:20030406201317-05'00') +/ModDate (D:20030406201317-05'00') +/Producer (Adobe Photoshop for Windows) +>> +endobj +825 0 obj +<< +/Filter /FlateDecode +/Size 2602 +/Length 829 0 R +>> +stream +HV}Pe$+ 76geh!U)׽IԴVOFÛ*le3'wVܠ<ۋޞ|wOxӗ~WY۰u3?e-ZN7nknϷ RI!e`RcD,mN=Dم;3,Lbw<ErNu-"n <  +I|O-K j>6堵|/?nck6Mm<>nUPr)Lunz1%I-`Gf-t>={z59v+hΏ~`*MkˏN\nصa>;P_ۮt]opP0p]h`gajc7_d|c#9}z|gG U7,ew@7 KiD=r Q`%`G<sCȂ0B#f3<˷>P1B<Wψ>sGDZߺ! 4GW| K x胐b41=87ۘiH3fgfჶq{%dϝ ElPD\?'1, S(ok'vendstream +endobj +826 0 obj +<< +/Type /XObject +/Subtype /Image +/Interpolate false +/Filter /FlateDecode +/DecodeParms << +/Predictor 2 +/Colors 3 +/BitsPerComponent 8 +/Columns 20 +>> +/Width 20 +/Height 20 +/BitsPerComponent 8 +/ColorSpace /DeviceRGB +/Length 830 0 R +>> +stream +H@]P + -l,H!O`WH)llTB09=n +v~g_UeYy Xu4 @"qkv k۶yZ%ؾNT.2sJiǎMʲ,K |Z+\TBs$ŸYި( +c\b9>cwkF]iqᆨ!`?.0 XJ؁2_I;cʽatQ܃عipEQU/T!<*[?1. endstream +endobj +827 0 obj +<< +/Length 831 0 R +>> +stream +endstream +endobj +828 0 obj +34 +endobj +829 0 obj +1441 +endobj +830 0 obj +292 +endobj +831 0 obj +0 +endobj +813 0 obj << +/Type /XObject +/Subtype /Form +/FormType 1 +/PTEX.FileName (c_ttbxtoolbar.pdf) +/PTEX.PageNumber 1 +/PTEX.InfoDict 832 0 R +/Matrix [1.00000000 0.00000000 0.00000000 1.00000000 0.00000000 0.00000000] +/BBox [0.00000000 0.00000000 21.00000000 21.00000000] +/PieceInfo << +/AdobePhotoshop << +/LastModified (D:20030406201321-05'00') +/Private << +/RoundTrip 1 +/ExportCrispy false +/SaveTransparency false +/ImageResources 833 0 R +/XObject << +/Im0 834 0 R +>> +/StandardImageFileData 835 0 R +>> +>> +>> +/Resources << +/XObject << +/Im0 834 0 R +>>/ProcSet [ /PDF /ImageC ] +>> +/Length 836 0 R +>> +stream +q q 21 0 0 21 0 0 cm /Im0 Do Q Q endstream +endobj +832 0 obj +<< +/Creator (Adobe Photoshop 7.0) +/CreationDate (D:20030406201321-05'00') +/ModDate (D:20030406201321-05'00') +/Producer (Adobe Photoshop for Windows) +>> +endobj +833 0 obj +<< +/Filter /FlateDecode +/Size 2668 +/Length 837 0 R +>> +stream +HV{PTU?w>e!DM3ȲIH0bHLCLvwwYũ?;}{ӓ3a%/M6|>| ÑMH\E =(#Oe8$Mx2G#OEEBYGqڝ-_Ce0~56gpmAΪqDó9 +'0B@V y=r#l,OtpK_j'IX@^je]l#@.ULRfG +'T /#bz,#a'3ll~ 2pH>gLnJTbj1[JR{ 9lPұijQJX4aB(#xgΙհsn%sS]i3nsf7H8bnK0P'R*ni5[]Q4뾌;r9")⪹yN cUʮ2*˲6blO\;:[jb|'EN`E|_Yi]0Gx07}.PiE2)@Hl&RT&Ud +CS)*?O\R*|J/;)}I| R@ 51n]!J/ 7'%R{Ԉ0zL@$KE"ոpw(EO5Z)~G 1ֵm)ʜ[om>lX>\S::ο= +q[_;uG';-LJZ:y>u=5 Z!$bQB`iHf/hvۭPeʔ?-v =ARh“LuA`~ +S />_zW{[vzTOZ6νAKm:{g+a@['w_fO€Β Gv5N^5Pwqx%1 :.  5oyy(`ՠ h ڜU=ca5]f2l+m2N,jmTWp|1p~p49W~8 NAwUCwuYzQ*/|qеu-꺚]A#G"s]u癇j\psCƜYK6Yj폽߸dե +ލҸWwxd4yowSGWCE_7+ +;Fu[Uz`♊rfى^fA)+ +.tj'_ewa7I/E @0X!^6ĕA:0 hKهgf& +$7<"SD ;c>Ģ+u6ZG(e>)[1Zt4@Dkb5qZM|Tt6 +=>`7p,px,~l ?4?t|,\4^F \]endstream +endobj +834 0 obj +<< +/Type /XObject +/Subtype /Image +/Interpolate false +/Filter /FlateDecode +/DecodeParms << +/Predictor 2 +/Colors 3 +/BitsPerComponent 8 +/Columns 28 +>> +/Width 28 +/Height 28 +/BitsPerComponent 8 +/ColorSpace /DeviceRGB +/Length 838 0 R +>> +stream +H1n0+ c92f \#C#H0t $> +stream +endstream +endobj +836 0 obj +34 +endobj +837 0 obj +1520 +endobj +838 0 obj +334 +endobj +839 0 obj +0 +endobj +819 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [144.893 615.095 164.044 625.943] +/Subtype /Link +/A << /S /GoTo /D (ttbxseparatortm.size) >> +>> endobj +820 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [108.862 486.716 187.316 494.836] +/Subtype /Link +/A << /S /GoTo /D (ttbxcustomitem) >> +>> endobj +817 0 obj << +/D [815 0 R /XYZ 109.858 727.97 null] +>> endobj +818 0 obj << +/D [815 0 R /XYZ 109.858 681.914 null] +>> endobj +726 0 obj << +/D [815 0 R /XYZ 109.858 616.091 null] +>> endobj +110 0 obj << +/D [815 0 R /XYZ 109.858 605.367 null] +>> endobj +821 0 obj << +/D [815 0 R /XYZ 109.858 377.102 null] +>> endobj +822 0 obj << +/D [815 0 R /XYZ 109.858 285.082 null] +>> endobj +727 0 obj << +/D [815 0 R /XYZ 109.858 233.152 null] +>> endobj +114 0 obj << +/D [815 0 R /XYZ 109.858 222.428 null] +>> endobj +814 0 obj << +/Font << /F29 416 0 R /F28 380 0 R /F22 363 0 R /F41 556 0 R /F8 369 0 R /F50 672 0 R /F54 713 0 R >> +/XObject << /Im12 812 0 R /Im13 813 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +842 0 obj << +/Length 2195 +/Filter /FlateDecode +>> +stream +xڝYs6_#S8ħVbsIe'u[C̺f 0sR.!jN?AD:Yy7+‹/% qhv=u /s#78pvŹt^`a;7qa&{s3^˜x$/C$dZ%;#ک%qqaĽJ-?O;z,GuY$%[ð' +͡{$\%A b2 3n&C8Zm!<~&aB@mDe٢:nUOn6x*TXDv2vbɴCD=t,HkabƏ0gXg)ć=@cX m',[v )k 27Ƈz'{ƴPl~& XD^hiM# q/(-0ZigOMdt"ɐBb鏮)K^qbQMS>}Z$-x<[?$wp_hY.J{4eźtE*m3m\P.lha{"u+~9LQڰP*Q)[/L+^j@᭭.79i +U욭(U1c|f}%=Z(v=H!%KA$i#Tޅ&量B'NCعJCz1'pUj`Z3$P>w,]Q'q 's_2n43pguDyk_'-"nQNG +C3&liZgUXˢ)M1҃DYrCa##IwVQpua)"bLMČ qLҤ.O%~43۱Gԧ@DN#(A8 cH +EYpB]Zl6A04qFt{Ctě 33H(%EOjsQ)AvHv+8"FncH% ~uCɈ }u> Ώ:X.Jbr[ƹP dNqB1T`A7vLKr=:| q/r7^oy=[vR@$F*?w!?(3tx0=Aa<Ά*CAtYaRPB\*ڱM/ }?XM=I&[]K-Qm"Z H-JiI,Pt\ѩB4܏ӘS6`xUtǧ [LGq -PFaa0OG3Ņ䨡prst=CY͠+@.ZO렁jPYQ9n3:˕46;R +Ss FfNBDUR- +ĉ3%UC!͔x(,,vsVY:j Vwv6 p//ӳҵ\;J=c-}8G!#=65M*8d6ſP f$zㇶLJora3}[E9C7l?zRd&iEXOtK+sQ'5RW,ꡱ6!acƽ%A-MYyզ'57ZwL~/D*})50$(q 7L{C|B䗗V7T}תv64U`=L8Ƶc"5|^qo +ԡԝh2KM d0A삩= w7Sr.[]> Bj+ջ'}>$^C *)endstream +endobj +841 0 obj << +/Type /Page +/Contents 842 0 R +/Resources 840 0 R +/MediaBox [0 0 612 792] +/Parent 823 0 R +/Annots [ 845 0 R 847 0 R ] +>> endobj +845 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [145.199 387.064 218.278 396.141] +/Subtype /Link +/A << /S /GoTo /D (ttbxtoolbar.updatechildclrs) >> +>> endobj +847 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [401.487 301.675 447.205 312.523] +/Subtype /Link +/A << /S /GoTo /D (ttbxtoolbar.embedded) >> +>> endobj +843 0 obj << +/D [841 0 R /XYZ 109.858 727.97 null] +>> endobj +844 0 obj << +/D [841 0 R /XYZ 109.858 494.342 null] +>> endobj +846 0 obj << +/D [841 0 R /XYZ 109.858 388.06 null] +>> endobj +848 0 obj << +/D [841 0 R /XYZ 109.858 302.671 null] +>> endobj +849 0 obj << +/D [841 0 R /XYZ 109.858 200.821 null] +>> endobj +850 0 obj << +/D [841 0 R /XYZ 109.858 134.998 null] +>> endobj +840 0 obj << +/Font << /F29 416 0 R /F28 380 0 R /F50 672 0 R /F8 369 0 R /F22 363 0 R /F41 556 0 R /F55 716 0 R /F34 719 0 R /F54 713 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +855 0 obj << +/Length 2281 +/Filter /FlateDecode +>> +stream +xڝYoF}spC$=VMi"} ظ`e3=9^?Qfq2 7v(f^j 2Ym~#J=`<= +νFy(|77#KJ ")sfyJ}07강گ괯߼܍Ep*}` h4.ߥLTye ,̓C%5CTR* e?%"a;FNt$Wq{yʲ*WI)%)=آpnO^[=ԃ9ܟֹ6ZǫLD21 X,2&cNǭXĊ2vgC=r#":6H+3 \599\pJB= +ơyfR^#ȸ *s6A:&[잊ynXgagLy]JihE38'1?j:&*D Z͏EztFVo~jO3'_OҝCMH-JujoKh47 'swCU ++([caT#:>KoT3pP)Nu=Yc !Р|֔AdACBN?0=K~szPg K1h77\U9(rm]u871'cphg`c0lBlc=<0 *~:"htCW:,!F<;RIAx: "xQ>OӵC@94( CUmL?`$IkX@r^>:<ȇryGKbUPFQěctkQpL,xl7w4i= sw6rz7/:w\yl>EFz-/Rf=FO: 8!h9c/hJFsta@K*H.e1!՜P]B;^oH5 YTnYa6 !endstream +endobj +854 0 obj << +/Type /Page +/Contents 855 0 R +/Resources 853 0 R +/MediaBox [0 0 612 792] +/Parent 823 0 R +/Annots [ 857 0 R 858 0 R 860 0 R ] +>> endobj +852 0 obj << +/Type /XObject +/Subtype /Form +/FormType 1 +/PTEX.FileName (c_ttbxtoolwindow.pdf) +/PTEX.PageNumber 1 +/PTEX.InfoDict 862 0 R +/Matrix [1.00000000 0.00000000 0.00000000 1.00000000 0.00000000 0.00000000] +/BBox [0.00000000 0.00000000 21.00000000 21.00000000] +/PieceInfo << +/AdobePhotoshop << +/LastModified (D:20030406201218-05'00') +/Private << +/RoundTrip 1 +/ExportCrispy false +/SaveTransparency false +/ImageResources 863 0 R +/XObject << +/Im0 864 0 R +>> +/StandardImageFileData 865 0 R +>> +>> +>> +/Resources << +/XObject << +/Im0 864 0 R +>>/ProcSet [ /PDF /ImageC ] +>> +/Length 866 0 R +>> +stream +q q 21 0 0 21 0 0 cm /Im0 Do Q Q endstream +endobj +862 0 obj +<< +/Creator (Adobe Photoshop 7.0) +/CreationDate (D:20030406201218-05'00') +/ModDate (D:20030406201218-05'00') +/Producer (Adobe Photoshop for Windows) +>> +endobj +863 0 obj +<< +/Filter /FlateDecode +/Size 2606 +/Length 867 0 R +>> +stream +HVypU/IӤi"mV4HhK &md7p$ Cp r㌀Z(Ł۷ {^&Xґ'x& )jzD6ii#eB4R4aXeU( +QqLO/ zٍR0Y(4(AuƄhirlDszh Y=ڧd0D۰pyUa 8@ `cL  cB~Be^'SflVht}*E{]43Z6Z.`:Q0]n6J3A2 !& ,Sr+\>_>%:$i*2Cr%X҉/'E8K+?QE/V?Vce\dFnJ+Fu(\ZJ ;MSAR8ܴoI>q* l4$km~>v:]mw*^(( x^~Ut}eQh5vE}DF?aw|b?J NËDXYAR~H[@ԧJQ|'m'k +@Z,2>w RRjT*^''h4 )C` ƫxVKjIMB&wh;C $zH! ں; b HIerR!!@)$$RL!WM62 iZb,!}r|ZAW+|WMh|F(ԙn7rh33O5LyYqq[$C^<}rH~8,?Rb!Q(oNendstream +endobj +864 0 obj +<< +/Type /XObject +/Subtype /Image +/Interpolate false +/Filter /FlateDecode +/DecodeParms << +/Predictor 2 +/Colors 3 +/BitsPerComponent 8 +/Columns 28 +>> +/Width 28 +/Height 28 +/BitsPerComponent 8 +/ColorSpace /DeviceRGB +/Length 868 0 R +>> +stream +H=0)(@$%r)nJHH > +stream +endstream +endobj +866 0 obj +34 +endobj +867 0 obj +1447 +endobj +868 0 obj +304 +endobj +869 0 obj +0 +endobj +857 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [284.888 537.538 348.206 548.387] +/Subtype /Link +/A << /S /GoTo /D (ttbxtoolbar.effectivecolor) >> +>> endobj +858 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [145.199 486.674 199.299 494.201] +/Subtype /Link +/A << /S /GoTo /D (ttbxtoolbar.effectivecolor) >> +>> endobj +860 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [145.199 161.284 218.278 170.361] +/Subtype /Link +/A << /S /GoTo /D (ttbxtoolwindow.updatechildclrs) >> +>> endobj +856 0 obj << +/D [854 0 R /XYZ 109.858 727.97 null] +>> endobj +851 0 obj << +/D [854 0 R /XYZ 109.858 643.079 null] +>> endobj +728 0 obj << +/D [854 0 R /XYZ 109.858 487.67 null] +>> endobj +118 0 obj << +/D [854 0 R /XYZ 109.858 476.946 null] +>> endobj +859 0 obj << +/D [854 0 R /XYZ 109.858 256.607 null] +>> endobj +861 0 obj << +/D [854 0 R /XYZ 109.858 162.28 null] +>> endobj +853 0 obj << +/Font << /F29 416 0 R /F22 363 0 R /F41 556 0 R /F8 369 0 R /F19 516 0 R /F55 716 0 R /F34 719 0 R /F28 380 0 R /F50 672 0 R >> +/XObject << /Im14 852 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +874 0 obj << +/Length 1961 +/Filter /FlateDecode +>> +stream +xڝXY6 ~У4S)⡃!qzlw43Mlk\Iv kw'%Jx1 O&ʓdޭb+߬SJDyev~uPF&7H?boҾ.mrHjݭtb"g.˴ᄘt3Z*2sق[c -ٝS?Bssπ!DȔCO3M*Y^ZZгl)R1HR/s遫'HMMCsԹB 4lki39VCim't@l6z⇲?6#`-ݺ-| +I\ Sp$9u}{M@YA*~eHĘ`lݹ9h#@aidjvh1!}Gp4͞h6W8~ +#&3osGAP m붨ks)R>"tt1WĻc^rS +&`-{P_UQ`lw8pnZ6gўyl_<,JbZzgwO !R0Lж]r 4ŊqP1(Yiy{@֎x-m>JI"\0"13 ݷMM0D +$q&fX"R`7A-k$v )̡ 0u|Qd XCkcXtc-FD W4K!/pibI wqW=۾iZ5{,w$eг[/E?r!bO!L uG/Z?CaIfgqIAҭ q ֥rj]/KuO? \<#ڗ cBWp]+ u`U+|%5 +Fw#ƪ igzŎmct1*#liGHjjE?vN[NXm!BJ:ՇX(s\|T:E1oqG B )'{o8> {eCms l aH. q\8J|U"9/:z#+DdM!cP1z!LtfPtO;³֗X)?s:&8NXׂ:zJXN¼90䂹*2]Ak]A͵S]siR#jou $8h+|怀|s֯l9R n—˕ j;/NK5?M}qK>;b;gOy <&uyL&\ʒ%X3=;<},@1/Pz\K狎 zY2IPc8rZ1JP>b>,:54Pj:p1ɵ. !P)B*׺.09.类PC˻Ef,2JR +KOhYh1 áv7{bTᵙՋ&8WQnT}@gxyם>\MYƯ8! +'–u]3Ub@K|'{lWKC$|y{$4J=~;~ӑu*`AŃ-xs؎7-& ̧x5SO1⿢endstream +endobj +873 0 obj << +/Type /Page +/Contents 874 0 R +/Resources 872 0 R +/MediaBox [0 0 612 792] +/Parent 823 0 R +/Annots [ 877 0 R 878 0 R 879 0 R ] +>> endobj +871 0 obj << +/Type /XObject +/Subtype /Form +/FormType 1 +/PTEX.FileName (c_ttbxvisibilitytoggleitem.pdf) +/PTEX.PageNumber 1 +/PTEX.InfoDict 880 0 R +/Matrix [1.00000000 0.00000000 0.00000000 1.00000000 0.00000000 0.00000000] +/BBox [0.00000000 0.00000000 15.00000000 15.00000000] +/PieceInfo << +/AdobePhotoshop << +/LastModified (D:20030406201222-05'00') +/Private << +/RoundTrip 1 +/ExportCrispy false +/SaveTransparency false +/ImageResources 881 0 R +/XObject << +/Im0 882 0 R +>> +/StandardImageFileData 883 0 R +>> +>> +>> +/Resources << +/XObject << +/Im0 882 0 R +>>/ProcSet [ /PDF /ImageC ] +>> +/Length 884 0 R +>> +stream +q q 15 0 0 15 0 0 cm /Im0 Do Q Q endstream +endobj +880 0 obj +<< +/Creator (Adobe Photoshop 7.0) +/CreationDate (D:20030406201222-05'00') +/ModDate (D:20030406201222-05'00') +/Producer (Adobe Photoshop for Windows) +>> +endobj +881 0 obj +<< +/Filter /FlateDecode +/Size 2632 +/Length 885 0 R +>> +stream +HV{TUfg_좄HY'H#@^0=, ;3?>"?ǑH;huP9 PZ ssgxNߜ=w)2Ap2lf #͂MmZ_DF1JE9,?(XbT$`)Q,ȢGBXT],4Riݹ˫1e4z4ix|ڧ9~F"o ކSȒ-[5QVË^$`3p:h-iG̀=4PXCA!C<;4&¸6Rkˬ\gkLC,84˩j_zI05dibWY!{؆UX(Z[ew1q9't A%X*7PNUQ6~}%9΂Fcn]"k4*V +Q"´0`P{A5laT*L|G-TFUWiNpo\ +=@=_qub@N xq +s49/\0 +Vca8T!':^ROÉ=P#dTYY\!} D_@ E@Ի +QWMP\Ab lL|/4FV5AA]Hp.2L #(4LDhHH64\ 7hZ0h b$Nc 8RGeq" ThsrR +!7 #=p )*ZAjRQGE$+WTl2* [<>?%%յ+W\~ꐕMg&,{–w[<u@7gׇw?wcdq˛{o4%ڭ-~q:Z9ƤR*0yr`M^aܴ 8Zu'ekssnyMW +T iǺٶu }K!;u#O yֺpzsCʩ7gRRk[K'"n;{%z{3o[6z|\WFڧX%v[G<ʾ[3rJܑ]K;M3}w{uƦ= Q񧆮TL﫛rP6+Oxҩ=_u_54ӵN v%NO#_u\zPI}{Ԯ|mH.,8qbs̮xxs,ȩE澩>n*9Jd~`Cכ]jP +5h-\w,^5 ?xB:,$nO +mTD "ҙsZ ]}D2~" ~ifI35 ǰ5rH_Ƥ̤̤űƤdcшnB|yvt)aS'f1Qr 2_nJ2`5adendstream +endobj +882 0 obj +<< +/Type /XObject +/Subtype /Image +/Interpolate false +/Filter /FlateDecode +/DecodeParms << +/Predictor 2 +/Colors 3 +/BitsPerComponent 8 +/Columns 20 +>> +/Width 20 +/Height 20 +/BitsPerComponent 8 +/ColorSpace /DeviceRGB +/Length 886 0 R +>> +stream +H1n0ED)(E)RJ%{#9B +J@"_xXIX2`<[m.˂DٶmuA"ya~& ~Eaz'q۶Ee˲,ɢh4EQuaz:61duB]Z%`cbB Ly+أ4SP9X.;$IMXܗ;Rߤ98hDa^|Vރ8뺷 햦) g +WCBz]fS8 endstream +endobj +883 0 obj +<< +/Length 887 0 R +>> +stream +endstream +endobj +884 0 obj +34 +endobj +885 0 obj +1461 +endobj +886 0 obj +302 +endobj +887 0 obj +0 +endobj +877 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [284.888 445.458 348.206 456.306] +/Subtype /Link +/A << /S /GoTo /D (ttbxtoolwindow.effectivecolor) >> +>> endobj +878 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [145.199 394.593 199.299 402.121] +/Subtype /Link +/A << /S /GoTo /D (ttbxtoolwindow.effectivecolor) >> +>> endobj +879 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [108.862 264.278 187.316 272.397] +/Subtype /Link +/A << /S /GoTo /D (ttbxcustomitem) >> +>> endobj +875 0 obj << +/D [873 0 R /XYZ 109.858 727.97 null] +>> endobj +876 0 obj << +/D [873 0 R /XYZ 109.858 616.821 null] +>> endobj +870 0 obj << +/D [873 0 R /XYZ 109.858 550.999 null] +>> endobj +729 0 obj << +/D [873 0 R /XYZ 109.858 395.59 null] +>> endobj +122 0 obj << +/D [873 0 R /XYZ 109.858 384.866 null] +>> endobj +872 0 obj << +/Font << /F29 416 0 R /F54 713 0 R /F22 363 0 R /F41 556 0 R /F8 369 0 R /F28 380 0 R /F19 516 0 R /F55 716 0 R /F34 719 0 R /F50 672 0 R >> +/XObject << /Im15 871 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +890 0 obj << +/Length 1841 +/Filter /FlateDecode +>> +stream +xڵXnF}W$Pn7^'qn@6aIJbK*Iwf/%JPٙ3sfIQFIe%,!YY-aՌZS09-ᇽd䅌diξ|9h{ Dz0 }1h1s7$.0)LX)gdg%@>P _jS[vvir:M*$Θk? fQi#8t`> 0QGVhkDciRrȿ .1:}-ԧcdHSSj]_m n<; Ea JF+ WxNA1I >a$| NdRw APFGS6dtoU&po@@<Kbr(uV-W7& +G8WlTPhẶ`"@[7ͻH +L!<ivpL'32+$2yvNDZΦB-%I|Aș}#tAoc9> endobj +894 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [145.199 436.928 245.154 444.455] +/Subtype /Link +/A << /S /GoTo /D (removethemenotification) >> +>> endobj +897 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [381.562 273.324 483.181 284.173] +/Subtype /Link +/A << /S /GoTo /D (addthemenotification) >> +>> endobj +891 0 obj << +/D [889 0 R /XYZ 109.858 727.97 null] +>> endobj +892 0 obj << +/D [889 0 R /XYZ 109.858 616.972 null] +>> endobj +126 0 obj << +/D [889 0 R /XYZ 109.858 552.381 null] +>> endobj +730 0 obj << +/D [889 0 R /XYZ 109.858 521.735 null] +>> endobj +893 0 obj << +/D [889 0 R /XYZ 109.858 521.735 null] +>> endobj +731 0 obj << +/D [889 0 R /XYZ 109.858 437.924 null] +>> endobj +895 0 obj << +/D [889 0 R /XYZ 109.858 429.345 null] +>> endobj +732 0 obj << +/D [889 0 R /XYZ 109.858 345.136 null] +>> endobj +896 0 obj << +/D [889 0 R /XYZ 109.858 336.557 null] +>> endobj +575 0 obj << +/D [889 0 R /XYZ 109.858 274.321 null] +>> endobj +898 0 obj << +/D [889 0 R /XYZ 109.858 265.742 null] +>> endobj +576 0 obj << +/D [889 0 R /XYZ 109.858 207.38 null] +>> endobj +899 0 obj << +/D [889 0 R /XYZ 109.858 198.801 null] +>> endobj +888 0 obj << +/Font << /F29 416 0 R /F28 380 0 R /F8 369 0 R /F54 713 0 R /F22 363 0 R /F41 556 0 R /F55 716 0 R /F34 719 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +902 0 obj << +/Length 2064 +/Filter /FlateDecode +>> +stream +xڵYێ6}߯ԬxӥEri)fݢ@b[$';ËDY٥!r2tdj{Vj,֜4jHfhEY07Bf%y͢%n k Hn}/77_aJ=oWlvtF`Ǔ9¬ɌS='cqf, ~=nm^NNydqgPxR0)PZtE"vȉHJM(T(T+-5L" c9HdO#.iLRV$jl׎+U5¡, +FA XN;HFe"QpnPDWE~B/B*eca0V)]e& # P + 6\Ӡ )xx\s.dNuVU=8-pHȸ@ŢmAB#Fkbh@qI}ۼ5;6oB YܿдݕG .#@S>bGTӝ ҍ؉a<zU֣7\LLjh6&;aBWX#Ǣ.b{>21u&ɋ@-I_5fo6a,Eo z=Pq+&d-a$rnoy]Bb']Nԫs ;Hy,ތ#=/z[_>KjPۜz^JW1s_]ܛo@gmˏ8X؉**Ɇ<4͏ž5g$Q38eU[OykXHFA#AD ɂuoQp-ck=* + tLN~|PkêSm; l^ٝبtj݉n[#2قQͨ z)Uխ4QY.Aֺ ц`$I_0wK2% У籌bNϚ-."W97>I1(MJ{LDh2rȠKC.%-_xʜrAXN tF.B8_@ʇ2 JȂVR +;a d@k3 hfxՉ-83-Nbϣ~<XT%%̞?^6? +h!+LAe:%γCbA>_>fQ>~||^۶.7ycC~8GqP!td M [5NY,ꚰ Mօ (yX(}P]6?;DKBÑW텛ebpIIluLx\4#8eQcSkzp*Adg|{8lxfCfY3&P ܨ.;uyo0OfhUʅ +7<{9I+J֖4M cYό+3B8!@<禭98$Jy;hEp,ypMgmi װ6L<%ND>榪wRrHm霩6:7fض|J,)lI_fQ~.c]A)1}x6KoDLW>*ⲠTp"n]_dQ^ohޔzx +P>"#X`/-/-K 7<2ncok~p*qa3(nP(~Q#sfmf1e@{SE*Ͼ3QЖ̖ +McMkyp*q4cRTRL_id2˘DBR ||6ՠ u oa'mb0&KZ{B +&s}1g +<'٢;E&&s==06}wx 7Uo#߻@`}aŚKwB+?/~W'dI'~oWބNxN{,J$Yi tq/Q '7d,'pL $?0endstream +endobj +901 0 obj << +/Type /Page +/Contents 902 0 R +/Resources 900 0 R +/MediaBox [0 0 612 792] +/Parent 823 0 R +/Annots [ 907 0 R 908 0 R 909 0 R 910 0 R 911 0 R 912 0 R 913 0 R 914 0 R 915 0 R 916 0 R 917 0 R 918 0 R ] +>> endobj +907 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [133.768 245.348 226.893 255.311] +/Subtype /Link +/A << /S /GoTo /D (ttbxalignmentpanel) >> +>> endobj +908 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [133.768 230.404 191.05 240.367] +/Subtype /Link +/A << /S /GoTo /D (ttbxbutton) >> +>> endobj +909 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [133.768 217.204 202.573 225.423] +/Subtype /Link +/A << /S /GoTo /D (ttbxcheckbox) >> +>> endobj +910 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [133.768 200.516 225.316 210.479] +/Subtype /Link +/A << /S /GoTo /D (ttbxcontrolmargins) >> +>> endobj +911 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [133.768 187.316 222.076 195.435] +/Subtype /Link +/A << /S /GoTo /D (ttbxcustombutton) >> +>> endobj +912 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [133.768 170.628 233.854 180.591] +/Subtype /Link +/A << /S /GoTo /D (ttbxcustomcheckbox) >> +>> endobj +913 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [133.768 155.684 215.935 165.647] +/Subtype /Link +/A << /S /GoTo /D (ttbxcustomlabel) >> +>> endobj +914 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [133.768 140.74 211.836 150.703] +/Subtype /Link +/A << /S /GoTo /D (ttbxcustomlink) >> +>> endobj +915 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [133.768 125.797 243.115 135.759] +/Subtype /Link +/A << /S /GoTo /D (ttbxcustompagescroller) >> +>> endobj +916 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [133.768 110.853 245.753 120.815] +/Subtype /Link +/A << /S /GoTo /D (ttbxcustomradiobutton) >> +>> endobj +917 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [133.768 95.909 221.391 105.871] +/Subtype /Link +/A << /S /GoTo /D (ttbxdockablepanel) >> +>> endobj +918 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [133.768 80.965 184.91 90.927] +/Subtype /Link +/A << /S /GoTo /D (ttbxlabel) >> +>> endobj +903 0 obj << +/D [901 0 R /XYZ 109.858 727.97 null] +>> endobj +130 0 obj << +/D [901 0 R /XYZ 109.858 703.064 null] +>> endobj +733 0 obj << +/D [901 0 R /XYZ 109.858 680.841 null] +>> endobj +904 0 obj << +/D [901 0 R /XYZ 109.858 680.841 null] +>> endobj +734 0 obj << +/D [901 0 R /XYZ 109.858 624.037 null] +>> endobj +905 0 obj << +/D [901 0 R /XYZ 109.858 615.458 null] +>> endobj +134 0 obj << +/D [901 0 R /XYZ 109.858 457.76 null] +>> endobj +735 0 obj << +/D [901 0 R /XYZ 109.858 427.114 null] +>> endobj +906 0 obj << +/D [901 0 R /XYZ 109.858 427.114 null] +>> endobj +680 0 obj << +/D [901 0 R /XYZ 109.858 372.195 null] +>> endobj +138 0 obj << +/D [901 0 R /XYZ 109.858 357.182 null] +>> endobj +900 0 obj << +/Font << /F29 416 0 R /F28 380 0 R /F41 556 0 R /F8 369 0 R /F20 385 0 R /F50 672 0 R /F51 675 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +935 0 obj << +/Length 1950 +/Filter /FlateDecode +>> +stream +xڥYK8W’,[fO ZVQr$Ñ(l[_j Ez4ʈKYJ[m3-9%RH6 bO2 %?.޾5h3}qDXyE,2RiUEϥ^jJ|0E$v]-O~e0[uq/b*w?,;499̊,nOEcI2&weG˫7n|WTRbR$ɒ4#Ű>b)aB̡a\c"l2-aqB#ڙ& e42.#L$]cfyjO.Ч80r!rԿzP/0}aNTa< aewzoǥ&I%"@Ih>#sC9}/z! +, 2`${V`d~B"JϭkrlnFnUigLp(Ih}#s97HwPܮ0I_͈{JIb,FcBPjioXvy42y^1<A8b]_sDh[Vf ӬO-0s XezxڤqE;]b_0A\?@1(ԅJ9tB#\AC"AD|ba7NRf]eef0= M1XL$P F75IN ^$4ͩtBe _—87̢b0PH}-VčL|.ۍ-u"p`LX.-?!MF=3 >"zFDЭšOķ-ゐ,u`=$N#prNtOsSݳ|m]{'M,L'=7݂⊌`q+` Mݍ~7ÃsXM5#<C3JjuиAպ})j\ ѕ2&&w(œ? {]/^-W3T>?)Fp4ˢA8 ^[D)6ў#$/& (Ds(#fOd" A"9kY赨LHQYfDrᇽa=1|(ui:*aߍYvQVsFL.{/KU r-LdTKRʵgsS +é^BvBjj}~5XZp/B= V`DYaY(tՁ}ǘEBr!3؈Q!dszDɕB,8Zٜ^u EǺUy(͛\+5h((^U9krD<`MDØR*[K+Gf;f6ÔDP{2|:$pp 43׆*Gܡ UR"sxeȼܹq@$ NKgX7{ eq׹ z/T90PxWM%Z{޸2#7*ֻŢeE&`1٣)_A[#bfnwmOQU79jewZx7?Ol +=ֽDyTZbe{|N-T)ۖsuJ-nw` "<"~}ɵJR6KQPB)JRj-Ay6 f:n!Rhx v,M'q͗gv#*rn \x屈HNqaȌbA'3csn +QpjIxvWF}݅|c_J.U' J/_";?/endstream +endobj +934 0 obj << +/Type /Page +/Contents 935 0 R +/Resources 933 0 R +/MediaBox [0 0 612 792] +/Parent 948 0 R +/Annots [ 937 0 R 938 0 R 939 0 R 940 0 R 941 0 R 942 0 R 943 0 R 944 0 R 945 0 R 947 0 R ] +>> endobj +931 0 obj << +/Type /XObject +/Subtype /Form +/FormType 1 +/PTEX.FileName (c_ttbxalignmentpanel.pdf) +/PTEX.PageNumber 1 +/PTEX.InfoDict 949 0 R +/Matrix [1.00000000 0.00000000 0.00000000 1.00000000 0.00000000 0.00000000] +/BBox [0.00000000 0.00000000 21.00000000 21.00000000] +/PieceInfo << +/AdobePhotoshop << +/LastModified (D:20030406201224-05'00') +/Private << +/RoundTrip 1 +/ExportCrispy false +/SaveTransparency false +/ImageResources 950 0 R +/XObject << +/Im0 951 0 R +>> +/StandardImageFileData 952 0 R +>> +>> +>> +/Resources << +/XObject << +/Im0 951 0 R +>>/ProcSet [ /PDF /ImageC ] +>> +/Length 953 0 R +>> +stream +q q 21 0 0 21 0 0 cm /Im0 Do Q Q endstream +endobj +949 0 obj +<< +/Creator (Adobe Photoshop 7.0) +/CreationDate (D:20030406201224-05'00') +/ModDate (D:20030406201224-05'00') +/Producer (Adobe Photoshop for Windows) +>> +endobj +950 0 obj +<< +/Filter /FlateDecode +/Size 2736 +/Length 954 0 R +>> +stream +HVyPW p(Z6rU"UL`,&8ÑV2=Z-b[e9gRQ9jo_6!QN{}63!̈́6e=+'c"d$BuC"H,ObìQ +WFQd?;99Т;jeѾ6M8ڧhPο_=*oC5 urXkhUp2;z+M`7Y5XT@p`}*xP=u$ltLj`19 <5i6hL{J6b+',ӑ-|"r)RF6r&]^6aR曘N!d< !qCnH T|Ҙ3JT&(2Sd@~?V>"n!A qL)Pzw4-Ջ[`ĵȶҠDR]k:NF 4u l.HypBÑDbn4d|&R.";kTlj G:tTuyEg]6/?ԢP )å7jV.)Xٮ$*ND> +/Width 28 +/Height 28 +/BitsPerComponent 8 +/ColorSpace /DeviceRGB +/Length 955 0 R +>> +stream +HԖIjAF7#Qw.021w\ D .DQ!)]-ڢ}zes2zX,9D"1gY:D" Zgh4 +XTx<똮T*V+`v\.DFYV*|> +t3Nl6Rt\\.4McD"VV0, +ǘ(h4B~R`P*x`V-fSHFuZ#=h 8$:{bNǷ<;t2[LBj, +AaN&^Nx> +stream +endstream +endobj +953 0 obj +34 +endobj +954 0 obj +1577 +endobj +955 0 obj +555 +endobj +956 0 obj +0 +endobj +932 0 obj << +/Type /XObject +/Subtype /Form +/FormType 1 +/PTEX.FileName (c_ttbxbutton.pdf) +/PTEX.PageNumber 1 +/PTEX.InfoDict 957 0 R +/Matrix [1.00000000 0.00000000 0.00000000 1.00000000 0.00000000 0.00000000] +/BBox [0.00000000 0.00000000 28.00000000 28.00000000] +/Resources << +/ColorSpace << +/Cs8 958 0 R +>>/XObject << +/Im1 959 0 R +>>/ProcSet [ /PDF /ImageC /ImageI ] +/ExtGState << +/GS1 960 0 R +>>>> +/Length 46 +/Filter /FlateDecode +>> +stream +Hw6TH/*22׳  D%r{*sr!9 + +endstream +endobj +957 0 obj +<< +/ModDate (D:20040529160855-04'00') +/CreationDate (D:20040529160320-04'00') +/Title (c_ttbxbutton.eps) +/Creator (Adobe Photoshop Version 8.0x118) +/Producer (Acrobat Distiller 6.0.1 \(Windows\)) +>> +endobj +958 0 obj +[/Indexed/DeviceRGB 33 961 0 R] +endobj +959 0 obj +<< +/Length 188 +/Filter /FlateDecode +/Width 28 +/Height 28 +/BitsPerComponent 8 +/ColorSpace 958 0 R +/Type /XObject +/Subtype /Image +/Metadata 962 0 R +>> +stream +H &ޢ8Y?\RӚ9 +aB7!UX Mse˱7L]`]OhI f&WlsdD6\^g\ff&T 9h/8Z^3]oHdcs8 Q 0?߬ТKYӹR+6p +endstream +endobj +960 0 obj +<< +/Type /ExtGState +/SA false +/OP false +/SM 0.02 +/op false +/OPM 1 +/UCR2 /Default +/BG2 /Default +>> +endobj +961 0 obj +<< +/Length 108 +/Filter /FlateDecode +>> +stream +HхhbfbQl޻sZc!st1B |9191sZSJ*Zk-J +endstream +endobj +962 0 obj +<< +/Length 6106 +/Type /Metadata +/Subtype /XML +>> +stream + + + + + + 1 + 28 + 28 + + + + + + + + + + + 1 + 72/1 + 72/1 + 2 + + + + 2004-05-29T16:02:42-05:00 + 2004-05-29T16:02:42-05:00 + 2004-05-29T16:02:42-05:00 + Adobe Photoshop CS Windows + + + + adobe:docid:photoshop:17e9d8fa-b1ab-11d8-8c90-a1142b67d8de + + + + image/epsf + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +endstream +endobj +937 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [133.768 692.105 180.811 700.324] +/Subtype /Link +/A << /S /GoTo /D (ttbxlink) >> +>> endobj +938 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [133.768 675.417 205.384 685.38] +/Subtype /Link +/A << /S /GoTo /D (ttbxmultidock) >> +>> endobj +939 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [133.768 660.473 212.089 670.436] +/Subtype /Link +/A << /S /GoTo /D (ttbxpagescroller) >> +>> endobj +940 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [133.768 645.529 212.304 655.492] +/Subtype /Link +/A << /S /GoTo /D (ttbxpanelobject) >> +>> endobj +941 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [133.768 632.329 214.728 640.548] +/Subtype /Link +/A << /S /GoTo /D (ttbxradiobutton) >> +>> endobj +942 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [133.768 615.641 208.337 625.604] +/Subtype /Link +/A << /S /GoTo /D (ttbxtextobject) >> +>> endobj +943 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [133.768 582.765 217.987 592.628] +/Subtype /Link +/A << /S /GoTo /D (ttbxresizingstage) >> +>> endobj +944 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [108.862 452.349 187.397 462.312] +/Subtype /Link +/A << /S /GoTo /D (ttbxpanelobject) >> +>> endobj +945 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [126.02 351 210.536 361.849] +/Subtype /Link +/A << /S /GoTo /D (ttbxpagescroller) >> +>> endobj +947 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [145.199 242.431 251.652 251.508] +/Subtype /Link +/A << /S /GoTo /D (ttbxcontrolmargins) >> +>> endobj +936 0 obj << +/D [934 0 R /XYZ 109.858 727.97 null] +>> endobj +919 0 obj << +/D [934 0 R /XYZ 109.858 579.776 null] +>> endobj +142 0 obj << +/D [934 0 R /XYZ 109.858 573.037 null] +>> endobj +946 0 obj << +/D [934 0 R /XYZ 109.858 313.844 null] +>> endobj +920 0 obj << +/D [934 0 R /XYZ 109.858 243.427 null] +>> endobj +146 0 obj << +/D [934 0 R /XYZ 109.858 232.704 null] +>> endobj +933 0 obj << +/Font << /F29 416 0 R /F51 675 0 R /F50 672 0 R /F28 380 0 R /F8 369 0 R /F54 713 0 R /F22 363 0 R /F41 556 0 R /F55 716 0 R /F34 719 0 R >> +/XObject << /Im16 931 0 R /Im17 932 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +973 0 obj << +/Length 1645 +/Filter /FlateDecode +>> +stream +xXYoF~ׯ7܃Rz8@K y)V, +Iv~}gfw)M pP1snd2yY\ί3("%10=j$n@ɑ8XpJ&q̥΃L'9qMeAH!O*Ee෷o=E͗p{ fUS*|9ys1Щ`P=KP_Ra$a֝-/n^JbWmPE:;4E~Z\I 4Sq$$GZ@htpI'BUS4HXfV$>hsK:\`mWoC.kqHēE[7?b[Q(\\/!t:Y.{t&82th#E%Xݑ&:@̑Ҕ&#2&ӧp44IXupp +ɵ@1.B +q4#`dt-K7c +Er` ,* +$< be[!tI!pNڲYﻵ5uPF7XI+'`H30IERok;IHVi-َ6>$zid5XQw@"Scɋn0q@䦶qxbM,A](56^$n)T*;!9pS##S7vrw]9H zl9ȟTg'5e/TwuwȪP)vVCJd-(9Wm4u_@nŦh[Ěf^crp'^/(+/zP{OᝧpY>H}{ >0dVE FfԬ!hDa= Z +t֖*"?Yyт -XF|d nAT MQq4 Y`vC5裡HM@*oJߌ}ZBSeחê3"-paYrMՑ~- /`j {GIj!> endobj +970 0 obj << +/Type /XObject +/Subtype /Form +/FormType 1 +/PTEX.FileName (c_ttbxcheckbox.pdf) +/PTEX.PageNumber 1 +/PTEX.InfoDict 984 0 R +/Matrix [1.00000000 0.00000000 0.00000000 1.00000000 0.00000000 0.00000000] +/BBox [0.00000000 0.00000000 21.00000000 21.00000000] +/PieceInfo << +/AdobePhotoshop << +/LastModified (D:20030406201227-05'00') +/Private << +/RoundTrip 1 +/ExportCrispy false +/SaveTransparency false +/ImageResources 985 0 R +/XObject << +/Im0 986 0 R +>> +/StandardImageFileData 987 0 R +>> +>> +>> +/Resources << +/XObject << +/Im0 986 0 R +>>/ProcSet [ /PDF /ImageC ] +>> +/Length 988 0 R +>> +stream +q q 21 0 0 21 0 0 cm /Im0 Do Q Q endstream +endobj +984 0 obj +<< +/Creator (Adobe Photoshop 7.0) +/CreationDate (D:20030406201227-05'00') +/ModDate (D:20030406201227-05'00') +/Producer (Adobe Photoshop for Windows) +>> +endobj +985 0 obj +<< +/Filter /FlateDecode +/Size 2632 +/Length 989 0 R +>> +stream +HV}PTUw~eAɐ˒D#D@]Q>Qawo}kj)dfYN"MG( +6Qd*Z*~D~)twwιy2rX`Pl5Vro'̜Mm*e*q bԇc<}+ *@p㕷^,+C+*^S&FǙhtk8ƫ1b;h#rކ,S2pOxIt{E ]0g l"D# ǭkJ]Vs_@9AgJ9Gc*mfC\M\%-iGJ-ӥ"jQ(F܋kAJHD)Hog x܉ Q9_d6P%z bFv*@rT(H2@ "ɠ&LP *`*8TRr*_7ZE RCB Nu{ !@mN,%|pCB$IdR QMG$HҧjbWꤡ53ĐXޚ)]WpLuϊ jmEuUGO.M~[{7;[}O~kFقW̯ڸ@WH؊1'T)H#c4]eu(H~đ.uaFgRo# KnhC$jMYEcꢇR`T4p+ІړBh>TڕQrsdL{Ӷ%kٵ=/j 1_6 =i[r#moX'-=4vxҞV]> +/Width 28 +/Height 28 +/BitsPerComponent 8 +/ColorSpace /DeviceRGB +/Length 990 0 R +>> +stream +H씱jP#D0ŀ2(U0C 4/ 31yf(8Q +:o. x] +=rws頻uT?,˲(<ϑ` :32۶gXcYEQ3$qgӁ؈tj$ItfLy>[| Hear-,L Ij5ꮘ;0{^7kKLub"Z0MӤI9yy:|2\(41 !LpPEuz~'Mkr:zyZ$o6`~nhea/j|C4Mcwb;A!V(=jy}hi endstream +endobj +987 0 obj +<< +/Length 991 0 R +>> +stream +endstream +endobj +988 0 obj +34 +endobj +989 0 obj +1486 +endobj +990 0 obj +379 +endobj +991 0 obj +0 +endobj +975 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [108.862 645.052 187.397 655.015] +/Subtype /Link +/A << /S /GoTo /D (ttbxpanelobject) >> +>> endobj +976 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [108.862 623.134 183.43 633.097] +/Subtype /Link +/A << /S /GoTo /D (ttbxtextobject) >> +>> endobj +977 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [108.862 602.96 197.169 611.079] +/Subtype /Link +/A << /S /GoTo /D (ttbxcustombutton) >> +>> endobj +978 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [466.52 501.611 538.252 512.459] +/Subtype /Link +/A << /S /GoTo /D (ttbxpanelobject) >> +>> endobj +979 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [108.862 489.656 126.628 500.504] +/Subtype /Link +/A << /S /GoTo /D (ttbxpanelobject) >> +>> endobj +980 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [383.175 489.656 420.397 500.504] +/Subtype /Link +/A << /S /GoTo /D (ttbxtextobject.margins) >> +>> endobj +981 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [108.862 347.479 187.397 357.442] +/Subtype /Link +/A << /S /GoTo /D (ttbxpanelobject) >> +>> endobj +982 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [108.862 325.561 183.43 335.524] +/Subtype /Link +/A << /S /GoTo /D (ttbxtextobject) >> +>> endobj +983 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [108.862 305.387 208.948 313.606] +/Subtype /Link +/A << /S /GoTo /D (ttbxcustomcheckbox) >> +>> endobj +974 0 obj << +/D [972 0 R /XYZ 109.858 727.97 null] +>> endobj +921 0 obj << +/D [972 0 R /XYZ 109.858 478.697 null] +>> endobj +150 0 obj << +/D [972 0 R /XYZ 109.858 467.973 null] +>> endobj +922 0 obj << +/D [972 0 R /XYZ 109.858 210.015 null] +>> endobj +971 0 obj << +/Font << /F29 416 0 R /F28 380 0 R /F50 672 0 R /F8 369 0 R /F19 516 0 R >> +/XObject << /Im18 970 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +995 0 obj << +/Length 1365 +/Filter /FlateDecode +>> +stream +xXێ6}WQ"VIduz ZdQrLG_.#o ,&bӘ$7ʽG/LLRgXMչVyu넳x164&Y;Et?A5L!j ¤<:P +E#+ɦYzwZo&2WD|_mDw >[|,]k{,Kמzmݼ໮a^֍iuYgnwBdE\;P>#ṶI"4qZff)'En+5l;O&J]1 f'&Y}K@bAҥWsf9 9QE[NkGKĮڴv$z%p[$l&zsrE+~x{aa.,PesIT0jHzCAo}o80 Z ve=Y_poc32*6VR䉡hHZ$&k8hY;Ews! +Bv+@Xw!zb%^r_`in #}g)c% s WF}I{9 y$AVRKn;8t[BZzRI[C{ҁm[> rYlMfa3a%6 ɠkqGayGP9*Ktg q$lFL(VBqB3f]ik hw9!\y7\1WuA95C1LrD*ݭ!G:"!iޏl|iEȎ6>ob4 ||#!1|R^Z 38)>34gP$DfͲtB N4<؞"[\%Fu1wA*Ǜ{>]r* ?>qa`|Jor6 {'(L4lI;eTgN˄Z5 +5#9&_y Ikr\~3_GZL<)z ئGSg2>P~AįjJ4˹3w9:sr[,OfR[0ωEd#C<fhΔ_-6ˆMo1/p\$Bȳ)A7O&ov" ø?endstream +endobj +994 0 obj << +/Type /Page +/Contents 995 0 R +/Resources 993 0 R +/MediaBox [0 0 612 792] +/Parent 948 0 R +/Annots [ 997 0 R 998 0 R 1003 0 R 1004 0 R ] +>> endobj +997 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [145.199 512.049 253.116 521.126] +/Subtype /Link +/A << /S /GoTo /D (ttbxalignmentpanel) >> +>> endobj +998 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [256.298 512.049 347.173 521.126] +/Subtype /Link +/A << /S /GoTo /D (ttbxtextobject) >> +>> endobj +1003 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [108.862 125.582 187.397 135.544] +/Subtype /Link +/A << /S /GoTo /D (ttbxpanelobject) >> +>> endobj +1004 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [108.862 103.664 183.43 113.626] +/Subtype /Link +/A << /S /GoTo /D (ttbxtextobject) >> +>> endobj +996 0 obj << +/D [994 0 R /XYZ 109.858 727.97 null] +>> endobj +154 0 obj << +/D [994 0 R /XYZ 109.858 703.064 null] +>> endobj +999 0 obj << +/D [994 0 R /XYZ 109.858 474.505 null] +>> endobj +1000 0 obj << +/D [994 0 R /XYZ 109.858 420.753 null] +>> endobj +1001 0 obj << +/D [994 0 R /XYZ 109.858 357.108 null] +>> endobj +1002 0 obj << +/D [994 0 R /XYZ 109.858 293.526 null] +>> endobj +923 0 obj << +/D [994 0 R /XYZ 109.858 229.944 null] +>> endobj +158 0 obj << +/D [994 0 R /XYZ 109.858 219.221 null] +>> endobj +993 0 obj << +/Font << /F29 416 0 R /F28 380 0 R /F8 369 0 R /F50 672 0 R /F55 716 0 R /F34 719 0 R /F54 713 0 R /F22 363 0 R /F41 556 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +1007 0 obj << +/Length 1828 +/Filter /FlateDecode +>> +stream +xYmo6_0q$v؇%]X5.PVb!/mٮP4Ļ#Mр&22EA j%bNICHA6I3r]|sʃh' .Te}_^\[1}YЛ9$p)pZ9<]N.~~T'}y1벞їۋ'EN-91(.{&?g(f,?UgZˏ/#¢.Ґ}r gGSԳE9ør)zfq"ϊ#\3{Sml/fYy1}S1$b +û@Mx.|iLX@T]7>nl[Fa5 Ca DRbe8x[<~\z^ohOGq> endobj +1009 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [325.466 668.021 387.235 676.932] +/Subtype /Link +/A << /S /GoTo /D (ttbxbutton) >> +>> endobj +1010 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [409.927 668.021 471.696 676.932] +/Subtype /Link +/A << /S /GoTo /D (ttbxbutton) >> +>> endobj +1016 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [276.986 281.149 331.102 291.997] +/Subtype /Link +/A << /S /GoTo /D (ttbxcustombuttn.groupindex) >> +>> endobj +1018 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [265.176 217.452 336.796 228.3] +/Subtype /Link +/A << /S /GoTo /D (ttbxcustombuttn.dropdownmenu) >> +>> endobj +1019 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [276.986 188.56 348.606 199.408] +/Subtype /Link +/A << /S /GoTo /D (ttbxcustombuttn.dropdownmenu) >> +>> endobj +1021 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [454.897 124.978 538.252 135.827] +/Subtype /Link +/A << /S /GoTo /D (ttbxpopupmenu) >> +>> endobj +1008 0 obj << +/D [1006 0 R /XYZ 109.858 727.97 null] +>> endobj +1011 0 obj << +/D [1006 0 R /XYZ 109.858 616.972 null] +>> endobj +1012 0 obj << +/D [1006 0 R /XYZ 109.858 563.221 null] +>> endobj +1013 0 obj << +/D [1006 0 R /XYZ 109.858 499.639 null] +>> endobj +1014 0 obj << +/D [1006 0 R /XYZ 109.858 435.941 null] +>> endobj +1015 0 obj << +/D [1006 0 R /XYZ 109.858 362.779 null] +>> endobj +1017 0 obj << +/D [1006 0 R /XYZ 109.858 282.145 null] +>> endobj +1020 0 obj << +/D [1006 0 R /XYZ 109.858 189.556 null] +>> endobj +1022 0 obj << +/D [1006 0 R /XYZ 109.858 114.019 null] +>> endobj +1005 0 obj << +/Font << /F29 416 0 R /F28 380 0 R /F8 369 0 R /F54 713 0 R /F22 363 0 R /F41 556 0 R /F19 516 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +1026 0 obj << +/Length 1927 +/Filter /FlateDecode +>> +stream +xڵY[۶~_G yċn=C7m-ghYr%pHc6oC̃˓Y/<" {CaТvZ3XNz/5T b|4w":8vƒ8EpN>}s,t|rǥ?Ĩ[W"\Zt̊]YS# ~f"X3)ŁbЮ,x @C=M`v{d5겣;Ҙ F`7Tw:5B69j,KɒxU{ll æ\kyC@8U 7pTkoq;)=ᥥgo:k7HPU6X!oyx}[/#p}*P*H/An%Av :ϣV#X8, Tn,dyCN=ܙ}XHoo73@16v˓԰j-Z3Bqmt FyJ ׭a^UX.Q.Eu&Oiʋ4PJ.ʀ2E~>$g!SѸctjW|N0M~'?w`Ksn%TK y$a~Eu_:vrñBx߽ Mc zӏg`*#8z2!@ՍLoGO8PL~Ј;Yf$p:Xg[zbۖ$mSt]x)áκTnK}ޕ$)6d"1C#?<.um)կ)(3> endobj +1030 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [172.9 439.091 225.536 449.939] +/Subtype /Link +/A << /S /GoTo /D (ttbxcustombuttn.imageindex) >> +>> endobj +1033 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [126.573 302.463 172.706 313.311] +/Subtype /Link +/A << /S /GoTo /D (ttbxcustombuttn.repeating) >> +>> endobj +1035 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [502.082 209.99 538.252 220.838] +/Subtype /Link +/A << /S /GoTo /D (ttbxcustombuttn.repeatdelay) >> +>> endobj +1036 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [108.862 198.034 135.623 208.883] +/Subtype /Link +/A << /S /GoTo /D (ttbxcustombuttn.repeatdelay) >> +>> endobj +1037 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [161.747 186.079 228.109 196.927] +/Subtype /Link +/A << /S /GoTo /D (ttbxcustombuttn.repeatinterval) >> +>> endobj +1039 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [126.573 122.497 172.706 133.346] +/Subtype /Link +/A << /S /GoTo /D (ttbxcustombuttn.repeating) >> +>> endobj +1027 0 obj << +/D [1025 0 R /XYZ 109.858 727.97 null] +>> endobj +1023 0 obj << +/D [1025 0 R /XYZ 109.858 654.974 null] +>> endobj +1028 0 obj << +/D [1025 0 R /XYZ 109.858 579.322 null] +>> endobj +1029 0 obj << +/D [1025 0 R /XYZ 109.858 515.74 null] +>> endobj +1031 0 obj << +/D [1025 0 R /XYZ 109.858 440.087 null] +>> endobj +1032 0 obj << +/D [1025 0 R /XYZ 109.858 367.041 null] +>> endobj +1034 0 obj << +/D [1025 0 R /XYZ 109.858 303.459 null] +>> endobj +1038 0 obj << +/D [1025 0 R /XYZ 109.858 187.075 null] +>> endobj +1024 0 obj << +/Font << /F29 416 0 R /F54 713 0 R /F22 363 0 R /F41 556 0 R /F8 369 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +1042 0 obj << +/Length 1654 +/Filter /FlateDecode +>> +stream +xXIoFW= ab;MKX +$908V# +E{Ph 0 g޼}(1gf(iUfՄe_GBrj-,~|dY!he+6esnfwfT*[M(m|_N'\YF +%GThgot&`:@޻\(ZմRԏB’׋.\}}KA[ns [ɳ2)^Q)GVRkeIN$#m$1]LŨK{ݭN +1ܔ֓]_A#ց<ЛP(CQńis-Iӹ\ 2 ( P+EfTE+v1Db@&F`ٸHwW%JDM`ꋼJp\h~-m/*=~F%3eKK~(95Wm37ߵc)RS^}d] IA^]u]p +\(IeO^4kІDURF&M@_7ƶI*8QkAԍ  m`Oڜ M5zA3 +U l/+7_]:Z$QOnn]4Rwe$ӳuklua1D"\m=}X/o c)QS:_b鼵u2a=HYw&S<mK\ߦ3j٤ց :JTzp-X3KdI,f;6]/뮅$q7!2Nx(eR0 ,a@C },a_̟ +]3w(xCќCq輅%It`5Ъy63Pdo c)|BCXoqq/*_5\Ǥ\\ )+=4nP4|u|eZEp3o)Yq*2U 3slX1y>"z`+-蹈n6-g'f|۩#"cK\\/mW@=%rDb@_a%HlO_?>.ħ!<#BS``3:@b7KG~"\(F?J=}=1ucQ'UaYIJمȶ sy kŘ:u`8GsׇVyEà3K_&(vo>NnU ;%&;%,я]: h L?eꨗqaϽMԯ!CMNrFf`l #jUab5Ԥ %(Ra/= PEQOf1>5#U LOTXS#pJ(y0O}?wendstream +endobj +1041 0 obj << +/Type /Page +/Contents 1042 0 R +/Resources 1040 0 R +/MediaBox [0 0 612 792] +/Parent 948 0 R +/Annots [ 1045 0 R 1046 0 R 1047 0 R 1048 0 R 1051 0 R 1052 0 R ] +>> endobj +1045 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [108.862 487.364 187.397 497.327] +/Subtype /Link +/A << /S /GoTo /D (ttbxpanelobject) >> +>> endobj +1046 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [108.862 465.446 183.43 475.409] +/Subtype /Link +/A << /S /GoTo /D (ttbxtextobject) >> +>> endobj +1047 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [346.527 396.669 420.748 405.58] +/Subtype /Link +/A << /S /GoTo /D (ttbxcheckbox) >> +>> endobj +1048 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [447.758 396.669 521.979 405.58] +/Subtype /Link +/A << /S /GoTo /D (ttbxcheckbox) >> +>> endobj +1051 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [513.566 210.123 538.252 220.971] +/Subtype /Link +/A << /S /GoTo /D (ttbxcustmchckbx.state) >> +>> endobj +1052 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [145.199 183.168 166.481 190.696] +/Subtype /Link +/A << /S /GoTo /D (ttbxcustmchckbx.state) >> +>> endobj +1043 0 obj << +/D [1041 0 R /XYZ 109.858 727.97 null] +>> endobj +1044 0 obj << +/D [1041 0 R /XYZ 109.858 681.914 null] +>> endobj +924 0 obj << +/D [1041 0 R /XYZ 109.858 618.582 null] +>> endobj +162 0 obj << +/D [1041 0 R /XYZ 109.858 607.858 null] +>> endobj +1049 0 obj << +/D [1041 0 R /XYZ 109.858 345.62 null] +>> endobj +1050 0 obj << +/D [1041 0 R /XYZ 109.858 291.753 null] +>> endobj +1053 0 obj << +/D [1041 0 R /XYZ 109.858 184.164 null] +>> endobj +1040 0 obj << +/Font << /F29 416 0 R /F28 380 0 R /F54 713 0 R /F22 363 0 R /F41 556 0 R /F8 369 0 R /F50 672 0 R /F55 716 0 R /F34 719 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +1056 0 obj << +/Length 1504 +/Filter /FlateDecode +>> +stream +xXYs6~ׯ#9SES=Ӥ2LFmJ@RȞt:K Qe٭ZrQ.eϫj[\ ꈎ=u6'qƌ9's ۶PzLI@AJH'B M}TCR +2MCM D %Ǟ^ؚ_u]-[MNk$yP\zL1O /1F"X7qL\ +`ڣJ\Y'39OXa`YZd+H,`4O8NܾH + a`tpE4GOtl|Y4DOGup?JI<hIǪ[ea,@Y㪹]rF33nuو0nT_/.>s@ר4(rM#⇦@io#cToNPo˜2 3P(r=ZSM(POG0]cQ~ cHՄ[HKQ]d\~G8`:s7͒'zwSAi ~J P +j2mlNU> endobj +1059 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [272.526 561.958 297.211 572.806] +/Subtype /Link +/A << /S /GoTo /D (ttbxcustmchckbx.state) >> +>> endobj +1060 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [108.862 431.736 187.397 441.699] +/Subtype /Link +/A << /S /GoTo /D (ttbxpanelobject) >> +>> endobj +1061 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [108.862 409.818 183.43 419.781] +/Subtype /Link +/A << /S /GoTo /D (ttbxtextobject) >> +>> endobj +1062 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [312.671 341.042 367.798 349.953] +/Subtype /Link +/A << /S /GoTo /D (ttbxlabel) >> +>> endobj +1063 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [389.318 341.042 444.445 349.953] +/Subtype /Link +/A << /S /GoTo /D (ttbxlabel) >> +>> endobj +1066 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [145.199 168.503 203.418 176.03] +/Subtype /Link +/A << /S /GoTo /D (ttbxcustomlabel.underlinecolor) >> +>> endobj +1057 0 obj << +/D [1055 0 R /XYZ 109.858 727.97 null] +>> endobj +1058 0 obj << +/D [1055 0 R /XYZ 109.858 616.821 null] +>> endobj +925 0 obj << +/D [1055 0 R /XYZ 109.858 562.954 null] +>> endobj +166 0 obj << +/D [1055 0 R /XYZ 109.858 552.23 null] +>> endobj +1064 0 obj << +/D [1055 0 R /XYZ 109.858 301.948 null] +>> endobj +1065 0 obj << +/D [1055 0 R /XYZ 109.858 248.08 null] +>> endobj +1067 0 obj << +/D [1055 0 R /XYZ 109.858 169.499 null] +>> endobj +1054 0 obj << +/Font << /F29 416 0 R /F54 713 0 R /F22 363 0 R /F41 556 0 R /F8 369 0 R /F28 380 0 R /F50 672 0 R /F55 716 0 R /F34 719 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +1071 0 obj << +/Length 1667 +/Filter /FlateDecode +>> +stream +xnF)g̤"EX$9(mHa_fHQ @q޾?(4!ZH1E")Dk8Qm ~E)#F{K%&L[iS..TܝR3DJ9jf"{yy\ߗ qٖuQ&_/~^ip\2X9ͮsXC]|xU.4&7e41y53RKԔ7^n pB3j}e۪.Ϛm:AAT"2fnDDp4'(WH>MGN61UxAX77X\)nWMyB!0fRaw^W +LҸT~SAą'KΖEnR9 1kKDZīm8x.*Cn2U~1s <9衤KD%8!f:BN>n5DfhFqfaf|&B@7zut\[D>2WXG{؇C ۢ-wC +|3L :an{GSs+:PܳL/m>e–0av77.H//j0o+yl_nʶ0( Դ?8@ڦh8p8տ^C/3MzKbyNBxtj>!u $T"ȇCHfxKO$9)Ѷ[eWWֺ(mnhcwM2 p$l: Fn; #L%2cD7/k' !blv\USK,x ֽ>"?27v:[Uen7xDfN5##72j&շ y%܇,LHhOZMFgE?$Z 2V1(=ߡ8м*,yEZ6Emfc?kp 1 ʟF92ЉCYzSvaD@1ۅbr)WLV0D 3U+d1LPx]vE[،5 (}A@F1F¥{⻒]ɕmCm /cIOEp R+92D\cfK9 E9k&+8ēLi?kU~g!`J4S֗nf%h3"wr*̈^ s<|*q>b?q?4oرxzۧmWBR[9!>ǘn=[}wZcK oZF-Y$ݎVQ9ef' +>c4ψi=~(ȷFt7lZUwo,w`R1p*v߹kpIWwUq//Y֭ ׸vw`Ct`{#AͰ>"q2 oEjF2MۖǶnfm^2 W\$LG%Ymd" 3X( 0qy} kn{-nS$endstream +endobj +1070 0 obj << +/Type /Page +/Contents 1071 0 R +/Resources 1069 0 R +/MediaBox [0 0 612 792] +/Parent 1068 0 R +/Annots [ 1073 0 R 1075 0 R 1076 0 R 1077 0 R 1078 0 R 1079 0 R 1081 0 R 1083 0 R ] +>> endobj +1073 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [145.199 638.979 183.181 646.506] +/Subtype /Link +/A << /S /GoTo /D (ttbxcustomlabel.underline) >> +>> endobj +1075 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [127.735 535.003 195.924 543.914] +/Subtype /Link +/A << /S /GoTo /D (ttbxcustomlabel.underlinecolor) >> +>> endobj +1076 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [108.862 402.844 187.397 412.807] +/Subtype /Link +/A << /S /GoTo /D (ttbxpanelobject) >> +>> endobj +1077 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [108.862 380.927 183.43 390.889] +/Subtype /Link +/A << /S /GoTo /D (ttbxtextobject) >> +>> endobj +1078 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [315.56 312.15 366.259 321.061] +/Subtype /Link +/A << /S /GoTo /D (ttbxlink) >> +>> endobj +1079 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [389.173 312.15 439.872 321.061] +/Subtype /Link +/A << /S /GoTo /D (ttbxlink) >> +>> endobj +1081 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [145.199 201.759 172.871 210.836] +/Subtype /Link +/A << /S /GoTo /D (ttbxcustomlink.images) >> +>> endobj +1083 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [151.258 125.719 203.894 136.567] +/Subtype /Link +/A << /S /GoTo /D (ttbxcustomlink.imageindex) >> +>> endobj +1072 0 obj << +/D [1070 0 R /XYZ 109.858 727.97 null] +>> endobj +1074 0 obj << +/D [1070 0 R /XYZ 109.858 599.885 null] +>> endobj +926 0 obj << +/D [1070 0 R /XYZ 109.858 535.999 null] +>> endobj +170 0 obj << +/D [1070 0 R /XYZ 109.858 525.276 null] +>> endobj +1080 0 obj << +/D [1070 0 R /XYZ 109.858 273.056 null] +>> endobj +1082 0 obj << +/D [1070 0 R /XYZ 109.858 202.755 null] +>> endobj +927 0 obj << +/D [1070 0 R /XYZ 109.858 126.715 null] +>> endobj +1069 0 obj << +/Font << /F29 416 0 R /F54 713 0 R /F22 363 0 R /F41 556 0 R /F8 369 0 R /F55 716 0 R /F34 719 0 R /F28 380 0 R /F50 672 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +1086 0 obj << +/Length 2067 +/Filter /FlateDecode +>> +stream +xڭYێ6}УD\Q$u{sx=q4aTH'USkH86ǭB3 G'M++0l屈2gY.%,G?a؅v<>܀o[t#,!|?W:1 +Ug%'2L@ & ĞKe,/]\2YƐ!$;U&B ?QXfrgP)S,Q~hWa]x +p렄 XCaecOz:+FR:p4N`SqLVבHF dbƐ,T;}/+RIS %#.l<7vWS +~Eꆻl)wa&~їc5螄]\p۽\~UH |ұkL$Sc#)elšطL<gd " $VْAȻ0ȳnGA37K2+xqTb56r1)2 +xDongw)DՒ 8OR9#h_qo]_C$Ef>s:19bn8 Xj;ԟ",(3y2S ߓJ̫W!ACwD%;L 1pKO8զ Ý6 Z#,NB>qX$) R~n؈zvqEk{m|uks׀}ffYϳ"!.M~Qn0 ,*(w.n!ѹN؅ڕ3PG7x]%g)ϋBOR:DUH6 +o}0$ ;D9+'TLጹt`fsEzڨ:S׷2|Lⲋ#Bd}Aqq+co骷]hX\d yߍU3me4,̠$%Ϙ`Qc +R6 -]:1c/b)}A,q7X/ƒyA,_C7gJW[wqp95lMU@8iBaL꺹|p)6.>KMssju;;${z;QƊ B iXfI"t?D%9lVMtS"_'f?#Zˆg,K1+j9ùo u M|E8]k5Bӂ#6DDŏCa+61ЎjWw7Cm@2jA)y 0f#ENO\GڳHn^Lg4V LJxٸ[Dc--W9H TN~ 0g;"21D/B~^\Q/!rm>o6[]!g['mXyh;`'&&lz[)~иDaB1Tce:<}H5B$$ +7 io5醵cݴGJ;T9~3o? +&G+BB;'pwendstream +endobj +1085 0 obj << +/Type /Page +/Contents 1086 0 R +/Resources 1084 0 R +/MediaBox [0 0 612 792] +/Parent 1068 0 R +/Annots [ 1088 0 R 1089 0 R 1090 0 R 1092 0 R 1095 0 R ] +>> endobj +1088 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [396.677 540.454 481.193 551.302] +/Subtype /Link +/A << /S /GoTo /D (ttbxpagescroller) >> +>> endobj +1089 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [504.019 540.454 538.252 551.302] +/Subtype /Link +/A << /S /GoTo /D (ttbxpagescroller) >> +>> endobj +1090 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [108.862 528.499 164.459 539.347] +/Subtype /Link +/A << /S /GoTo /D (ttbxpagescroller) >> +>> endobj +1092 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [145.199 420.045 170.358 429.122] +/Subtype /Link +/A << /S /GoTo /D (ttbxcstmpgscrll.range) >> +>> endobj +1095 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [436.139 268.352 465.391 279.201] +/Subtype /Link +/A << /S /GoTo /D (ttbxcstmpgscrll.range) >> +>> endobj +1087 0 obj << +/D [1085 0 R /XYZ 109.858 727.97 null] +>> endobj +174 0 obj << +/D [1085 0 R /XYZ 109.858 703.064 null] +>> endobj +1091 0 obj << +/D [1085 0 R /XYZ 109.858 491.342 null] +>> endobj +1093 0 obj << +/D [1085 0 R /XYZ 109.858 421.041 null] +>> endobj +1094 0 obj << +/D [1085 0 R /XYZ 109.858 333.046 null] +>> endobj +1096 0 obj << +/D [1085 0 R /XYZ 109.858 259.331 null] +>> endobj +1097 0 obj << +/D [1085 0 R /XYZ 109.858 193.812 null] +>> endobj +1098 0 obj << +/D [1085 0 R /XYZ 109.858 86.721 null] +>> endobj +1084 0 obj << +/Font << /F29 416 0 R /F28 380 0 R /F8 369 0 R /F50 672 0 R /F22 363 0 R /F41 556 0 R /F19 516 0 R /F55 716 0 R /F34 719 0 R /F54 713 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +1102 0 obj << +/Length 1790 +/Filter /FlateDecode +>> +stream +xXKoFWHhO Pĵ@-mdZ* +Вfwv. M +}N%D0NE Yg1߲`jC\Rrf>+<X̗;%b"Tj*<?{;g xv`rfQ4{&ci3j0n8 F}DiH6e:rR)'hA8>NC%rDkJI_.i M^6IP 66j=AD´$AE ؙ$,HgS[l쁍lZs 0P}:0wߍR\)5m$Ǎ\fP+I΃ޭx )ԓo`,T(a!B0p.ͳrF֯/w9 ˕}] Zud;1c3"}٬xƒ =ƒzp]o{*g81ϙfEXj Ir37E50nw:Nt8;j N{HJ |e!gW[uhiQF.xeKMI#O'y@¤π_P\PSOrVם*u*;$˒c=.ڦbhIR@F*\ج2nכQz$Ul>=,0UaJjR6wP"~h6b!7;IL2v12u2#Y_|5B-zB8ZZOܠ|/̣D[+Cj~Dy4&D +&""K> endobj +1104 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [401.542 590.512 452.656 601.36] +/Subtype /Link +/A << /S /GoTo /D (ttbxcstmpgscrll.autorange) >> +>> endobj +1107 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [292.282 422.954 373.422 433.803] +/Subtype /Link +/A << /S /GoTo /D (ttbxcstmpgscrll.enableautorange) >> +>> endobj +1109 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [411.976 359.373 495.109 370.221] +/Subtype /Link +/A << /S /GoTo /D (ttbxcstmpgscrll.disableautorang) >> +>> endobj +1111 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [108.862 144.034 187.397 153.997] +/Subtype /Link +/A << /S /GoTo /D (ttbxpanelobject) >> +>> endobj +1112 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [108.862 122.116 183.43 132.079] +/Subtype /Link +/A << /S /GoTo /D (ttbxtextobject) >> +>> endobj +1103 0 obj << +/D [1101 0 R /XYZ 109.858 727.97 null] +>> endobj +1099 0 obj << +/D [1101 0 R /XYZ 109.858 655.09 null] +>> endobj +1105 0 obj << +/D [1101 0 R /XYZ 109.858 553.355 null] +>> endobj +1106 0 obj << +/D [1101 0 R /XYZ 109.858 499.488 null] +>> endobj +1108 0 obj << +/D [1101 0 R /XYZ 109.858 423.951 null] +>> endobj +1110 0 obj << +/D [1101 0 R /XYZ 109.858 360.369 null] +>> endobj +928 0 obj << +/D [1101 0 R /XYZ 109.858 275.252 null] +>> endobj +178 0 obj << +/D [1101 0 R /XYZ 109.858 264.528 null] +>> endobj +1100 0 obj << +/Font << /F29 416 0 R /F54 713 0 R /F22 363 0 R /F41 556 0 R /F8 369 0 R /F19 516 0 R /F28 380 0 R /F50 672 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +1116 0 obj << +/Length 1781 +/Filter /FlateDecode +>> +stream +xڭXKs6WHJOL'VIr%X")vOcv+ISHKDd؜Ho;Ni +'Zm=("K3r p,v,Eh2osbLI˓˓w{)x{Qz'$hV +{N'fon,@uM].W s'W7!z~rvLBc1VjRfrI!8˯~ޝyNؖU{O7_BBRUX YX`VCeT`b.#_~:T +Io F[Hв ]ΑB"^+4汣5xmndp +pvFM{FgD H0մ9֍8ܨ׳ p8bΎ?z6j%鲱כ ٸ͊u S"B,ypZ#Hf% c1xü*yT=Z:R(QTI!i>\ルHЂ$EPe>Gݵ?G3Ag1,sβr@@-C!ePN#6 TA/+ #Ҥc3$>9Ӂ+%_ ]]4ŖfLPD(SfDʄ^pRvy{ˋA)Qշxu]`nэۊcWwOfiFřAzha" SEF<?ta$ϸ0G& صm[HM1xUZwm=brzIZi8tnüzXŁkoPfVbU?02.%+~VL.stjٽ?ACD_j$endstream +endobj +1115 0 obj << +/Type /Page +/Contents 1116 0 R +/Resources 1114 0 R +/MediaBox [0 0 612 792] +/Parent 1068 0 R +/Annots [ 1119 0 R 1121 0 R 1123 0 R ] +>> endobj +1113 0 obj << +/Type /XObject +/Subtype /Form +/FormType 1 +/PTEX.FileName (c_ttbxdockablepanel.pdf) +/PTEX.PageNumber 1 +/PTEX.InfoDict 1126 0 R +/Matrix [1.00000000 0.00000000 0.00000000 1.00000000 0.00000000 0.00000000] +/BBox [0.00000000 0.00000000 21.00000000 21.00000000] +/PieceInfo << +/AdobePhotoshop << +/LastModified (D:20030406201237-05'00') +/Private << +/RoundTrip 1 +/ExportCrispy false +/SaveTransparency false +/ImageResources 1127 0 R +/XObject << +/Im0 1128 0 R +>> +/StandardImageFileData 1129 0 R +>> +>> +>> +/Resources << +/XObject << +/Im0 1128 0 R +>>/ProcSet [ /PDF /ImageC ] +>> +/Length 1130 0 R +>> +stream +q q 21 0 0 21 0 0 cm /Im0 Do Q Q endstream +endobj +1126 0 obj +<< +/Creator (Adobe Photoshop 7.0) +/CreationDate (D:20030406201237-05'00') +/ModDate (D:20030406201237-05'00') +/Producer (Adobe Photoshop for Windows) +>> +endobj +1127 0 obj +<< +/Filter /FlateDecode +/Size 2680 +/Length 1131 0 R +>> +stream +HVyPW !JQvC0Щ)7XX6d1٨QTJa+E&¬=bQ9{ΌBV1;l{j2-C#lC'0XL[Ҳ33$id bYO JOsO 48 ~& lr0pڄcic&W\Hl}l[U>VjƜ[ē}+O4Yo?M[_Kwf-\U@owcSg9xgrA|I$Q|`AX@|] XօΘ1VęA:B(Bu:T3"n(X7*r)5+Rstjvwyگ}s9yk4hW<(#»o71u6m uN]UY<{Rzvw9BUk;춦9]TƫH8u_j^_{HjJ*lo5pmۧJ}ugݍ}0I|xF)RSLSL +U*⢕q1Vah*+oH^s'X7@7l@q9;S8g endstream +endobj +1128 0 obj +<< +/Type /XObject +/Subtype /Image +/Interpolate false +/Filter /FlateDecode +/DecodeParms << +/Predictor 2 +/Colors 3 +/BitsPerComponent 8 +/Columns 28 +>> +/Width 28 +/Height 28 +/BitsPerComponent 8 +/ColorSpace /DeviceRGB +/Length 1132 0 R +>> +stream +H!P + +f`p 7?Zl,#Ogpa+Fuܰ/|y8ἧmū}4MUUeYb1!Ia͢(Ǚ}60DQa\~w] 4'ie<^5Mâ7oy/$Sz:ĤwUfs5Ɯv1?|$_x|;y Qm{7{"4%I0 &Ieq#{a{#7EΎXER>se84^wYUUـ^5EQc: |`M endstream +endobj +1129 0 obj +<< +/Length 1133 0 R +>> +stream +endstream +endobj +1130 0 obj +34 +endobj +1131 0 obj +1524 +endobj +1132 0 obj +326 +endobj +1133 0 obj +0 +endobj +1119 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [173.951 603.139 228.068 613.988] +/Subtype /Link +/A << /S /GoTo /D (ttbxcustmrdbttn.groupindex) >> +>> endobj +1121 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [145.199 512.488 178.007 520.015] +/Subtype /Link +/A << /S /GoTo /D (ttbxcustmrdbttn.checked) >> +>> endobj +1123 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [279.14 418.53 317.386 429.378] +/Subtype /Link +/A << /S /GoTo /D (ttbxcustmrdbttn.checked) >> +>> endobj +1117 0 obj << +/D [1115 0 R /XYZ 109.858 727.97 null] +>> endobj +1118 0 obj << +/D [1115 0 R /XYZ 109.858 681.914 null] +>> endobj +1120 0 obj << +/D [1115 0 R /XYZ 109.858 604.136 null] +>> endobj +1122 0 obj << +/D [1115 0 R /XYZ 109.858 473.394 null] +>> endobj +929 0 obj << +/D [1115 0 R /XYZ 109.858 419.526 null] +>> endobj +182 0 obj << +/D [1115 0 R /XYZ 109.858 408.803 null] +>> endobj +1124 0 obj << +/D [1115 0 R /XYZ 109.858 190.401 null] +>> endobj +1125 0 obj << +/D [1115 0 R /XYZ 109.858 136.533 null] +>> endobj +1114 0 obj << +/Font << /F29 416 0 R /F28 380 0 R /F54 713 0 R /F22 363 0 R /F41 556 0 R /F8 369 0 R /F19 516 0 R /F55 716 0 R /F34 719 0 R /F50 672 0 R >> +/XObject << /Im19 1113 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +1136 0 obj << +/Length 1922 +/Filter /FlateDecode +>> +stream +xڽYYF~_G ++s"CXUlBUȖckY_]>.Tšϯ{ZZ '=)0R/QI%ty&9~&be0Ľ0 mG) +4C>| S&K[P[( U:{wg%^jG!GqJJ*h~y1\>o@i||uvqrtraPt{ԏJDkU6vtgZ~ηK,YJc#*iHh-ep3J!Iynznr|ZV i'=b8fR`(b~sg6=M8hcgoFrh:3BGĬ[;d‰e Z&>>HoMSF-Ww/ͷ H l˔jHMLwh7O?pwZPz@)@k-ĵk;ՠv +dHn1J͆X0)iɟ񧘽(J=P*td'=QK@ӗ#;|^m0ֆYC@{;AM-9H­:ȸpZڒ%"Z$ @ b2a6ty_@OMd'G|9䇡Cv>9iȹ%7R[ "f060\J61FbHtBG" ^am8M-ڶӦB>+(q`a< =Cp$*qg#8b]iu} ,Z QpU}etFω:Q٥lIOP(󫊷j3 +˫Mw2B2&MPͦƖ<<0Z"AÛPGwZ"渡⣐7 +k6C%dӑ(s\L[|r;ۺ)S^똨j27V6 fYޮT"NO nbv@I+JũV4v]OF#PK4:`XK=J֊@%Ϝn?oB9o30j-'53huBx)UG34'v2&\A[]Cc,;N%}ȹρqXs%RdLPYK{sH&uXk $߶J o-yvQV24k0#CfOmlKBZ,L0kfvRk4DH޳MΪmS.)隖2w"KmkР)?$)=}_0R'q?@?=`ZQ (l +vd`[貥f~ޒ@M`Qi{;8 py"%xgV3\D/0eI⮆4si .E2Hk7 ^<8wGZþ6{Oi{ο#BIf=CIH#Āc˵Xࣄƾz?q^ָc)jwAQƩՙοIW8FX跿j\uguceO#n9'T^;Qx2U6~!wߋØ;Ł.DrLrLT m/Y&&HRS<)m:P);ܓY8'ONzGɬ1wչm7 go-por߮"#.ǣI2=Q F۪A {늱nIp/NP e?0gyjendstream +endobj +1135 0 obj << +/Type /Page +/Contents 1136 0 R +/Resources 1134 0 R +/MediaBox [0 0 612 792] +/Parent 1068 0 R +/Annots [ 1144 0 R 1145 0 R 1146 0 R ] +>> endobj +1144 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [132.108 179.105 206.607 189.954] +/Subtype /Link +/A << /S /GoTo /D (ttbxdockablepnl.minclientheight) >> +>> endobj +1145 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [145.199 162.556 208.806 171.633] +/Subtype /Link +/A << /S /GoTo /D (ttbxdockablepnl.minclientheight) >> +>> endobj +1146 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [211.989 162.556 276.536 171.633] +/Subtype /Link +/A << /S /GoTo /D (ttbxdockablepnl.maxclientwidth) >> +>> endobj +1137 0 obj << +/D [1135 0 R /XYZ 109.858 727.97 null] +>> endobj +1138 0 obj << +/D [1135 0 R /XYZ 109.858 645.51 null] +>> endobj +1139 0 obj << +/D [1135 0 R /XYZ 109.858 581.928 null] +>> endobj +1140 0 obj << +/D [1135 0 R /XYZ 109.858 518.346 null] +>> endobj +1141 0 obj << +/D [1135 0 R /XYZ 109.858 430.738 null] +>> endobj +1142 0 obj << +/D [1135 0 R /XYZ 109.858 343.246 null] +>> endobj +1143 0 obj << +/D [1135 0 R /XYZ 109.858 255.754 null] +>> endobj +1147 0 obj << +/D [1135 0 R /XYZ 109.858 163.553 null] +>> endobj +1134 0 obj << +/Font << /F29 416 0 R /F54 713 0 R /F22 363 0 R /F41 556 0 R /F8 369 0 R /F55 716 0 R /F34 719 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +1151 0 obj << +/Length 2046 +/Filter /FlateDecode +>> +stream +xڽYnF}WB{%}K6-U8@ڤ%"Rt;3˫ȊQH̜3ksXG~9YȯHxq 8GxK$NPO'kLb \H<{yq}ggEENgj搕8%/eۭ/WÂK7o>_|^~ѱY#b#%r.+jo]k`io E 8lbJ,,c0ߑPYo XFhLj + 54׫ƴ7PR0N)V(`Mَ<y6+>#sԇ7Q]y<$@Ehk@°XiJ}3[%=#F5iU'u`wTn+򙅖=@F֊qab]x5qhC`?ݱن}^S"p4Zb~6_>DU4yrtb :>‡؊C5DDZd,p:gHYԊPDB!5WѴ|Hq|9gþ/Tߊڇjܜ17vPCgGjuabD!~4>G"/)SC&Od^ aܔ!'bq?72gx?_!1C"{oKŃ4ȯ91v^Pyԅ;0:RXj ]k<*>KmQW7SL_<@rsɳbu1Hش c4n҉B~rcA.kFLaO›]0#FzZd6`TΠd}{+5w J&\ Wt:Q>hJJ+islr^g&lgh-_>afn+RȸI qxab/:^Ckm2^ӬK?W3&;-j!O#[sHMH(u364/+a2zh{+@ *q`m,bxk 1 R7~QAQ]H{ЁX=KzО&d㮥tdrRJJ"8DHI]-z=Vi7 +\Χ(ێ8xiHM|^ Pz@ _Afˉ|ȧ$OD$lDbl7wM;endstream +endobj +1150 0 obj << +/Type /Page +/Contents 1151 0 R +/Resources 1149 0 R +/MediaBox [0 0 612 792] +/Parent 1167 0 R +/Annots [ 1153 0 R 1154 0 R 1155 0 R 1156 0 R 1157 0 R 1159 0 R 1160 0 R 1165 0 R ] +>> endobj +1153 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [108.862 643.96 182.53 652.871] +/Subtype /Link +/A << /S /GoTo /D (ttbxdockablepnl.minclientwidth) >> +>> endobj +1154 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [145.199 625.474 208.1 634.551] +/Subtype /Link +/A << /S /GoTo /D (ttbxdockablepnl.minclientwidth) >> +>> endobj +1155 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [211.283 625.474 276.536 634.551] +/Subtype /Link +/A << /S /GoTo /D (ttbxdockablepnl.maxclientheight) >> +>> endobj +1156 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [145.199 544.84 210.453 553.917] +/Subtype /Link +/A << /S /GoTo /D (ttbxdockablepnl.maxclientheight) >> +>> endobj +1157 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [213.635 544.84 276.536 553.917] +/Subtype /Link +/A << /S /GoTo /D (ttbxdockablepnl.minclientwidth) >> +>> endobj +1159 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [145.199 464.206 209.747 473.283] +/Subtype /Link +/A << /S /GoTo /D (ttbxdockablepnl.maxclientwidth) >> +>> endobj +1160 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [212.93 464.206 276.536 473.283] +/Subtype /Link +/A << /S /GoTo /D (ttbxdockablepnl.minclientheight) >> +>> endobj +1165 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [145.199 110.786 188.349 119.863] +/Subtype /Link +/A << /S /GoTo /D (ttbxdockablepnl.splitwidth) >> +>> endobj +1152 0 obj << +/D [1150 0 R /XYZ 109.858 727.97 null] +>> endobj +1148 0 obj << +/D [1150 0 R /XYZ 109.858 626.47 null] +>> endobj +1158 0 obj << +/D [1150 0 R /XYZ 109.858 545.836 null] +>> endobj +1161 0 obj << +/D [1150 0 R /XYZ 109.858 465.202 null] +>> endobj +1162 0 obj << +/D [1150 0 R /XYZ 109.858 401.117 null] +>> endobj +1163 0 obj << +/D [1150 0 R /XYZ 109.858 337.42 null] +>> endobj +1164 0 obj << +/D [1150 0 R /XYZ 109.858 273.723 null] +>> endobj +1166 0 obj << +/D [1150 0 R /XYZ 109.858 111.782 null] +>> endobj +1149 0 obj << +/Font << /F29 416 0 R /F54 713 0 R /F22 363 0 R /F41 556 0 R /F8 369 0 R /F55 716 0 R /F34 719 0 R /F19 516 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +1170 0 obj << +/Length 2537 +/Filter /FlateDecode +>> +stream +xڥZr6}W#ʃ%. [~:juyCO~zy-١^scR#&\tzk&q)Q2b"P; Ԝ3 #7K%>7y)O=c6*dL?yցґvyb)Va=c5[MG ^+bTk{1@ɾ<lYR@ YoREd{JÉ9h%&[oW9<Y k<+`ytX{I%4 {#<2O]+7-6Z!Df +hivv[ z}&ny̺El%i\!@2Vb]Tg{OngǸWG\Kn3xPgx^pY~5B3tȉtqTHn|s:KB5YzUn<b>2`Gx.wgI [ǼHkmHjPYy>f-yBm_9ގ07vJ5$9\[H"o~7MRI MNO&+ 6eL6.eJH%G&L ";|}n9, .A8z &IA/wn_C.k, )Zv 7d S w?rCSnQWht'(|:B{D6C|H7 ''d"y K2>Grܖ& eE>4XD?wV>> ^gf朗2 '􇣑+qŽ15\BmaA>a6.rÎ Z_{U>N$1`Ay,.6͉R*nJ]g;LϷ3&ɘ~2PE:ZѲeQ7iۀ YD2ADSOO9J,e zEv$[0^JFc%.w9:oownWoc|uR=[(7$_&/74t9q]y-p_ %VVHw3ϔ,$Á1$H'CG 7\PAq'\:$A!쒴6Jl՟0}ZGDJ-*Ɋ,!Xׅqs/R.[#4k'e6 + NX phLG4zr2K(YjzuB뜅ce^_c)t^T*!| e}YE4:!q"5qP̲B&2/h~ï1ᔉ:M>sb&XeYEX:fu\x ^м̋k5@8eub24/x/gdM40jQNf $ Eac[/\wU8T(^GW]cζ/,4o[+m7Nٶ,Wbx>0?-2ҟ IJ:!}+C7kרgW,ز"a_߲c +}~H/CYs}uJGx^q"66KOո8=TMb%Gp|Kʎ*>LX/?cvS6 +)չہJo6!g29B墘P(b'YU𼎕.a{CG,G4_zGLed +kt*ۍBuu%5\Vqi8Vp;ʈn3uİ|Asd@X=|u%% U(!w]M_{_2ik>/51d@i%@; 8 +%BLT^R!IѼ>s󺷯wKEɸV=;4:bF1DrcAdɐ$EI9Ң3n ?0uJ0kDu{(+AN<="ͱ_l;fzWx>\.OUKfesV=#U.Ni{UMݚ<k੶~҃ia ̦@lnn?.=ڇ fMS]C+= 1ݿQ-`endstream +endobj +1169 0 obj << +/Type /Page +/Contents 1170 0 R +/Resources 1168 0 R +/MediaBox [0 0 612 792] +/Parent 1167 0 R +/Annots [ 1172 0 R 1174 0 R 1176 0 R 1177 0 R 1178 0 R 1179 0 R 1180 0 R 1181 0 R 1183 0 R ] +>> endobj +1172 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [145.199 637.429 189.055 646.506] +/Subtype /Link +/A << /S /GoTo /D (ttbxdockablepnl.splitheight) >> +>> endobj +1174 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [165.115 546.943 217.53 557.791] +/Subtype /Link +/A << /S /GoTo /D (ttbxmultidock) >> +>> endobj +1176 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [133.768 403.062 207.437 411.973] +/Subtype /Link +/A << /S /GoTo /D (ttbxdockablepnl.minclientwidth) >> +>> endobj +1177 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [133.768 381.199 208.267 392.047] +/Subtype /Link +/A << /S /GoTo /D (ttbxdockablepnl.minclientheight) >> +>> endobj +1178 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [133.768 363.211 195.675 372.122] +/Subtype /Link +/A << /S /GoTo /D (ttbxdockablepnl.dockedwidth) >> +>> endobj +1179 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [133.768 341.349 196.505 352.197] +/Subtype /Link +/A << /S /GoTo /D (ttbxdockablepnl.dockedheight) >> +>> endobj +1180 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [133.768 321.423 251.3 332.271] +/Subtype /Link +/A << /S /GoTo /D (ttbxdockablepnl.showcptnwhndckd) >> +>> endobj +1181 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [133.768 303.435 228.524 312.346] +/Subtype /Link +/A << /S /GoTo /D (ttbxdockablepnl.smoothdockedrsz) >> +>> endobj +1183 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [284.888 196.954 348.206 207.802] +/Subtype /Link +/A << /S /GoTo /D (ttbxdockablepnl.effectivecolor) >> +>> endobj +1171 0 obj << +/D [1169 0 R /XYZ 109.858 727.97 null] +>> endobj +1173 0 obj << +/D [1169 0 R /XYZ 109.858 638.425 null] +>> endobj +1175 0 obj << +/D [1169 0 R /XYZ 109.858 497.831 null] +>> endobj +1182 0 obj << +/D [1169 0 R /XYZ 109.858 296.461 null] +>> endobj +1168 0 obj << +/Font << /F29 416 0 R /F54 713 0 R /F22 363 0 R /F41 556 0 R /F8 369 0 R /F55 716 0 R /F34 719 0 R /F28 380 0 R /F14 372 0 R /F19 516 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +1188 0 obj << +/Length 1948 +/Filter /FlateDecode +>> +stream +xXmo6_HMkSI~WZJr\7!ڕ0K?&Y1ث9S@qp ྋ67ട H`ADб\{Q}]Z{PYsI\X\s(*8$qI|7٧کP{Z%bJpyl)و2+{8U Xci+( ۭn r` t _S7]HޮD(ZiS_b?U( "'_EZxDQWP8TZwNk0)mDY0zx;N 8"ǘ $ T/[>_V&𓗗pρn:WslΡ 2K_?xC^ K#O8rՖ@y8f۲dh.҂V>(sMf +{> endobj +1184 0 obj << +/Type /XObject +/Subtype /Form +/FormType 1 +/PTEX.FileName (c_ttbxlabel.pdf) +/PTEX.PageNumber 1 +/PTEX.InfoDict 1196 0 R +/Matrix [1.00000000 0.00000000 0.00000000 1.00000000 0.00000000 0.00000000] +/BBox [0.00000000 0.00000000 21.00000000 21.00000000] +/PieceInfo << +/AdobePhotoshop << +/LastModified (D:20030406201244-05'00') +/Private << +/RoundTrip 1 +/ExportCrispy false +/SaveTransparency false +/ImageResources 1197 0 R +/XObject << +/Im0 1198 0 R +>> +/StandardImageFileData 1199 0 R +>> +>> +>> +/Resources << +/XObject << +/Im0 1198 0 R +>>/ProcSet [ /PDF /ImageC ] +>> +/Length 1200 0 R +>> +stream +q q 21 0 0 21 0 0 cm /Im0 Do Q Q endstream +endobj +1196 0 obj +<< +/Creator (Adobe Photoshop 7.0) +/CreationDate (D:20030406201244-05'00') +/ModDate (D:20030406201244-05'00') +/Producer (Adobe Photoshop for Windows) +>> +endobj +1197 0 obj +<< +/Filter /FlateDecode +/Size 2676 +/Length 1201 0 R +>> +stream +HV{LSW?OZ*塨ˤn b{d,[(lęE$NQؒ |0B}Н{K1˾|O4h>M +`ÞlRwDF&D.\H-H90&ʇ4CˌE t:h1F1{k]S7)pKН{rak uUąv(?j +<NsCQ֜.ո* ^AHޙf)i*ї J<:(쫲Pda$L*" هq5%L? +{kzKW(J肋jG̙j4S,*&MS %zg&0tj bh +D^T{4@<+cR3\2H",ϱPf³p>Xȗ5IïEwW2b +D1SNBx[gBP/Z0S& IђjB 8@$Hgr@" +EBH$}IJ Ʉ`{OX+JRi IٿIȄ:!882 a>xu< Q0Dlqx9./|؋F pp`\ p9<_%(ùѼ5b;O13(:6δ=M0*sn\KM?wJԑO<:WfWq75]^ؾdk׭2 +9vp Z.$h.D&"ig lnؙUiyAsY| 2\qp6=?"]^`7 3e 5oٯ}ScGe:|KPOּwXdMh5jnv-m/ϿfzZ"<ۏQm`[i5{o972ʿVD;FTNkbrd/kpרSgzN G YkGXpXѲdRߌūCnyVi:zG|d)@ Hz A1)̈+恹@\\"P Dfg9@ @6ƦR5Dh*g qw0.%+͔$Ekf\9cqybtLb\j}<}Wސ}g,6'~l?N=6qvR&+oendstream +endobj +1198 0 obj +<< +/Type /XObject +/Subtype /Image +/Interpolate false +/Filter /FlateDecode +/DecodeParms << +/Predictor 2 +/Colors 3 +/BitsPerComponent 8 +/Columns 28 +>> +/Width 28 +/Height 28 +/BitsPerComponent 8 +/ColorSpace /DeviceRGB +/Length 1202 0 R +>> +stream +H-s@6.O@lm,_H"qC;ݹIjH*Vd>w4ּ/24vUUM&x܃zQ8Cr9eJ1 y,g2MU焣ʘ2%I&H~[ZLf͆aV+v*Qe(_תp8(2lI,{F/Ԓ2N÷˴B2%'CbRHi"1Ţ<$I*ƴae$bhZN'VEveI.UúqBjUzp\.bćg_'ۛg9-joA3~WE9qOi3u/GI&7E0- +0u_́jqsFڑ{JQ05 endstream +endobj +1199 0 obj +<< +/Length 1203 0 R +>> +stream +endstream +endobj +1200 0 obj +34 +endobj +1201 0 obj +1522 +endobj +1202 0 obj +393 +endobj +1203 0 obj +0 +endobj +1185 0 obj << +/Type /XObject +/Subtype /Form +/FormType 1 +/PTEX.FileName (c_ttbxlink.pdf) +/PTEX.PageNumber 1 +/PTEX.InfoDict 1204 0 R +/Matrix [1.00000000 0.00000000 0.00000000 1.00000000 0.00000000 0.00000000] +/BBox [0.00000000 0.00000000 21.00000000 21.00000000] +/PieceInfo << +/AdobePhotoshop << +/LastModified (D:20030406201249-05'00') +/Private << +/RoundTrip 1 +/ExportCrispy false +/SaveTransparency false +/ImageResources 1205 0 R +/XObject << +/Im0 1206 0 R +>> +/StandardImageFileData 1207 0 R +>> +>> +>> +/Resources << +/XObject << +/Im0 1206 0 R +>>/ProcSet [ /PDF /ImageC ] +>> +/Length 1208 0 R +>> +stream +q q 21 0 0 21 0 0 cm /Im0 Do Q Q endstream +endobj +1204 0 obj +<< +/Creator (Adobe Photoshop 7.0) +/CreationDate (D:20030406201249-05'00') +/ModDate (D:20030406201249-05'00') +/Producer (Adobe Photoshop for Windows) +>> +endobj +1205 0 obj +<< +/Filter /FlateDecode +/Size 2720 +/Length 1209 0 R +>> +stream +HVyPWB$bS!\Br"6$jQ!K Z"-cEBǙJQc +n߾8~wkK޷ JHF\sm^Ζ:`íMl&6J/_GKqf|Qǃth!,XM=6MSlՄy| +.cmb[9yoy٪̎`c4n8Hhz@L`y_l:XeLo\x -i1I51JGZlo4ixEYF4T jLn^F,63#D6qEr;L%N%"ML#ndA$Ifb4 EFܔFzlsvd cI2x[L:fھDӈJft8S xub-IAlU9K2HӆH"`$V5S]=f!(=7Q/ݝh M+glȬNPf|| XR-Iw_qVz;B8)X +,D` +V7NlB,xMiщG?2~X,T$$N6E.E- ,sv\e2;3I@ bxi|_yt,|x8P 8:a1[.`|'t|i04|n}5s68Ĵb]}:s?[K9]N󼤹Uqe˭G<_5z\}`Yz֢ok^ [nXڝrAA$ Ef + >n ͅ SgiL[vF'{!}"_KD>F3o(1 +t;3@ E :|mӕչt Jb U v)W-5׿h?b8|g{;;3 7}5^g  5: ~lֵ?N%8SKxgܺJeODqcHgHK{Xn@n >wxHYe*dUxcr~^JB{wkm;~ϙn4PUv箪?ה]T &_),\Ia> +/Width 28 +/Height 28 +/BitsPerComponent 8 +/ColorSpace /DeviceRGB +/Length 1210 0 R +>> +stream +H?P0((bY +.Xi <@qKmL T.!!]p7i1/͗7yyOaF#8: :al*-Cb :|"4d2YTq + 1V6WY*%~lzlj&uv%6T*u.[MJBL\3á6 P(ngAl6h> +stream +endstream +endobj +1208 0 obj +34 +endobj +1209 0 obj +1574 +endobj +1210 0 obj +438 +endobj +1211 0 obj +0 +endobj +1191 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [145.199 538.77 222.732 547.847] +/Subtype /Link +/A << /S /GoTo /D (ttbxresizingstage) >> +>> endobj +1192 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [108.862 408.161 187.397 418.124] +/Subtype /Link +/A << /S /GoTo /D (ttbxpanelobject) >> +>> endobj +1193 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [108.862 386.243 183.43 396.206] +/Subtype /Link +/A << /S /GoTo /D (ttbxtextobject) >> +>> endobj +1194 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [108.862 366.069 191.029 374.288] +/Subtype /Link +/A << /S /GoTo /D (ttbxcustomlabel) >> +>> endobj +1195 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [372.641 264.72 461.309 275.568] +/Subtype /Link +/A << /S /GoTo /D (ttbxcustomlabel) >> +>> endobj +1189 0 obj << +/D [1187 0 R /XYZ 109.858 727.97 null] +>> endobj +1190 0 obj << +/D [1187 0 R /XYZ 109.858 681.914 null] +>> endobj +930 0 obj << +/D [1187 0 R /XYZ 109.858 539.766 null] +>> endobj +186 0 obj << +/D [1187 0 R /XYZ 109.858 529.042 null] +>> endobj +963 0 obj << +/D [1187 0 R /XYZ 109.858 253.761 null] +>> endobj +190 0 obj << +/D [1187 0 R /XYZ 109.858 243.037 null] +>> endobj +1186 0 obj << +/Font << /F29 416 0 R /F28 380 0 R /F54 713 0 R /F22 363 0 R /F41 556 0 R /F8 369 0 R /F19 516 0 R /F55 716 0 R /F34 719 0 R /F50 672 0 R >> +/XObject << /Im20 1184 0 R /Im21 1185 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +1215 0 obj << +/Length 1413 +/Filter /FlateDecode +>> +stream +xWo6_G XK%GvRoAXlܬwGR"94H4Ɉ:PLLfwpzS5,(_^( f$R~^|+DX',,SW)LA=ſ0)V薆O, 6`^ۈ4f[ &@թ$'bؕcK1-;Z]_ܿ8 ڈҐm4 GQM\&){:pv#\,!R4yQ +׸,BGBt,B!:cx=ޡ˛(*W`f4%h0LhxI4 ;ũ0"F +qa$kz:0Q`X۲xSBT@H-<)8J7 D_{̠1$$)z7:x3(´ES:ՁPqp'f<^ +4 iz7vQ +ڔ=i\UDB$99 G{B3k|L%$M\4'+a˱[p/ * Sn|ڳuٮ͊@Ͳ4|u +J@Mm |UT%xEn 8K; DKX`=V(swvKn,gZcO~[4aoxvг_{ wxn!Yo^c]HM!>(.o?x c]A$cʇjmsQC]N1JlG?Eendstream +endobj +1214 0 obj << +/Type /Page +/Contents 1215 0 R +/Resources 1213 0 R +/MediaBox [0 0 612 792] +/Parent 1167 0 R +/Annots [ 1217 0 R 1218 0 R 1219 0 R 1220 0 R 1221 0 R ] +>> endobj +1212 0 obj << +/Type /XObject +/Subtype /Form +/FormType 1 +/PTEX.FileName (c_ttbxpagescroller.pdf) +/PTEX.PageNumber 1 +/PTEX.InfoDict 1223 0 R +/Matrix [1.00000000 0.00000000 0.00000000 1.00000000 0.00000000 0.00000000] +/BBox [0.00000000 0.00000000 21.00000000 21.00000000] +/PieceInfo << +/AdobePhotoshop << +/LastModified (D:20030406201301-05'00') +/Private << +/RoundTrip 1 +/ExportCrispy false +/SaveTransparency false +/ImageResources 1224 0 R +/XObject << +/Im0 1225 0 R +>> +/StandardImageFileData 1226 0 R +>> +>> +>> +/Resources << +/XObject << +/Im0 1225 0 R +>>/ProcSet [ /PDF /ImageC ] +>> +/Length 1227 0 R +>> +stream +q q 21 0 0 21 0 0 cm /Im0 Do Q Q endstream +endobj +1223 0 obj +<< +/Creator (Adobe Photoshop 7.0) +/CreationDate (D:20030406201301-05'00') +/ModDate (D:20030406201301-05'00') +/Producer (Adobe Photoshop for Windows) +>> +endobj +1224 0 obj +<< +/Filter /FlateDecode +/Size 2644 +/Length 1228 0 R +>> +stream +HVyLWfgOXëTU\Km*rCE֖ :g)4mWFԪmQPbjQ+ p쥘{NMΕFO ME6K l=ۤئqG$~X1#e*g!D<>,qd`ٌ,4bٵmK<4;5xO0_ I𞕮ڣ}Jf +CvUMG @#,E) P`GZ0@BI^iHxha5 n{qn ř&2r +T2o)c=d.7Rb:z p-XNȭGJ-V@::$:X&RR2a*)Gp5%?t-F^J/H8j)m*10 N-O-J r(sfyŔ½ةv5XRyW+d <7+X2)ШiE}N>qٳi1K=)Kz8 +*J4]723We.dcJRsAuK`Zg`-JJVZ__mZ2"(($(hVI\&Ok4`~ !JP wm]&JI, 6'J/ 4!%HT"Sȕ2RZR:60F<4(|*7xQsՏF7Nl~2@M{-1v뭧TwEcqϼwʘ돺\A]9fpu5丹qQr͝Vߘ֤I;ZOZm`yW;w.h}fV%Tޑ7ݮ+\;cpcǎټ +m%GWTX\{ڎ햞uv~z?WU3x"9ӎ:Ӗ%i{̘/GIO_sE©E<`!EÎJaѠ?pͅW +"2\b胮E"_|7z_\-h@;4JDK*cX^.hu麸麄0nz c#q@ĕ7tMOďs;)KZ2endstream +endobj +1225 0 obj +<< +/Type /XObject +/Subtype /Image +/Interpolate false +/Filter /FlateDecode +/DecodeParms << +/Predictor 2 +/Colors 3 +/BitsPerComponent 8 +/Columns 28 +>> +/Width 28 +/Height 28 +/BitsPerComponent 8 +/ColorSpace /DeviceRGB +/Length 1229 0 R +>> +stream +H액P0(X  + + +l78Q}|T}   +2ve?\\L1iqYeŖ}syQ9veu뺤@DZ$2i1$Af, Xދ ow p0ܝID[OR/ΎqspQy{4 4wdzzEyiGý+n#2۶ɰf{>#[&2( +`> +stream +endstream +endobj +1227 0 obj +34 +endobj +1228 0 obj +1484 +endobj +1229 0 obj +322 +endobj +1230 0 obj +0 +endobj +1217 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [108.862 645.052 187.397 655.015] +/Subtype /Link +/A << /S /GoTo /D (ttbxpanelobject) >> +>> endobj +1218 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [108.862 623.134 183.43 633.097] +/Subtype /Link +/A << /S /GoTo /D (ttbxtextobject) >> +>> endobj +1219 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [108.862 602.96 186.93 611.179] +/Subtype /Link +/A << /S /GoTo /D (ttbxcustomlink) >> +>> endobj +1220 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [216.553 530.502 271.68 541.351] +/Subtype /Link +/A << /S /GoTo /D (ttbxlabel) >> +>> endobj +1221 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [194.117 506.592 274.565 517.44] +/Subtype /Link +/A << /S /GoTo /D (ttbxtextobject) >> +>> endobj +1216 0 obj << +/D [1214 0 R /XYZ 109.858 727.97 null] +>> endobj +964 0 obj << +/D [1214 0 R /XYZ 109.858 507.588 null] +>> endobj +194 0 obj << +/D [1214 0 R /XYZ 109.858 496.865 null] +>> endobj +1222 0 obj << +/D [1214 0 R /XYZ 109.858 343.404 null] +>> endobj +965 0 obj << +/D [1214 0 R /XYZ 109.858 289.536 null] +>> endobj +198 0 obj << +/D [1214 0 R /XYZ 109.858 278.813 null] +>> endobj +1213 0 obj << +/Font << /F29 416 0 R /F28 380 0 R /F50 672 0 R /F8 369 0 R /F22 363 0 R /F41 556 0 R >> +/XObject << /Im22 1212 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +1233 0 obj << +/Length 2626 +/Filter /FlateDecode +>> +stream +xڵے}EUhc{oz[ujw(<;||ΥLMR1}9}/-$O"q恑&&n`;)9 q/6 -B_` ؾSXjntjcir7o>y{&Q]!"l]ki۟JfS~]f=b )<3M"eÿ4ןޭ a|,z2ħp?jIuL,9=y ttFslBmVeWt+ 8xd +d#DҙOHJͫY70KdiORHaEhQئlY +ϰLgdLX9f(C\ۏ+iW~hpXnɱ!e&VVYB2ŹR3'879Cz`^3W A ~Uǡl~2-[ruq/q­)Uâz(֋Ԗ??Q#ʡ@-ueg5EpaīH#h㬝}6MHKJ!9%Al˾5A~Ib +'ǺaW&A7YS#hvf%_ ,*fxcj""(AtgT_,y%%ID"6,,<ϥSkPʣ&&LC>8#E_Lĉ 20_i|?{@kþt͎' Gb-Aƚ.Ba'd('Zdm~?nCйHA2ޛ)=}+ <ˆAoXU iN>O*rgW\R`ۖa~ #i Gp&Xfj'VpܷEi߈*#="UQ_JC#a@ H#oR cYzݳ!LUrx8ұ@oQ|RqEZS]qw \H(ɇ +57 rxp b24n㾪+Z kKCEqYg^4*TN1&2`[Yrޙ"?Y\-䛻/{AW5Egj1Tmue=66/ϐ=/KY&d(5dߕ]7 ~ s}Hs4/n)ʘT%0.FGSQnJ„~Q} oZzڜzܜ.\yiK WQ w2R Dғ/ˬ/@̛9$xOfgdaNX#Y"gǧ1_ ]JĚ$y8gY't"7y+ը'$Uj&ɽhs*_([a*]fD{u}^eD-uʮkq.Q՚< S"Gm`7C7'CL\{l K@65?nomS^*Hש.74tDr;1bely۹y{E3""}]|B\מ>2(4k1 R4"R#ma`/FZp7޺v{v!F%fTr';mJwjHԳYWݡ# {FmiꧩږX&!a&Btޗ\e׺jlGWx+qof#xk,=ݎ͒ r[-_+CEX4JɄ70-+!2CiykWMǂυ zZJE-U)|odn#<&{7t^ܲm1LFUP/Ur ˳JW4Cvڜf_{^~v^Q>u$ uv +hEŵCq&3%=TuބJ_|D{YMyjrsx9ơD?+TAzg^-G.+ N?endstream +endobj +1232 0 obj << +/Type /Page +/Contents 1233 0 R +/Resources 1231 0 R +/MediaBox [0 0 612 792] +/Parent 1167 0 R +/Annots [ 1235 0 R 1236 0 R 1237 0 R 1238 0 R 1239 0 R 1240 0 R ] +>> endobj +1235 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [108.862 645.052 218.208 655.015] +/Subtype /Link +/A << /S /GoTo /D (ttbxcustompagescroller) >> +>> endobj +1236 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [223.368 560.639 317.931 571.488] +/Subtype /Link +/A << /S /GoTo /D (ttbxdockablepanel) >> +>> endobj +1237 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [480.496 438.099 538.252 448.947] +/Subtype /Link +/A << /S /GoTo /D (ttbxalignmentpanel) >> +>> endobj +1238 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [108.862 426.144 156.932 436.992] +/Subtype /Link +/A << /S /GoTo /D (ttbxalignmentpanel) >> +>> endobj +1239 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [147.882 233.427 217.731 244.276] +/Subtype /Link +/A << /S /GoTo /D (ttbxdockablepanel) >> +>> endobj +1240 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [238.432 233.427 298.706 244.276] +/Subtype /Link +/A << /S /GoTo /D (ttbxpagescroller) >> +>> endobj +1234 0 obj << +/D [1232 0 R /XYZ 109.858 727.97 null] +>> endobj +966 0 obj << +/D [1232 0 R /XYZ 109.858 427.14 null] +>> endobj +202 0 obj << +/D [1232 0 R /XYZ 109.858 416.416 null] +>> endobj +1231 0 obj << +/Font << /F29 416 0 R /F28 380 0 R /F50 672 0 R /F8 369 0 R /F19 516 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +1243 0 obj << +/Length 2122 +/Filter /FlateDecode +>> +stream +xڽYnF}W/e֎ x:@jGÈ"$G~El `Owuuu9UEJG ӑNJUE\yJ[XǕժ(`k*DdA2FE$ڀa+ Ɖ2\Z*pI Ѥ̠ +9^t7~gʈ~Hjk.}۵_z5i %E穛1biL#Vo~šj}3,C5MPe>KeQsV6W&M_:Y]D)`7%+jM:/: Zv"8@-hχ +z/{'ӥ.S6 */Rw_&^cs"š(s*# Jd3a9 +]ZDȥa0~bvYRg$"|_}mB\_EGdn/ +dnoB;c p$L1zJ FҤ<>_`&}/cPEy`{>ࠆA8=N`Bumk(ik׀?|+;O!/Gs[5՟yyx%v ]0e<]Ótc$7tMn#BsN2=xӘxvgS(\^p0x}sо-RMîE!\AzsN#_>-k'l5|+[胚"2 5;{E%pҳC(Qfa5*uZDh=X?M3W / lIHb˔w 6U݊ '-J1F*^ݵd{ւ'b 0GAKsIybɂVp\]$ÓM15]jړQI\*t?<mb2]8HV;#z"|w{2rZtg^^ɷ,@8Ѭ$<i15)dg!O8$%)qG{u zyDB޵:8Y O>w } S^'ixw, k ʏ5"68{`ȁ> endobj +1248 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [244.674 358.87 362.732 369.718] +/Subtype /Link +/A << /S /GoTo /D (ttbxcustompagescroller) >> +>> endobj +1250 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [145.199 239.895 203.329 247.422] +/Subtype /Link +/A << /S /GoTo /D (ttbxpanelobject.onmouseleave) >> +>> endobj +1252 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [145.199 159.261 202.866 166.788] +/Subtype /Link +/A << /S /GoTo /D (ttbxpanelobject.onmouseenter) >> +>> endobj +1244 0 obj << +/D [1242 0 R /XYZ 109.858 727.97 null] +>> endobj +1245 0 obj << +/D [1242 0 R /XYZ 109.858 681.914 null] +>> endobj +1246 0 obj << +/D [1242 0 R /XYZ 109.858 527.423 null] +>> endobj +1247 0 obj << +/D [1242 0 R /XYZ 109.858 413.618 null] +>> endobj +1249 0 obj << +/D [1242 0 R /XYZ 109.858 309.758 null] +>> endobj +1251 0 obj << +/D [1242 0 R /XYZ 109.858 240.891 null] +>> endobj +967 0 obj << +/D [1242 0 R /XYZ 109.858 160.257 null] +>> endobj +1241 0 obj << +/Font << /F29 416 0 R /F28 380 0 R /F54 713 0 R /F22 363 0 R /F41 556 0 R /F8 369 0 R /F19 516 0 R /F55 716 0 R /F34 719 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +1256 0 obj << +/Length 1350 +/Filter /FlateDecode +>> +stream +xWY6~DxIdHP`7 HSr$m7!ɖhba9{I&9ϩb7I=2a#j K<ݭ/g=gJN6iCJ ܒFGXKCv vfr҉8IIni'Xz"3̗Yʺ/y''K ,bs%Zs :}ij>}{m,xTm3CѠMV&Pd +.A?j%rʕdu`Y Tl̤T1f]m悽bm[흙Rm$TpE!n,,An"N,M=0KCL*|"}U O6qA+(=`PTG!4M&2*)뢎[h/.*-RͯЭv? F.2ȰdOJBK\BNQŨ ?wԓv~' Egb` +<9::} ݢX7wqchGj+hfTYFђއ<'јZEgopq).J!@8.fL| /ʶ ?= C±-h:)M,EHBZ'\v T|n!C! Lu,͡ݜA.%צ wXp#TX*hEW=F-Zrȴ.ݺi=.cC,;\XCg4N$ˣ7h NW+Ў;4/pT}E0uUp]GXAu۸;M +7wj8X/l @MUv0dam3 ->6n 2'LSQahkf NH!"uJ hE +<_1jÙᰀHe06=$e*@k{;m}}Cgb hJ\)=+Fa3Mv2@IqJĞ!Q}Q{ooyZڎ-P omVtep_G9vsߕ{cxu% PP +[8rՂiZǟ#5y p=OX$. IعU$\q\f=eō3?OG-*!{Md>_SI@FϾ%|D}bendstream +endobj +1255 0 obj << +/Type /Page +/Contents 1256 0 R +/Resources 1254 0 R +/MediaBox [0 0 612 792] +/Parent 1263 0 R +/Annots [ 1258 0 R 1259 0 R 1260 0 R 1261 0 R ] +>> endobj +1253 0 obj << +/Type /XObject +/Subtype /Form +/FormType 1 +/PTEX.FileName (c_ttbxradiobutton.pdf) +/PTEX.PageNumber 1 +/PTEX.InfoDict 1264 0 R +/Matrix [1.00000000 0.00000000 0.00000000 1.00000000 0.00000000 0.00000000] +/BBox [0.00000000 0.00000000 21.00000000 21.00000000] +/PieceInfo << +/AdobePhotoshop << +/LastModified (D:20030406201305-05'00') +/Private << +/RoundTrip 1 +/ExportCrispy false +/SaveTransparency false +/ImageResources 1265 0 R +/XObject << +/Im0 1266 0 R +>> +/StandardImageFileData 1267 0 R +>> +>> +>> +/Resources << +/XObject << +/Im0 1266 0 R +>>/ProcSet [ /PDF /ImageC ] +>> +/Length 1268 0 R +>> +stream +q q 21 0 0 21 0 0 cm /Im0 Do Q Q endstream +endobj +1264 0 obj +<< +/Creator (Adobe Photoshop 7.0) +/CreationDate (D:20030406201305-05'00') +/ModDate (D:20030406201305-05'00') +/Producer (Adobe Photoshop for Windows) +>> +endobj +1265 0 obj +<< +/Filter /FlateDecode +/Size 2578 +/Length 1269 0 R +>> +stream +HVypU/ICi)PIz1ҖDtrl6&:U +tA` 3J`8V`"T +mon.(8~w}{ZhJO:ME6W>X +oc6XbQF2GG],qP,exbxY̗)uuBY.F Mk> +ix~AM6'58矘oxo{Vj)& і 9bN@cA,B6 ) +Oy0ٞ$]X 4Z$<0;:3a{57R4h +Aձr!ԋ2QrO{G=GmCC + 4Dx)oIJ>h&!9`RKl,5PskxeO|tUܪGk~hiYuahޠ Unjq+5B|YPWI4˻7Q>v:]mw14(.) </XafSQ!j +^^Qw|HB#cqB"Q&&xVPTF; t%%u*MSEV ~Z,b>w,RRjT* Q #4 ~$.Uc:VjI/&wJL$.K0ALb 9LPbQ#"h(D*)JDFędm<~զ'$Tgf,Ruß=mV9mfsOU_ZwK2W>rׁlq`nׂnk B+ŘrY6b"zeU<`[}KVU&8Y<EzSDgquK] Ax20$Չ^R[4ýSL=/?tzvW[yn-Z|vsϽKn7'-o.H+6{pZ#qggݮ }=qF7%L+Z t7g=;m7dz..| [jw[V?o֮I?-cϽ>{<mlooے۟oX;Tys}u䵎9a.њf );@5JLpP- +,F<y1׀%k w4+PxQ;v#%M ɑQstI8w  01endstream +endobj +1266 0 obj +<< +/Type /XObject +/Subtype /Image +/Interpolate false +/Filter /FlateDecode +/DecodeParms << +/Predictor 2 +/Colors 3 +/BitsPerComponent 8 +/Columns 28 +>> +/Width 28 +/Height 28 +/BitsPerComponent 8 +/ColorSpace /DeviceRGB +/Length 1270 0 R +>> +stream +H1@ E eJ(Lڽ +pڴ4tp ?X,!6q1<֛o{fy^ma4M8߲,4 Pf뺺98-&E?MS1[-fyAdY5I$ض{&D6MPUUeYz*u"yWuL-̶mIfPi#eOj3bp0Aaҝvی(YMʁ#_?с O~V(utp^> +stream +endstream +endobj +1268 0 obj +34 +endobj +1269 0 obj +1418 +endobj +1270 0 obj +311 +endobj +1271 0 obj +0 +endobj +1258 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [108.862 590.993 187.397 600.956] +/Subtype /Link +/A << /S /GoTo /D (ttbxpanelobject) >> +>> endobj +1259 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [108.862 569.076 183.43 579.038] +/Subtype /Link +/A << /S /GoTo /D (ttbxtextobject) >> +>> endobj +1260 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [108.862 548.901 220.847 557.121] +/Subtype /Link +/A << /S /GoTo /D (ttbxcustomradiobutton) >> +>> endobj +1261 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [108.862 322.312 187.397 332.275] +/Subtype /Link +/A << /S /GoTo /D (ttbxpanelobject) >> +>> endobj +1257 0 obj << +/D [1255 0 R /XYZ 109.858 727.97 null] +>> endobj +206 0 obj << +/D [1255 0 R /XYZ 109.858 703.064 null] +>> endobj +968 0 obj << +/D [1255 0 R /XYZ 109.858 453.53 null] +>> endobj +210 0 obj << +/D [1255 0 R /XYZ 109.858 442.806 null] +>> endobj +1262 0 obj << +/D [1255 0 R /XYZ 109.858 200.743 null] +>> endobj +992 0 obj << +/D [1255 0 R /XYZ 109.858 146.927 null] +>> endobj +1254 0 obj << +/Font << /F29 416 0 R /F28 380 0 R /F8 369 0 R /F50 672 0 R /F54 713 0 R /F22 363 0 R /F41 556 0 R >> +/XObject << /Im23 1253 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +1274 0 obj << +/Length 2537 +/Filter /FlateDecode +>> +stream +xڵYmo6_剤^SC];H]eWړ!#CK"g|?A(]%"aY/b-9KS> tG`Y!?0ڏV"2&wvd uF"AiRv뻼"[!p{n}zVFxquӍd`23)=BwOBZ{_/^^]sC '=\ʲ8B1)B +S֑L92šsAFędS|xJ% +fmpkwr{:6R(bXZ2J +Q[i-tNd0+$, +Rm +UzQ70ɼlWȆ6eLI+dW]#]VNt"=[jϢSxSw`-+]!WK։EEEcۢ9'Gm=$jnfNHf(XⱣ3Zz<A5Aw:3,6}CjɌAH)5eFj^s6W>Q7-̝#ꝎXk5RõXč}~67ka=+3];b c FR;rӯC gʌմvq[=➦kLN㐞];N#yk((Xehcl#I#bZ3CW#ڋBVT7E}>g"e5O"'}}PPw<<,+Rn9|} 0r_ب}:9y9=03xϪT1UC:tC`Čdpf~z5m0NPiz'&Skh~Y; +BcY Aw4m "3Bo9gT,I˃CcC=$@BNqf2OdkOnfJ9҆H,QjwJu}Tw3GHmVzaTdCê ۾J*[}t v6t"Q-/'ukoj + +"pD WSa {im71I ?e<9Pd,L,9C42rMj-`K,f"ay$xBg]ȦEXZ7-mԘMrQBվ7ZlR YCa0=KppLáx1_VK]_Ig{ww뤫E vF,:yjxmqV> endobj +1279 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [145.199 349.657 216.389 358.734] +/Subtype /Link +/A << /S /GoTo /D (ttbxdockablepnl.ondockedresizng) >> +>> endobj +1280 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [133.768 237.312 202.977 247.274] +/Subtype /Link +/A << /S /GoTo /D (ttbxcoloritem) >> +>> endobj +1281 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [133.768 224.111 225.354 232.33] +/Subtype /Link +/A << /S /GoTo /D (ttbxcomboboxitem) >> +>> endobj +1282 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [133.768 207.424 255.759 217.386] +/Subtype /Link +/A << /S /GoTo /D (ttbxcustomdropdownitem) >> +>> endobj +1283 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [133.768 192.48 247.676 202.442] +/Subtype /Link +/A << /S /GoTo /D (ttbxcustomspinedititem) >> +>> endobj +1284 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [133.768 177.536 224.734 187.498] +/Subtype /Link +/A << /S /GoTo /D (ttbxdropdownitem) >> +>> endobj +1285 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [133.768 162.592 198.732 172.554] +/Subtype /Link +/A << /S /GoTo /D (ttbxedititem) >> +>> endobj +1286 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [133.768 147.648 203.599 157.61] +/Subtype /Link +/A << /S /GoTo /D (ttbxlabelitem) >> +>> endobj +1287 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [133.768 134.447 199.929 142.666] +/Subtype /Link +/A << /S /GoTo /D (ttbxmrulist) >> +>> endobj +1288 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [133.768 117.76 218.618 127.723] +/Subtype /Link +/A << /S /GoTo /D (ttbxmrulistitem) >> +>> endobj +1289 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [133.768 102.816 216.651 112.779] +/Subtype /Link +/A << /S /GoTo /D (ttbxspinedititem) >> +>> endobj +1275 0 obj << +/D [1273 0 R /XYZ 109.858 727.97 null] +>> endobj +1276 0 obj << +/D [1273 0 R /XYZ 109.858 654.974 null] +>> endobj +1277 0 obj << +/D [1273 0 R /XYZ 109.858 550.43 null] +>> endobj +214 0 obj << +/D [1273 0 R /XYZ 109.858 456.642 null] +>> endobj +969 0 obj << +/D [1273 0 R /XYZ 109.858 424.059 null] +>> endobj +1278 0 obj << +/D [1273 0 R /XYZ 109.858 424.059 null] +>> endobj +681 0 obj << +/D [1273 0 R /XYZ 109.858 350.653 null] +>> endobj +218 0 obj << +/D [1273 0 R /XYZ 109.858 335.64 null] +>> endobj +1290 0 obj << +/D [1273 0 R /XYZ 109.858 99.827 null] +>> endobj +1272 0 obj << +/Font << /F29 416 0 R /F54 713 0 R /F22 363 0 R /F41 556 0 R /F8 369 0 R /F19 516 0 R /F28 380 0 R /F55 716 0 R /F34 719 0 R /F50 672 0 R /F51 675 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +1304 0 obj << +/Length 2120 +/Filter /FlateDecode +>> +stream +xڭYYs6~ׯ#DYN2TeמT\䁚$nf IEFW!M$DTv=wۮ8Cv[NJʘISaR(8(=8$Yؓ,4TQY¹=1o[*> jKJf%(0!כHJv5ga}0oe2`§7BwV|/-QQ';x ',3&HSb<{ɊF–~)ʔhxh),^ȉI}"ZڽhSx9]#)gݓYnɠ'&{uKǮ¿;X~, $[m`fxW+fBˠ2N0t8ξHKG }Dry0iMO%B`8BafL" _5La!F$̼"_7$6NW,CJd?mTo옏 +}|Srr&e1e9|pKxYPž8DC4kH0'رaha~xW<sc|:PBLk4:Lgg/ [ۣS{w5ʛ[-rlp@=>^ukVg$5cab'}fW¼<`X{#siTƍcvs;De';43ws$+貁 Jt?ږsEksGE +4s%/ ^'|Q^]2yON?)Pæe'4wt7yS-a"ٞw"L9hĺ3vE=(<[B+%!OTE9󕂫T h4eѹv %,NRM❟w4 ?=oF9z\{Pq PK49毺g4b]ދge0jhV0xP%>XÆk +88y +w+`bNj-up] ^䖲^mڎфuߍ=|%w7޼WL.Qi!^z@iP)AHW\$z +ZLNJ=ڥRU'Q݄ +8+O fl:u2Ӯi}2'ͦv$Ƴ쟱͚ڥCb޷#ʾBsLř +]X@dxׄk# ԛJD~} Wh۪6wˀ'YQEԌuj:~V~*%-z.W1xFL > endobj +1300 0 obj << +/Type /XObject +/Subtype /Form +/FormType 1 +/PTEX.FileName (c_ttbxcoloritem.pdf) +/PTEX.PageNumber 1 +/PTEX.InfoDict 1316 0 R +/Matrix [1.00000000 0.00000000 0.00000000 1.00000000 0.00000000 0.00000000] +/BBox [0.00000000 0.00000000 15.00000000 15.00000000] +/PieceInfo << +/AdobePhotoshop << +/LastModified (D:20030406201229-05'00') +/Private << +/RoundTrip 1 +/ExportCrispy false +/SaveTransparency false +/ImageResources 1317 0 R +/XObject << +/Im0 1318 0 R +>> +/StandardImageFileData 1319 0 R +>> +>> +>> +/Resources << +/XObject << +/Im0 1318 0 R +>>/ProcSet [ /PDF /ImageC ] +>> +/Length 1320 0 R +>> +stream +q q 15 0 0 15 0 0 cm /Im0 Do Q Q endstream +endobj +1316 0 obj +<< +/Creator (Adobe Photoshop 7.0) +/CreationDate (D:20030406201229-05'00') +/ModDate (D:20030406201229-05'00') +/Producer (Adobe Photoshop for Windows) +>> +endobj +1317 0 obj +<< +/Filter /FlateDecode +/Size 2582 +/Length 1321 0 R +>> +stream +HV{PTU?}˲.x*X3검 +)9=aw/8w޻dfG3`&9c+ 4|V3ZE i sϽR9|;߽9;?D6|d#$[&OZ,tb,24<5T&A1*L$ dQ#`̩E +)Jlg_cshi<+9b~B" Y='8$[juehT\o`2naUsL}c…ѨiVC}HA;/ft 8 +"T*W ϐ>LH@tJl;csK:,Z! 6JRj֠ "ڈ)Fc8Š$- huzNot&aҙÿI * a B(T@mN&W(U0 |Aze$d\PIm +2HY\d<cue9 ӣʻ)r36Uܺ|ƦMUi;; +g?y'm6ˣgYV۰qˇ [/ V1)4 !.9R7-ZLSR[/{oʭg(ĴCĎu@Kg@uëfVmWA5t$m,pV{w?ntF?*Hb>;sx@o?Į7-Wg]|_ ;I'3=tOg+_f[ֶ[$7(sw M'3[yRLkh_G'/wT{ٲ 'v0tǡk>Qa3vf;<5E 75 v:.6=:v-ٚuGnܿ:t|dpux늢>e9[q۩Oʲ]^Vtqłx s` "%%IJ>d8 ȥ +8SALƗh3mh|F$w{R'1]flN0fZɖ K:n6(>h#yMmdLI "?H@nH2^`0endstream +endobj +1318 0 obj +<< +/Type /XObject +/Subtype /Image +/Interpolate false +/Filter /FlateDecode +/DecodeParms << +/Predictor 2 +/Colors 3 +/BitsPerComponent 8 +/Columns 20 +>> +/Width 20 +/Height 20 +/BitsPerComponent 8 +/ColorSpace /DeviceRGB +/Length 1322 0 R +>> +stream +H??zǏ߿xprrrppp_|yg>G///$\ׯ]fooߑZZZp@KϞ=sA> +stream +endstream +endobj +1320 0 obj +34 +endobj +1321 0 obj +1424 +endobj +1322 0 obj +268 +endobj +1323 0 obj +0 +endobj +1301 0 obj << +/Type /XObject +/Subtype /Form +/FormType 1 +/PTEX.FileName (c_ttbxcomboboxitem.pdf) +/PTEX.PageNumber 1 +/PTEX.InfoDict 1324 0 R +/Matrix [1.00000000 0.00000000 0.00000000 1.00000000 0.00000000 0.00000000] +/BBox [0.00000000 0.00000000 15.00000000 15.00000000] +/PieceInfo << +/AdobePhotoshop << +/LastModified (D:20030406201235-05'00') +/Private << +/RoundTrip 1 +/ExportCrispy false +/SaveTransparency false +/ImageResources 1325 0 R +/XObject << +/Im0 1326 0 R +>> +/StandardImageFileData 1327 0 R +>> +>> +>> +/Resources << +/XObject << +/Im0 1326 0 R +>>/ProcSet [ /PDF /ImageC ] +>> +/Length 1328 0 R +>> +stream +q q 15 0 0 15 0 0 cm /Im0 Do Q Q endstream +endobj +1324 0 obj +<< +/Creator (Adobe Photoshop 7.0) +/CreationDate (D:20030406201235-05'00') +/ModDate (D:20030406201235-05'00') +/Producer (Adobe Photoshop for Windows) +>> +endobj +1325 0 obj +<< +/Filter /FlateDecode +/Size 2672 +/Length 1329 0 R +>> +stream +HVkPW͛$u@NEvD@*y,YH6h#jLTev⣎j[vLNT/*ۻw7/itz2ssM|rz&*`<#Їws*2>~)<,|8&!{![,)g +#elGf@B.E̍h]=/@*]ЙsfMrW'0fϊ?$X 5ՠDނ \. "d[dbHHڊEV`j#Kf" r"V¦bn1K`a<+q͢K}S[|_$n&|BfLa$`J23 $iab,)$mk,EfWưOsLuMDaRF} Bڼd Y%YA I-ϡ2I>pt˔HŸc{10: 9 + +02}17}.xUi tY4)Gi= +ʁL,K2D)dcT@*H)C- &+ +ZPIfSfq,< Y +0$\qx8@(K~سN p`| yP,eЩ!QzUhPu7/O :emlHMʾѮŷ٦3b5+qon'>8om(tӧj=7oyUEs,3´O &+ DW&^La;p<VAi//HNI D&Di4{x}{p]!s܄$oq{`a<.Il-dendstream +endobj +1326 0 obj +<< +/Type /XObject +/Subtype /Image +/Interpolate false +/Filter /FlateDecode +/DecodeParms << +/Predictor 2 +/Colors 3 +/BitsPerComponent 8 +/Columns 20 +>> +/Width 20 +/Height 20 +/BitsPerComponent 8 +/ColorSpace /DeviceRGB +/Length 1330 0 R +>> +stream +HEPƯDABDPx/r xV+?a`/?, {`- endstream +endobj +1327 0 obj +<< +/Length 1331 0 R +>> +stream +endstream +endobj +1328 0 obj +34 +endobj +1329 0 obj +1513 +endobj +1330 0 obj +325 +endobj +1331 0 obj +0 +endobj +1306 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [108.862 593.149 187.316 601.269] +/Subtype /Link +/A << /S /GoTo /D (ttbxcustomitem) >> +>> endobj +1307 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [309.61 520.926 394.265 531.774] +/Subtype /Link +/A << /S /GoTo /D (ttbxcustomitem) >> +>> endobj +1309 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [108.862 290.161 173.825 298.38] +/Subtype /Link +/A << /S /GoTo /D (ttbxedititem) >> +>> endobj +1310 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [108.862 266.5 230.853 276.363] +/Subtype /Link +/A << /S /GoTo /D (ttbxcustomdropdownitem) >> +>> endobj +1311 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [295.082 196.02 393.269 206.869] +/Subtype /Link +/A << /S /GoTo /D (ttbxdropdownitem) >> +>> endobj +1312 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [413.969 196.02 488.274 206.869] +/Subtype /Link +/A << /S /GoTo /D (ttbxstringlist) >> +>> endobj +1313 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [388.741 150.192 439.993 161.041] +/Subtype /Link +/A << /S /GoTo /D (ttbxedititem.showimage) >> +>> endobj +1314 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [317.579 138.237 389.56 149.085] +/Subtype /Link +/A << /S /GoTo /D (ttbxcomboboxitm.showlistimages) >> +>> endobj +1315 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [127.154 80.454 222.464 91.302] +/Subtype /Link +/A << /S /GoTo /D (ttbxcomboboxitm.onadjustimagndx) >> +>> endobj +1305 0 obj << +/D [1303 0 R /XYZ 109.858 727.97 null] +>> endobj +222 0 obj << +/D [1303 0 R /XYZ 109.858 703.064 null] +>> endobj +1308 0 obj << +/D [1303 0 R /XYZ 109.858 472.049 null] +>> endobj +1291 0 obj << +/D [1303 0 R /XYZ 109.858 419.167 null] +>> endobj +226 0 obj << +/D [1303 0 R /XYZ 109.858 408.599 null] +>> endobj +1302 0 obj << +/Font << /F29 416 0 R /F28 380 0 R /F8 369 0 R /F50 672 0 R /F54 713 0 R /F22 363 0 R /F41 556 0 R >> +/XObject << /Im24 1300 0 R /Im25 1301 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +1337 0 obj << +/Length 1564 +/Filter /FlateDecode +>> +stream +xXK6W(+Rԃ)zHؠڬ`[ e^{VSp A d c#r  @Z((`k"5eDJ ?_`>6Eq,6bS#T^v{/u@(G +{7|2}Ka F~tX~}e tI~a̦<_ʆREDzx4zmwUv(e(VeB,CYZ( {]j&PizNcGrq%q#P2Kګ eX $n;a+EIMB2 UF2 $0(5?5ռ*ft& )ʅ@Y5LprC"QAwq0-ms4^47XUl-Ajks%ZZٰ&oỦWfYoTJ2nWUVcmXChR#ep6^2`0# +af, 4|[L_ hwL2WE +‰! xz+Rɻ9^oɴqE6DAR/a}ʘu}o#9 H@ϲ֦HleS-0RQ?PHPnhE ϑRD^"9/,,'S + #⽾Ͳs$%e0kkϫ՜S]7K^.~ sRinvGV["\XXXW;LY, cvOC +z۝/r <˰Š#+WCd=MzQ D΃pV'aswW6f Ar? ˵Dig5kSF) I *6L蝓cR:Q !d$ %">6qF+P:ũ^8~gG#b,{ ЃJBܡϺﰧW&Zs"rz'\ l'Z;̮f=շ5'=A5'tnH GږjمXc1ߕkf/WVr2fV-ySP"6]9N]{H{ pe>"%u9}Nv%#1lMSٚ'*ߋPB#ŞtU’y}";eҖ|jcXD+RT;{iCQZ/u qkg+A*O^ 3X8s-t ӜSP*Աim* +8m_B %)EGrM)hd=-YVOQƵPK|h(l 聠uOiܷ |0)8[\ @rH^$v44^͓o0j^1endstream +endobj +1336 0 obj << +/Type /Page +/Contents 1337 0 R +/Resources 1335 0 R +/MediaBox [0 0 612 792] +/Parent 1263 0 R +/Annots [ 1342 0 R 1345 0 R 1346 0 R ] +>> endobj +1342 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [145.199 444.029 200.028 451.556] +/Subtype /Link +/A << /S /GoTo /D (ttbxcomboboxitm.minlistwidth) >> +>> endobj +1345 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [145.199 287.974 201.674 295.501] +/Subtype /Link +/A << /S /GoTo /D (ttbxcomboboxitm.maxlistwidth) >> +>> endobj +1346 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [480.302 222.339 535.484 233.187] +/Subtype /Link +/A << /S /GoTo /D (ttbxcustomlist.showimages) >> +>> endobj +1338 0 obj << +/D [1336 0 R /XYZ 109.858 727.97 null] +>> endobj +1339 0 obj << +/D [1336 0 R /XYZ 109.858 653.011 null] +>> endobj +1340 0 obj << +/D [1336 0 R /XYZ 109.858 587.188 null] +>> endobj +1341 0 obj << +/D [1336 0 R /XYZ 109.858 523.606 null] +>> endobj +1343 0 obj << +/D [1336 0 R /XYZ 109.858 445.025 null] +>> endobj +1344 0 obj << +/D [1336 0 R /XYZ 109.858 369.488 null] +>> endobj +1333 0 obj << +/D [1336 0 R /XYZ 109.858 288.97 null] +>> endobj +1347 0 obj << +/D [1336 0 R /XYZ 109.858 223.335 null] +>> endobj +1335 0 obj << +/Font << /F29 416 0 R /F8 369 0 R /F28 380 0 R /F54 713 0 R /F22 363 0 R /F41 556 0 R /F55 716 0 R /F34 719 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +1351 0 obj << +/Length 2535 +/Filter /FlateDecode +>> +stream +xYs6_#g*_v;ms7 D*$o@Rzc$yJlw[ +rҘ 04HE7J,ҳA-4"; (䡈e]]sXvu^˛238<{{WƟC5[\ֻ}]٪-+f`)P\a9r=W^ J+7J_y(|j @h[NP +_RD+H{}v.Auݰ-C"Ԕ.~mPŸua:y:ONM{3!Tp_wv%uKVxPf >XOJZb*lq&Ǯf̓R4|)ΏS7;a͉ + c)Ԥp4_(lC/m/rW&X(*diOiS8`ķNϹRw"͸Y>Np#)H*[S] gb`G[Q ~Y7C9Ki@WOwVsQp2$@;H|5!@4T 0=a>@I)~Dx;^F1pJfڋ'[PypgoYP{endstream +endobj +1350 0 obj << +/Type /Page +/Contents 1351 0 R +/Resources 1349 0 R +/MediaBox [0 0 612 792] +/Parent 1263 0 R +/Annots [ 1354 0 R ] +>> endobj +1354 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [145.199 446.749 173.121 455.826] +/Subtype /Link +/A << /S /GoTo /D (ttbxcomboboxitm.strings) >> +>> endobj +1352 0 obj << +/D [1350 0 R /XYZ 109.858 727.97 null] +>> endobj +1353 0 obj << +/D [1350 0 R /XYZ 109.858 681.914 null] +>> endobj +1334 0 obj << +/D [1350 0 R /XYZ 109.858 589.893 null] +>> endobj +1355 0 obj << +/D [1350 0 R /XYZ 109.858 447.746 null] +>> endobj +1356 0 obj << +/D [1350 0 R /XYZ 109.858 311.93 null] +>> endobj +1357 0 obj << +/D [1350 0 R /XYZ 109.858 147.61 null] +>> endobj +1349 0 obj << +/Font << /F29 416 0 R /F28 380 0 R /F22 363 0 R /F41 556 0 R /F8 369 0 R /F54 713 0 R /F55 716 0 R /F34 719 0 R /F19 516 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +1360 0 obj << +/Length 1722 +/Filter /FlateDecode +>> +stream +xڭXYs6~ׯ#9SE&&43Ih HJq_])Jv2p, (4YAԑb*ZgYt;?ϨH9%Z e@ʿg?fD{g"Zτ,SW{.nOE=B * +|>'VDv><'/ouDlS/LqrsquaPtb(cy2?sw_Y 1ٖ-cYiR9 ld0)OiHhL))`댩ЌZikT|U-*ON9W.9) Ʃ""cjU&<^NKs9r#m~ةFJ{@,lM^-h "ԟ~HR.D̺ê͵7e V*0K875HM'쭩h?b0H=k$$g CoekU<NPfq/3ҖtAF^֝1 hK'sIXls:GwKuYtB|$)_gT + +bqZm+;,V="|ukukOG \V'<nz["?>dՖw5UN`VW!2(ޭT×;!LjtCCZ56ȩg0kQ_cVK]]j"}bc(H Y] 6\2~€9&B@G ̒C lOq +z3Cj<sKd08R- 10JDX_Tn!) ڸ4/M\-EPJoab @Mx@~"kPe'tD4MJ +d +zU!Հ#g;,~=}]+obfZL+G_vXT{U}KX=1rQјC5 !ה³mikpޒ@Gr|U|sb޵y $98q*} #7Uz`sU#vq4,ˠ+}த*Ӕ֎Eb{+)#ws+AKQp9Զ,Z4{hΓ\)Mߌ޷b54,yK0S10,1 $F +szz9Rm5ќba<~dHh_ɓ*q?44@O9JIh +J< .Ф} uZM%0}n+O7‹Qo Dvendstream +endobj +1359 0 obj << +/Type /Page +/Contents 1360 0 R +/Resources 1358 0 R +/MediaBox [0 0 612 792] +/Parent 1263 0 R +/Annots [ 1364 0 R 1365 0 R 1366 0 R 1367 0 R ] +>> endobj +1364 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [108.862 324.382 173.825 332.601] +/Subtype /Link +/A << /S /GoTo /D (ttbxedititem) >> +>> endobj +1365 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [361.234 250.181 459.422 261.029] +/Subtype /Link +/A << /S /GoTo /D (ttbxdropdownitem) >> +>> endobj +1366 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [481.99 250.181 538.252 261.029] +/Subtype /Link +/A << /S /GoTo /D (ttbxdropdownitem) >> +>> endobj +1367 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [108.862 240.163 156.101 249.074] +/Subtype /Link +/A << /S /GoTo /D (ttbxdropdownitem) >> +>> endobj +1361 0 obj << +/D [1359 0 R /XYZ 109.858 727.97 null] +>> endobj +1362 0 obj << +/D [1359 0 R /XYZ 109.858 654.974 null] +>> endobj +1363 0 obj << +/D [1359 0 R /XYZ 109.858 560.393 null] +>> endobj +1292 0 obj << +/D [1359 0 R /XYZ 109.858 455.793 null] +>> endobj +230 0 obj << +/D [1359 0 R /XYZ 109.858 445.069 null] +>> endobj +1293 0 obj << +/D [1359 0 R /XYZ 109.858 241.159 null] +>> endobj +1358 0 obj << +/Font << /F29 416 0 R /F54 713 0 R /F22 363 0 R /F41 556 0 R /F8 369 0 R /F28 380 0 R /F50 672 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +1370 0 obj << +/Length 1586 +/Filter /FlateDecode +>> +stream +xڝXKs6WHΔ($Nqj$F-NLR%8ŃHYM</~4(cJG9IGzE;XeżD*Fr?|sQI w`7В`L ET*ϵ߯nVVZ)q[֫_"m%z.~cn.cәfcV" 'K "bs%^s%):7Z_2L'd_5IehK.7Ql9J]8,"DlD1f/އ +~rV#ytN}0 ٨%kCk*hJO_ o ~+.r; vN ĝ?U˲ٺhNTTr5TlAhid0׵'.<ݢeD DI7WL 29Y; Ňe('P[/ri`ȦNvpQ0ˏ!$̸ Tbh}ECXt3NwrxZ{Cڈ&G*QЏ@uZ1iiU!TLo(YL'ͭϋݏ+Ȝ4["˞9=X#X[ƃW,=O8o&K]K!.Eendstream +endobj +1369 0 obj << +/Type /Page +/Contents 1370 0 R +/Resources 1368 0 R +/MediaBox [0 0 612 792] +/Parent 1382 0 R +/Annots [ 1372 0 R 1373 0 R 1374 0 R 1375 0 R 1377 0 R 1378 0 R ] +>> endobj +1372 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [108.862 592.737 173.825 600.956] +/Subtype /Link +/A << /S /GoTo /D (ttbxedititem) >> +>> endobj +1373 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [356.152 518.536 445.595 529.384] +/Subtype /Link +/A << /S /GoTo /D (ttbxspinedititem) >> +>> endobj +1374 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [469.565 518.536 538.252 529.384] +/Subtype /Link +/A << /S /GoTo /D (ttbxspinedititem) >> +>> endobj +1375 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [108.862 508.518 134.931 517.429] +/Subtype /Link +/A << /S /GoTo /D (ttbxspinedititem) >> +>> endobj +1377 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [367.039 414.676 393.385 425.524] +/Subtype /Link +/A << /S /GoTo /D (ttbxcstmspndttm.value) >> +>> endobj +1378 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [267.889 402.721 316.65 413.569] +/Subtype /Link +/A << /S /GoTo /D (ttbxcstmspndttm.valuetype) >> +>> endobj +1371 0 obj << +/D [1369 0 R /XYZ 109.858 727.97 null] +>> endobj +234 0 obj << +/D [1369 0 R /XYZ 109.858 703.064 null] +>> endobj +1376 0 obj << +/D [1369 0 R /XYZ 109.858 469.424 null] +>> endobj +1379 0 obj << +/D [1369 0 R /XYZ 109.858 391.762 null] +>> endobj +1380 0 obj << +/D [1369 0 R /XYZ 109.858 318.716 null] +>> endobj +1381 0 obj << +/D [1369 0 R /XYZ 109.858 243.179 null] +>> endobj +1368 0 obj << +/Font << /F29 416 0 R /F28 380 0 R /F8 369 0 R /F50 672 0 R /F22 363 0 R /F41 556 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +1387 0 obj << +/Length 2731 +/Filter /FlateDecode +>> +stream +xڵko`m{bD^{\nHRX+BJ}g8DIWyqC//xbXXݝ%wqYo?"!8dj?4 iwgR&t7gQ=HM)x~<0 |yprKsy2*e*]xK< STV22">UKwy~l˻fyvEXR93Y$7,x#%T3ԜĜ3;Nft̤'rxReQjg,O"!lb3߁ ~)h+$jI=wXdJ ++Noq*e-u a zM3v1e |nJ@K%Q%RZȽlF-tM,ccETLiKOgw{8@j 1S$M䊁  KmoeђVEM^eo!PWkgd`gӘk8dƤ\*eX4[BKe +nwv2cdL&,1VqjSX`xe =\0='VI86>5a~j>;tF~ bd%I%EALq: !P5f3r=ԥoy,wAi+h T{&*GN)M`&JK2 +8j_D|To]/s9CئẄ́KGJik0#*{pG$l_mWG%xu}j"\&:V`,^;8sžq/[. &ÐB{ej\^ ܴz$) (fA^ Gڻ,V`B.c~% H'JMmYkz-]>9qhmξ!gnЋ +/~ˇd0"gƅN;b|lhiFh 7`Ճ4o8YT>Tk:2U]w)CM}1晏R!,dOEW:?w7*V[}߭syʜa^Ϗ)#3Q^[Bc;]F`EHUzr 7kb^o[ZTS^ EW9- +ȑzN }T9# j|9r> o;W(/ԫ*izzeU)lӚJ0RP茙8ׯQÜaDݚngUz[ʋetzV3fN1Y2-^9/MYc; ϣMV +:_؜yU| 鯜GZ+R8ӭLg}'JBV +K$0WoPz0ȏ75p*()Ns1u<7O;Α8E,Iҁ8{o3XBUOE:`Cm~Z䕟xm< &3؅1L5}Fz WNʅ&%L$8ZR݃~a~a8?ug5gLxc|֧w*|e +kEܩ|h#-7ݥ[]p2=yl H+ 18Nj_ޅ+\Yy9c:Ȝ:?4&p~}U갷ɱ2e:1KZy;Z~*/7Pפ+gLb20uRGԟ +TKa|nw0|u O+;n +&TcΉ5,Ǖp^N<,sЉ:w\'r}&zi'At/d ŗnhX=+L#:g9 fC%t}sw`:K3=aԣԟdE(ē_S\ bGu@)+^eeYsQmj]W&МɁ}`hOu4B$"d].XصP:8@xDIB,8H3j8j}9xtζ?~]' ~씪U +=Q55p.endstream +endobj +1386 0 obj << +/Type /Page +/Contents 1387 0 R +/Resources 1385 0 R +/MediaBox [0 0 612 792] +/Parent 1382 0 R +/Annots [ 1389 0 R 1390 0 R 1392 0 R 1393 0 R 1395 0 R 1396 0 R 1397 0 R 1399 0 R 1400 0 R 1402 0 R 1403 0 R 1404 0 R 1405 0 R 1406 0 R 1407 0 R 1408 0 R ] +>> endobj +1389 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [260.377 654.094 286.723 664.942] +/Subtype /Link +/A << /S /GoTo /D (ttbxcstmspndttm.value) >> +>> endobj +1390 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [145.199 639.094 182.695 646.622] +/Subtype /Link +/A << /S /GoTo /D (ttbxcstmspndttm.minvalue) >> +>> endobj +1392 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [264.556 575.512 290.902 584.424] +/Subtype /Link +/A << /S /GoTo /D (ttbxcstmspndttm.value) >> +>> endobj +1393 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [145.199 558.576 184.342 566.103] +/Subtype /Link +/A << /S /GoTo /D (ttbxcstmspndttm.maxvalue) >> +>> endobj +1395 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [145.199 406.706 186.938 415.783] +/Subtype /Link +/A << /S /GoTo /D (ttbxcstmspndttm.valuetype) >> +>> endobj +1396 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [190.12 406.706 262.493 415.783] +/Subtype /Link +/A << /S /GoTo /D (ttbxcstmspndttm.spacebeforpstfx) >> +>> endobj +1397 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [265.676 406.706 289.665 415.783] +/Subtype /Link +/A << /S /GoTo /D (ttbxcstmspndttm.prefix) >> +>> endobj +1399 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [395.925 313.781 427.999 324.629] +/Subtype /Link +/A << /S /GoTo /D (ttbxcstmspndttm.postfix) >> +>> endobj +1400 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [145.199 297.232 209.647 306.309] +/Subtype /Link +/A << /S /GoTo /D (ttbxcstmspndttm.spaceafterprefx) >> +>> endobj +1402 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [146.498 221.192 172.844 232.04] +/Subtype /Link +/A << /S /GoTo /D (ttbxcstmspndttm.value) >> +>> endobj +1403 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [484.205 221.192 529.95 232.04] +/Subtype /Link +/A << /S /GoTo /D (ttbxcstmspndttm.increment) >> +>> endobj +1404 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [349.403 204.256 375.749 215.104] +/Subtype /Link +/A << /S /GoTo /D (ttbxcstmspndttm.value) >> +>> endobj +1405 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [430.169 204.256 475.914 215.104] +/Subtype /Link +/A << /S /GoTo /D (ttbxcstmspndttm.increment) >> +>> endobj +1406 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [371.108 192.3 397.454 203.149] +/Subtype /Link +/A << /S /GoTo /D (ttbxcstmspndttm.value) >> +>> endobj +1407 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [129.712 180.345 156.058 191.193] +/Subtype /Link +/A << /S /GoTo /D (ttbxcstmspndttm.value) >> +>> endobj +1408 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [108.862 168.39 135.207 179.238] +/Subtype /Link +/A << /S /GoTo /D (ttbxcstmspndttm.value) >> +>> endobj +1388 0 obj << +/D [1386 0 R /XYZ 109.858 727.97 null] +>> endobj +1391 0 obj << +/D [1386 0 R /XYZ 109.858 640.091 null] +>> endobj +1394 0 obj << +/D [1386 0 R /XYZ 109.858 559.572 null] +>> endobj +1398 0 obj << +/D [1386 0 R /XYZ 109.858 407.702 null] +>> endobj +1401 0 obj << +/D [1386 0 R /XYZ 109.858 298.228 null] +>> endobj +1409 0 obj << +/D [1386 0 R /XYZ 109.858 169.386 null] +>> endobj +1385 0 obj << +/Font << /F29 416 0 R /F22 363 0 R /F41 556 0 R /F8 369 0 R /F55 716 0 R /F34 719 0 R /F19 516 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +1413 0 obj << +/Length 2257 +/Filter /FlateDecode +>> +stream +xڥZmo6_N<"E2E?i:@\+=IN7^v$zÙ<á6t&Jdh_D[::D)1" + cVkF҈şEH{Vp MTpqsVV 8äe)\'Wy_9lv}xUY¿6/mZ4\,! JRO%1{csduHi@iQ$AYj3QO-$L%=dbJg3JcB#jmvoC}"8M*x;a= %uoIcN>T>>mNm 4JIYk)6оG%3e,+v0\8v"0bqګ$\ ,*>'i*aYzC!J{bw3׽f=ݧф_H79EIquE'rl{5QʔYlPYzK7] &-;_\njtO9v1Pcm1x MZxoi16!yhklnލ\3m<42V>PJI"tR6r}s(ÓnJX+<|gO2m~1GM'z$gCGqb,ضfm3Ԍc[UMM6`gBzgz#+0ԾAB%k8̙֎k2#m5yÞjGvDn\sU͓AR}[F$s%C)ӅN2A|nl&6TI;ĩ^$I Mw5k]=q05U640ya۔ըAq-]Z\3Z`Ʉ;_ߖDzȊf8ir▽v)dm{q]ZWa)1bsCݔe>`BqrNr;h2*nuuh'mtMFWiDʗCkvr2ȽEΕb9=9McGʑB/)D+8ȉLb^5}5SVXv,jW1 +O13u`A[y&Xh>Xl~KN, +Vf1."qY.c+bA +zE, <S '7VYK5Ar=F*V>(t>(pde3L0e^© #=?@!}b! +&M9[RS%#A|^h>l$:HT`z6 /{tY}cv =yLX-[endstream +endobj +1412 0 obj << +/Type /Page +/Contents 1413 0 R +/Resources 1411 0 R +/MediaBox [0 0 612 792] +/Parent 1382 0 R +/Annots [ 1415 0 R 1416 0 R 1417 0 R 1418 0 R 1419 0 R 1420 0 R 1421 0 R 1422 0 R 1424 0 R 1425 0 R 1426 0 R 1427 0 R ] +>> endobj +1415 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [108.862 643.96 136.757 652.871] +/Subtype /Link +/A << /S /GoTo /D (ttbxcstmspndttm.prefix) >> +>> endobj +1416 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [149.57 568.307 181.645 577.218] +/Subtype /Link +/A << /S /GoTo /D (ttbxcstmspndttm.postfix) >> +>> endobj +1417 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [138.551 485.852 187.312 496.7] +/Subtype /Link +/A << /S /GoTo /D (ttbxcstmspndttm.valuetype) >> +>> endobj +1418 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [108.862 461.942 152.725 472.679] +/Subtype /Link +/A << /S /GoTo /D (ttbxcstmspndttm.asinteger) >> +>> endobj +1419 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [145.199 445.393 182.695 454.47] +/Subtype /Link +/A << /S /GoTo /D (ttbxcstmspndttm.minvalue) >> +>> endobj +1420 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [185.878 445.393 225.021 454.47] +/Subtype /Link +/A << /S /GoTo /D (ttbxcstmspndttm.maxvalue) >> +>> endobj +1421 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [145.199 355.294 167.884 364.371] +/Subtype /Link +/A << /S /GoTo /D (ttbxcstmspndttm.value) >> +>> endobj +1422 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [171.067 355.294 208.617 364.371] +/Subtype /Link +/A << /S /GoTo /D (ttbxcstmspndttm.asinteger) >> +>> endobj +1424 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [133.768 221.043 181.146 231.891] +/Subtype /Link +/A << /S /GoTo /D (ttbxedititem.alignment) >> +>> endobj +1425 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [133.768 201.118 171.045 211.966] +/Subtype /Link +/A << /S /GoTo /D (ttbxcstmspndttm.decimal) >> +>> endobj +1426 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [133.768 181.193 179.514 191.93] +/Subtype /Link +/A << /S /GoTo /D (ttbxcstmspndttm.increment) >> +>> endobj +1427 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [133.768 161.267 157.347 172.005] +/Subtype /Link +/A << /S /GoTo /D (ttbxcstmspndttm.snap) >> +>> endobj +1414 0 obj << +/D [1412 0 R /XYZ 109.858 727.97 null] +>> endobj +1410 0 obj << +/D [1412 0 R /XYZ 109.858 644.956 null] +>> endobj +1383 0 obj << +/D [1412 0 R /XYZ 109.858 569.304 null] +>> endobj +1384 0 obj << +/D [1412 0 R /XYZ 109.858 446.389 null] +>> endobj +1423 0 obj << +/D [1412 0 R /XYZ 109.858 317.75 null] +>> endobj +1411 0 obj << +/Font << /F29 416 0 R /F22 363 0 R /F41 556 0 R /F8 369 0 R /F19 516 0 R /F55 716 0 R /F34 719 0 R /F28 380 0 R /F14 372 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +1431 0 obj << +/Length 2528 +/Filter /FlateDecode +>> +stream +xZ~l;`AӴ99(,XHJQߙ}PHtRPlB0jDsM,Wtr#bb*1nqhpӞNXc?WJ'K=̒L>=%\Jfpm-?'-@ 2pm{3<@0[ߦ\&yҌm0M@Y#m2/~6fS9PEUmeDGJKPJxN3t۸jeq򶩋n'L@3Q8|y^XLD⹽^Tg3_hp S@dmoMUy K~e|[|1㘉NqN 8a>l)Krp6Ŷ(10x|5O[OAaߑn[|JSy }r>xu@X|LD^"j8D65 \0mZUnpt}7R~[x]1Az[TAOQi(Qn4\ERumioxR t;_Pk~&war$y$w)@R%kh@9ȸ4I2i@ˬ~ (aU싁d>FrTwO,4*v343hRUzf+ѧ y<_.V"(ɷ2av\U"d ݲX +8c=lVŢhVDјb%*n҄%w겛#jNh}>v? lyb3P@,ݒňwLھ%T ,#R㦶~d?az3Yʰwa9P.3I4䋢|145Tc<0A0_qLO{bݰKn~1FgNцct$'>Ā!-f~ 8 ukZd`\|{pw9B /50T.Rf#v,qP4eFЋi-B9OJ>|QUܷWvp9ljH؁bcU$2 1z _og_">/i@qgn?Ct:=GHC4O}yy/#JJ|;`_F*t<߶{~56JF&^l b$O?bTz~RзM RXe ]8\.VZB)qj2{C胃jb1{)p_L;+`KSP>N;hWCDX,@]cH$TƟ8\~endstream +endobj +1430 0 obj << +/Type /Page +/Contents 1431 0 R +/Resources 1429 0 R +/MediaBox [0 0 612 792] +/Parent 1382 0 R +/Annots [ 1441 0 R ] +>> endobj +1441 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [145.199 82.391 205.756 89.918] +/Subtype /Link +/A << /S /GoTo /D (ttbxcstmspndttm.onvaluetotext) >> +>> endobj +1432 0 obj << +/D [1430 0 R /XYZ 109.858 727.97 null] +>> endobj +1433 0 obj << +/D [1430 0 R /XYZ 109.858 682.147 null] +>> endobj +1439 0 obj << +/D [1430 0 R /XYZ 109.858 419.134 null] +>> endobj +1440 0 obj << +/D [1430 0 R /XYZ 109.858 327.195 null] +>> endobj +1442 0 obj << +/D [1430 0 R /XYZ 109.858 83.387 null] +>> endobj +1429 0 obj << +/Font << /F29 416 0 R /F28 380 0 R /F54 713 0 R /F22 363 0 R /F41 556 0 R /F8 369 0 R /F47 1436 0 R /F58 1438 0 R /F19 516 0 R /F55 716 0 R /F34 719 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +1448 0 obj << +/Length 2138 +/Filter /FlateDecode +>> +stream +xY[o~# ۽s<4O @YblX*Q_ߙ]"e%nx|3È"dθ+d-B\ \;V_J䒕D?/~'k#ҥK3dsMd=HzV3"gh޾W+˄@_iUjsTqaPt{aXR,ҥ6u]=vojτHvG}cK)A61fQƜ8XV›3-\P[6W,˵eb(NmwQiUg9%[s|D G.'IPDV;7O')2-o\i.LjoCyL[C캧m5(< +3= gƾe8ZUn.A9DL߹UF(F ^]պ%*-U컙8.Aߡz'it31־7VsQJ1)D ںLT>05 <&4i\){ծZZuPͰBPX } +3 Y|tzdΔ;Z6s +\ 8 Xi!Er,2Yw GOE@93M!dE +'\AτY8 $Nʠ\Β} ́fFy\K{\" 0!>DY,Ds`E#:&Cľ\mɄY <>Zu'"ꆄu:dMKGJM   v_Up)~[\:X5ݲ[ @щIkaV&?Z&2c91X}n ؉:ѓmM8àGx]bU8ItO8Xw}\<ٷC +/c +~3Ci@wQZY d`Ɠ(ys${=,/}>vp `zl\XY'$3u5v{.,}3{}w 10oV2%31Rl77XMECL7tIxjΏ=l_[`wx)'5 x&3HɃl.[aY|lثvPpC]UFIC6|6p{bxuCqw™aj,|Z洯*trl"_1={*#}O<#6 ' [!La}B_9Aϗc*F2|n6Uﴁg}`E.01%ozr_mF)UӛVyL]@0Asv-9S"uxO;lDB5%1GG13b3Ni+X@>9P@Eq +:Ly"#YsAa_g~JڶׇUy[RB5Ճ:K?Bhى8.^[N ; }=4y T>zՅP=3 )`^0ܒD~r4J_t˿#endstream +endobj +1447 0 obj << +/Type /Page +/Contents 1448 0 R +/Resources 1446 0 R +/MediaBox [0 0 612 792] +/Parent 1382 0 R +/Annots [ 1450 0 R 1451 0 R 1452 0 R 1453 0 R 1454 0 R 1455 0 R 1456 0 R 1457 0 R 1458 0 R 1459 0 R ] +>> endobj +1444 0 obj << +/Type /XObject +/Subtype /Form +/FormType 1 +/PTEX.FileName (c_ttbxdropdownitem.pdf) +/PTEX.PageNumber 1 +/PTEX.InfoDict 1460 0 R +/Matrix [1.00000000 0.00000000 0.00000000 1.00000000 0.00000000 0.00000000] +/BBox [0.00000000 0.00000000 15.00000000 15.00000000] +/PieceInfo << +/AdobePhotoshop << +/LastModified (D:20030406201239-05'00') +/Private << +/RoundTrip 1 +/ExportCrispy false +/SaveTransparency false +/ImageResources 1461 0 R +/XObject << +/Im0 1462 0 R +>> +/StandardImageFileData 1463 0 R +>> +>> +>> +/Resources << +/XObject << +/Im0 1462 0 R +>>/ProcSet [ /PDF /ImageC ] +>> +/Length 1464 0 R +>> +stream +q q 15 0 0 15 0 0 cm /Im0 Do Q Q endstream +endobj +1460 0 obj +<< +/Creator (Adobe Photoshop 7.0) +/CreationDate (D:20030406201239-05'00') +/ModDate (D:20030406201239-05'00') +/Producer (Adobe Photoshop for Windows) +>> +endobj +1461 0 obj +<< +/Filter /FlateDecode +/Size 2660 +/Length 1465 0 R +>> +stream +HVyPg !}0BqRFo͚mi gagE)m[l)3+> s5Q% ùWR6f|7o06j> %chI[UN -TiTgp>oo '7TrP]\ |^Oק!"PD]&@f*i5kA)rBTCQMF3J",  +R*JM*-7 /A-GђD8&k"HB,%$:X"~FD EbD&KHe,2IqXp$yn&bN~0 !9isy=q#vz7r\SډFfy7~foz;ov9}%?uϷ3 +K?} !bI&a +a1bĠ"\#ѭr ZsN0\Uզ 1ڧݍrdq'##MiyꆇDy)AIg! nO}S~ck6umYa˵^k>UrAP͂Klmiݷ;ыU{}ƞ=;4I(7?8O +Wm;rc}=o64EߚKǪD=xhaDya䍓3ޛYۘB΅+o:1h]]K]u3vvD}97/vt ABusѣ%G6ߏ}9q>س}㖇']d!$^+pf~+]yZ꪿xBU[Yvu[LKK`Qd4`(́Rgа]9G(?p#ʂI\.H@ X~!^D ~YrF> +/Width 20 +/Height 20 +/BitsPerComponent 8 +/ColorSpace /DeviceRGB +/Length 1466 0 R +>> +stream +H??"prrrpp|Ϟ=2+%%%))իk׮988hiim<{/.322IE6olll M1{A zqB^ 6Phb#b M/1iP `$0QR^.p+yh[z'NTSSSVVgyhׯo޼y(b}(0| A<<< }@ِ @6@BS endstream +endobj +1463 0 obj +<< +/Length 1467 0 R +>> +stream +endstream +endobj +1464 0 obj +34 +endobj +1465 0 obj +1504 +endobj +1466 0 obj +296 +endobj +1467 0 obj +0 +endobj +1445 0 obj << +/Type /XObject +/Subtype /Form +/FormType 1 +/PTEX.FileName (c_ttbxedititem.pdf) +/PTEX.PageNumber 1 +/PTEX.InfoDict 1468 0 R +/Matrix [1.00000000 0.00000000 0.00000000 1.00000000 0.00000000 0.00000000] +/BBox [0.00000000 0.00000000 15.00000000 15.00000000] +/PieceInfo << +/AdobePhotoshop << +/LastModified (D:20030406201241-05'00') +/Private << +/RoundTrip 1 +/ExportCrispy false +/SaveTransparency false +/ImageResources 1469 0 R +/XObject << +/Im0 1470 0 R +>> +/StandardImageFileData 1471 0 R +>> +>> +>> +/Resources << +/XObject << +/Im0 1470 0 R +>>/ProcSet [ /PDF /ImageC ] +>> +/Length 1472 0 R +>> +stream +q q 15 0 0 15 0 0 cm /Im0 Do Q Q endstream +endobj +1468 0 obj +<< +/Creator (Adobe Photoshop 7.0) +/CreationDate (D:20030406201241-05'00') +/ModDate (D:20030406201241-05'00') +/Producer (Adobe Photoshop for Windows) +>> +endobj +1469 0 obj +<< +/Filter /FlateDecode +/Size 2628 +/Length 1473 0 R +>> +stream +HV{PTU}²<uY@!@[l(/lXΕwI%gԑ2B)iL{;JYj #|۹ehv9w1SG3􈶪V O\y44eB4R4&b@DzGQADO/ z9B^[,4bٴMƈդy_s|=7&xo{Vj)yJmjsz@ T~XXx~P@cy:7MEC0:2o/a[(cchMSDղY FΎ.QC*"?92lCL8 +,fʭ9w}J86GUk+僊!n)(g5KY1$8bZ`OtY^eY`5f +ȫiP(ZĚ\e" мAU8laV*T|WWJViwo^u{ŖЌsTqB@NxWY5pA4*ZaQAWl.-f  'qBS"L,d Ho @pg_!|S>Bt=ζ2* O` 8 +@T*UJJk#BЈ :]N7A$.c hFO7 @DѓDH%hB(e&$ڜT&W(UAF$ %RL!WHu22jIilx,{N.nr\nG9&G$8*[KQJy ^-uu3/?Ok?O|W>^}} +_S +^lgߜxK  B+ŘrY*.Ed<}%Ǯ'Os6FԸRnyԮDxk^ :p~\IL-dw\.k277s0/⺵Wv}enQkyIs{5+gzv '9Soo=~hGڮ-/*q MOW nT~x(㙩'vOQmH~ͩoߊ}Llj~Ʈ5 mcӆrtՊ +=s} 4?d?tWԠ([Mݓeh8m}>{oXG]Kߡ6F80T}4Rvf vtD"RS^֤z?+rN4G~n|pNiɑ'YZpZQlt1ڣ f,.#?x@L9l +"} 2X(?"H—"#ǯlq=64Q%x!fa]i `4 )1FCz1=% vBxK|yϥ Elq~Qs n/2^`D>endstream +endobj +1470 0 obj +<< +/Type /XObject +/Subtype /Image +/Interpolate false +/Filter /FlateDecode +/DecodeParms << +/Predictor 2 +/Colors 3 +/BitsPerComponent 8 +/Columns 20 +>> +/Width 20 +/Height 20 +/BitsPerComponent 8 +/ColorSpace /DeviceRGB +/Length 1474 0 R +>> +stream +H??"prrrpp|Ϟ=2+%%%))իk׮988hiim<{/gddܼy1^ $U/D^aPV^%&m +4&?JJ ^ɷn8QMMMYY{hׯo޼y(b}(0| A<<< }@ِ @6@ S endstream +endobj +1471 0 obj +<< +/Length 1475 0 R +>> +stream +endstream +endobj +1472 0 obj +34 +endobj +1473 0 obj +1465 +endobj +1474 0 obj +263 +endobj +1475 0 obj +0 +endobj +1450 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [257.029 644.513 283.374 655.362] +/Subtype /Link +/A << /S /GoTo /D (ttbxcstmspndttm.value) >> +>> endobj +1451 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [399.886 561.887 426.231 572.735] +/Subtype /Link +/A << /S /GoTo /D (ttbxcstmspndttm.value) >> +>> endobj +1452 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [145.199 534.933 205.756 542.46] +/Subtype /Link +/A << /S /GoTo /D (ttbxcstmspndttm.ontexttovalue) >> +>> endobj +1453 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [108.862 404.517 173.825 412.737] +/Subtype /Link +/A << /S /GoTo /D (ttbxedititem) >> +>> endobj +1454 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [108.862 380.856 230.853 390.719] +/Subtype /Link +/A << /S /GoTo /D (ttbxcustomdropdownitem) >> +>> endobj +1455 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [187.892 308.399 257.963 319.247] +/Subtype /Link +/A << /S /GoTo /D (ttbxedititem) >> +>> endobj +1456 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [474.684 308.399 538.252 319.247] +/Subtype /Link +/A << /S /GoTo /D (ttbxsubmenuitem) >> +>> endobj +1457 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [108.862 298.381 141.849 307.181] +/Subtype /Link +/A << /S /GoTo /D (ttbxsubmenuitem) >> +>> endobj +1458 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [423.404 250.615 538.252 261.464] +/Subtype /Link +/A << /S /GoTo /D (ttbxcustomdropdownitem) >> +>> endobj +1459 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [108.862 238.66 131.056 249.508] +/Subtype /Link +/A << /S /GoTo /D (ttbxcustomdropdownitem) >> +>> endobj +1449 0 obj << +/D [1447 0 R /XYZ 109.858 727.97 null] +>> endobj +1443 0 obj << +/D [1447 0 R /XYZ 109.858 645.51 null] +>> endobj +1294 0 obj << +/D [1447 0 R /XYZ 109.858 535.929 null] +>> endobj +238 0 obj << +/D [1447 0 R /XYZ 109.858 525.205 null] +>> endobj +1295 0 obj << +/D [1447 0 R /XYZ 109.858 239.656 null] +>> endobj +242 0 obj << +/D [1447 0 R /XYZ 109.858 228.933 null] +>> endobj +1446 0 obj << +/Font << /F29 416 0 R /F54 713 0 R /F22 363 0 R /F41 556 0 R /F8 369 0 R /F55 716 0 R /F34 719 0 R /F28 380 0 R /F50 672 0 R >> +/XObject << /Im26 1444 0 R /Im27 1445 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +1478 0 obj << +/Length 2036 +/Filter /FlateDecode +>> +stream +xڭXrF}Wm nSȻJU*^rUICӷ R.K\zfgNrBAgN O&t60%~,&)v "͏d:ȳ%w~U&Ϝ#@ݘ8tIy׸ ϥθՙBV +wvq{;_wcqˮl盻Ÿ +A.Jߺ0+ơxil~:|3t4r}ѣ>UI{6p6n'Q8~Kc+rq(D&:#T< bVeWtݥ[lyxc%6voЭz-$+yj'W0 ,Q~̆OL"Ү=?swʮ7ʹHA5mőJ+rG977Zeje'ܕk$#oaSeZ-gCӪ[4h;l a[Vզٕ|,A9I C4>Q䁱g=4 ҿ?mb1І-b9x=U镞96<o+6%ػ|xnhךB3HvX{(fG@K@Jܡ*'@X B&fU߀i uNcL v4sY&D_P7r!:ޝM hԸ*2AlphpƸ OqsҐ>Dh\8"# MB=#D&Y# ^F-zMGvpρPx fKJ.)W"؊.Kq"ƖA [8slî . -H6C9 Ûѐ6^BH|{Q8bt:Խk%b ^Xak z$*:')=U?aQdv>z0_YWfuэwv((! +1U)SwfB^rv'{d>P~tL.A;fCTzc"8ȇdjB\;Clf[ zNס~&| VXdsp)p0 r֎[!gܐ@U:I8Dx9E+dy箥aD&ZM ,Clyc;~(ʶ 'U~sFʼnTbˡek`gy,B^EXc"e+44Cfa[IlxcJA"@j9?,q>utٻjUKJ}JC.1 ??ׇ ~ɿ!endstream +endobj +1477 0 obj << +/Type /Page +/Contents 1478 0 R +/Resources 1476 0 R +/MediaBox [0 0 612 792] +/Parent 1382 0 R +/Annots [ 1481 0 R ] +>> endobj +1481 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [423.654 407.199 480.358 418.047] +/Subtype /Link +/A << /S /GoTo /D (ttbxcustomitem.fontsettings) >> +>> endobj +1479 0 obj << +/D [1477 0 R /XYZ 109.858 727.97 null] +>> endobj +1428 0 obj << +/D [1477 0 R /XYZ 109.858 535.682 null] +>> endobj +1480 0 obj << +/D [1477 0 R /XYZ 109.858 472.801 null] +>> endobj +1482 0 obj << +/D [1477 0 R /XYZ 109.858 408.195 null] +>> endobj +1483 0 obj << +/D [1477 0 R /XYZ 109.858 345.527 null] +>> endobj +1332 0 obj << +/D [1477 0 R /XYZ 109.858 270.904 null] +>> endobj +1484 0 obj << +/D [1477 0 R /XYZ 109.858 158.34 null] +>> endobj +1476 0 obj << +/Font << /F29 416 0 R /F28 380 0 R /F50 672 0 R /F8 369 0 R /F54 713 0 R /F22 363 0 R /F41 556 0 R /F19 516 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +1488 0 obj << +/Length 1623 +/Filter /FlateDecode +>> +stream +xڭX[6~ϯ=S lKt :lax&bֱ=Gĉ0YttnѲ,bTEXht +ΘG`k@I4">|]RƔpLfBzv9c'ŭND8C@{:=zud#C|NMgI>_Ϟw(ơ"S?r')*7?}vx5u0M٣>V":Qd.lg <˾qL4VD<茩kJ2iϿf  S( {\8 ؽS>9ѐiA$^U2I&,'J(hz8xl:;A QbNvc:;d]BLr`$Rs ڲ7S9D晕0m HNBABſLD0o,TPD3iF/MD!۫bZg$Q\Y Hhc;<~z*&^e6"ʵZk~A8 yT9Z`.p#@3],$' +}$e +.48Qem +C~;57(gaE Nú"6ެ*^5YHܳٱPNòOPZCj]S-d2ʓ-VW-(Yr|8@PE#m? min On _~䃄zW}Z5͉zse:SWǭ +Yv=%LX{kx +̒Be-Ȧendstream +endobj +1487 0 obj << +/Type /Page +/Contents 1488 0 R +/Resources 1486 0 R +/MediaBox [0 0 612 792] +/Parent 1496 0 R +/Annots [ 1493 0 R ] +>> endobj +1485 0 obj << +/Type /XObject +/Subtype /Form +/FormType 1 +/PTEX.FileName (c_ttbxlabelitem.pdf) +/PTEX.PageNumber 1 +/PTEX.InfoDict 1497 0 R +/Matrix [1.00000000 0.00000000 0.00000000 1.00000000 0.00000000 0.00000000] +/BBox [0.00000000 0.00000000 15.00000000 15.00000000] +/PieceInfo << +/AdobePhotoshop << +/LastModified (D:20030406201246-05'00') +/Private << +/RoundTrip 1 +/ExportCrispy false +/SaveTransparency false +/ImageResources 1498 0 R +/XObject << +/Im0 1499 0 R +>> +/StandardImageFileData 1500 0 R +>> +>> +>> +/Resources << +/XObject << +/Im0 1499 0 R +>>/ProcSet [ /PDF /ImageC ] +>> +/Length 1501 0 R +>> +stream +q q 15 0 0 15 0 0 cm /Im0 Do Q Q endstream +endobj +1497 0 obj +<< +/Creator (Adobe Photoshop 7.0) +/CreationDate (D:20030406201246-05'00') +/ModDate (D:20030406201246-05'00') +/Producer (Adobe Photoshop for Windows) +>> +endobj +1498 0 obj +<< +/Filter /FlateDecode +/Size 2582 +/Length 1502 0 R +>> +stream +HV{lSU?ϵk׵0]׭,=Yu#">ͻޭe10D1l !H0" Ad"0z/?_sw{s:-bbc4 وz@V&N6u("w%Ƣx,?)}XV %XJDq2Ǒ~̗55BY*DM5F<&ϓC`G%&gmx`>E/C9(I/ pj,DkҐGTńnEEā>;^Lz`tcE]4d .3t ceZ&Lz:Kzϑ`bbѐaR[оԹܤFUT:$G| =tC:1I9w4JOUi qi1 ӈ񧝊Ba\v"  +b^.(*A򜴝. Xe\&XTr\!W)*2JӨTq:]N7N$,V*1ju^VIC&{hh;z&Z^F[`.B)hsbT&WD)FDD"H"%*816]7ǦKjZnu.9=i=] Ki/wÛ9fwR W8lcƞ!ܳYo}ir~`~ϭYjgOt<ܶ7o<cL2$CHL#MI:q:=p{8t?Ef9@l,bȞ #H A`*?S r_JgZ}=<2zgWk& -]+ yx_cW<+]Jκ3ڼ+KXpW}nzG32县2s`ދU]o,8=t䭖=si2n^S7m @>9_6 L8qA7z_?R>|ca{̅kȩ滛r\2ߝx2R?p*9e%U=#S`-~4 :7M{侔/Z؋Sww'fZ3hx1׈/ Ky4Umuf4EZ=av-Zt`6 Y FCv1۔cY:D" }&M y$䀩P2^`:m|endstream +endobj +1499 0 obj +<< +/Type /XObject +/Subtype /Image +/Interpolate false +/Filter /FlateDecode +/DecodeParms << +/Predictor 2 +/Colors 3 +/BitsPerComponent 8 +/Columns 20 +>> +/Width 20 +/Height 20 +/BitsPerComponent 8 +/ColorSpace /DeviceRGB +/Length 1503 0 R +>> +stream +H@S)THʳ LF ViR\+DQPQBAA!B' ˒#7dowf>}>~#IRL&N#In=y>Kfe꺎|<j(FtZ,ns2T*Ru|2 4M{)bahEh Qit^IlHTQj)uJUUUU!MMِ,˂ x4M,* +r!QX,bl٠eXľ/{ͨ:aCw`n3 o!%mpdN>u;*ԃ Tzrt kg@`ٸCj2v_9.HMVF{uWu}IX9+`Yi endstream +endobj +1500 0 obj +<< +/Length 1504 0 R +>> +stream +endstream +endobj +1501 0 obj +34 +endobj +1502 0 obj +1421 +endobj +1503 0 obj +415 +endobj +1504 0 obj +0 +endobj +1493 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [253.597 259.039 310.301 269.887] +/Subtype /Link +/A << /S /GoTo /D (ttbxcustomitem.fontsettings) >> +>> endobj +1489 0 obj << +/D [1487 0 R /XYZ 109.858 727.97 null] +>> endobj +1490 0 obj << +/D [1487 0 R /XYZ 109.858 681.914 null] +>> endobj +1296 0 obj << +/D [1487 0 R /XYZ 109.858 608.564 null] +>> endobj +246 0 obj << +/D [1487 0 R /XYZ 109.858 597.84 null] +>> endobj +1491 0 obj << +/D [1487 0 R /XYZ 109.858 377.601 null] +>> endobj +1492 0 obj << +/D [1487 0 R /XYZ 109.858 323.733 null] +>> endobj +1494 0 obj << +/D [1487 0 R /XYZ 109.858 260.036 null] +>> endobj +1495 0 obj << +/D [1487 0 R /XYZ 109.858 195.9 null] +>> endobj +1486 0 obj << +/Font << /F29 416 0 R /F28 380 0 R /F54 713 0 R /F22 363 0 R /F41 556 0 R /F8 369 0 R /F50 672 0 R >> +/XObject << /Im28 1485 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +1508 0 obj << +/Length 1982 +/Filter /FlateDecode +>> +stream +xڝXYsF~ׯ@PLWlulW6rUD$o3 H1@Ÿ +,DA3QdB9(05l$n@)X"/ϋ_ +l0B"h.lR}squȅײ`d5S ~K"38cL$[n9'$y*4YNs'Av]e.վnPB#QN$Nޝ1FL;_Lf_~?E0*unLU5.a=D +Lo2&:1.^wƓd͉<)Pp#-`>eCGy!pr*B"6}n&MA(I +ʁ!0,Po<gřu?k焆5>%0Iv=dyqtw֜7R%5%$VޏLFwNHL&xL +xc]KSt1[w(w &ra^al }}*x䘢o Cx}?n]FB}c>΄j{;1*\ m҄*y *a0<̀XX$%!@I'@Fx,' /f;q!l17<0 ~ BNʬ#P>&LM)._Bxu Ƕ νH_ +GJ*R##nzݿͦ UZ E$PULi]4w`!.3lo~*a '}raa ѥå[_7D<0ОFR(arO")wd )7XJbOe3Rl끣Iq+˶Zv{Bc} D @$8b]IS\[s+|w }^&F(@F038\{$xN&}d&F 󽶁n'&SWRJgX!V"@ " j"_mנ{_uapK|&ƍ,. 3r*ꨤ2B::?NC@)p]C/zloR'{CUpS>"QL$Д`' )]Krwb 2 \Nm\ߺ('Q d aRjlI01|ސӣiIyQJOI3o"_$KV H]VWkmz~[rgeVLϵh+Ej$na%][ኜ+]䖂24:Mw-:M+4raK\Y=b8VEd<*-> endobj +1505 0 obj << +/Type /XObject +/Subtype /Form +/FormType 1 +/PTEX.FileName (c_ttbxmrulist.pdf) +/PTEX.PageNumber 1 +/PTEX.InfoDict 1516 0 R +/Matrix [1.00000000 0.00000000 0.00000000 1.00000000 0.00000000 0.00000000] +/BBox [0.00000000 0.00000000 21.00000000 21.00000000] +/PieceInfo << +/AdobePhotoshop << +/LastModified (D:20030406201256-05'00') +/Private << +/RoundTrip 1 +/ExportCrispy false +/SaveTransparency false +/ImageResources 1517 0 R +/XObject << +/Im0 1518 0 R +>> +/StandardImageFileData 1519 0 R +>> +>> +>> +/Resources << +/XObject << +/Im0 1518 0 R +>>/ProcSet [ /PDF /ImageC ] +>> +/Length 1520 0 R +>> +stream +q q 21 0 0 21 0 0 cm /Im0 Do Q Q endstream +endobj +1516 0 obj +<< +/Creator (Adobe Photoshop 7.0) +/CreationDate (D:20030406201256-05'00') +/ModDate (D:20030406201256-05'00') +/Producer (Adobe Photoshop for Windows) +>> +endobj +1517 0 obj +<< +/Filter /FlateDecode +/Size 2660 +/Length 1521 0 R +>> +stream +HV{PTUH +498LI k()v,{ݻbȰ?J*I8|D*/$2CMQKM@s|L9|;߽wJV'!lVȥyDfTG +=E>Eaw|T%N%qNM|agJF7 gf! PFgiFJOg@%\5drB.W|}|U! +HhPPHPPJ_O/@ V* BT&-dh;cDTPE0L P L|hs"D*  DP XH@FP4.0^6$(j*$xݦ''L>!ɻs8jcoP, +kV f=}'amuMF^>n Ig_[vSM*f`Ma#ipa|99nOG:?;#rk62ͻI:NV8u _\PjHSVbwATᘂYz)b΃ԙ_wK71nupsOе ԷIf) QÄG;#;-ll}[\vi_!\|gxWw ;6}xzik=ofŅ%!U{XOm&): DգZju#jyL'wzᷱ;Ϩ ABE"a6!FÎ9+HH8PO% +1:<6OhC" |OEӼ`qk˹z4Qx#rvES2IISFNHQONQ'Ej)$|T7`wFO$QnD'~DIټ׿@endstream +endobj +1518 0 obj +<< +/Type /XObject +/Subtype /Image +/Interpolate false +/Filter /FlateDecode +/DecodeParms << +/Predictor 2 +/Colors 3 +/BitsPerComponent 8 +/Columns 28 +>> +/Width 28 +/Height 28 +/BitsPerComponent 8 +/ColorSpace /DeviceRGB +/Length 1522 0 R +>> +stream +H약@-,l 0E*h"16H)ckr@BKZla{ȀHLX[ ן +&+=/`Vh4NL:;Oֿlp:OF{w;bML҅n ,L]Hu>!k6Lw:&.@mi*:,gQywppl&Qyw!` endstream +endobj +1519 0 obj +<< +/Length 1523 0 R +>> +stream +endstream +endobj +1520 0 obj +34 +endobj +1521 0 obj +1510 +endobj +1522 0 obj +379 +endobj +1523 0 obj +0 +endobj +1512 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [149.017 563.352 185.879 574.201] +/Subtype /Link +/A << /S /GoTo /D (ttbxlabelitem.caption) >> +>> endobj +1514 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [239.151 440.448 303.604 451.296] +/Subtype /Link +/A << /S /GoTo /D (ttbxcustomitem.onadjustfont) >> +>> endobj +1509 0 obj << +/D [1507 0 R /XYZ 109.858 727.97 null] +>> endobj +1510 0 obj << +/D [1507 0 R /XYZ 109.858 681.914 null] +>> endobj +1511 0 obj << +/D [1507 0 R /XYZ 109.858 629.983 null] +>> endobj +1513 0 obj << +/D [1507 0 R /XYZ 109.858 514.241 null] +>> endobj +1297 0 obj << +/D [1507 0 R /XYZ 109.858 441.444 null] +>> endobj +250 0 obj << +/D [1507 0 R /XYZ 109.858 430.72 null] +>> endobj +1515 0 obj << +/D [1507 0 R /XYZ 109.858 212.418 null] +>> endobj +1298 0 obj << +/D [1507 0 R /XYZ 109.858 134.64 null] +>> endobj +1506 0 obj << +/Font << /F29 416 0 R /F28 380 0 R /F22 363 0 R /F41 556 0 R /F8 369 0 R /F54 713 0 R /F50 672 0 R >> +/XObject << /Im29 1505 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +1528 0 obj << +/Length 1691 +/Filter /FlateDecode +>> +stream +xXY6~УT OQlrl]48h$]+%GͿ Km"Ț9" +XĨ!#51:*63=_fS<%#@w%RNLn-opJz>"ܿoQ{\yAhnPXw>b&9Lij,Gm JV Iя.x=a([]2^ǒ:K04ŒV0+aZk9 g20n]Nu7h lh~pT>f`s*aLp3V3vbf@$긒A#UNۓB8Ncq @\d!'"A2bHl_lK.䋾*F5@U1#\@G 9TBCuN5OGH!aD5A4 hV8=m:"v-?hб+@pꕄE7$Jr߉~:~tI%ltTS>pWz `w~$*P✴9=C1a0ꏮ=E &Zg4g8sYO +ʧy0 =BvaHendstream +endobj +1527 0 obj << +/Type /Page +/Contents 1528 0 R +/Resources 1526 0 R +/MediaBox [0 0 612 792] +/Parent 1496 0 R +/Annots [ 1530 0 R 1531 0 R 1532 0 R 1534 0 R 1536 0 R 1537 0 R ] +>> endobj +1524 0 obj << +/Type /XObject +/Subtype /Form +/FormType 1 +/PTEX.FileName (c_ttbxmrulistitem.pdf) +/PTEX.PageNumber 1 +/PTEX.InfoDict 1538 0 R +/Matrix [1.00000000 0.00000000 0.00000000 1.00000000 0.00000000 0.00000000] +/BBox [0.00000000 0.00000000 15.00000000 15.00000000] +/PieceInfo << +/AdobePhotoshop << +/LastModified (D:20030406201258-05'00') +/Private << +/RoundTrip 1 +/ExportCrispy false +/SaveTransparency false +/ImageResources 1539 0 R +/XObject << +/Im0 1540 0 R +>> +/StandardImageFileData 1541 0 R +>> +>> +>> +/Resources << +/XObject << +/Im0 1540 0 R +>>/ProcSet [ /PDF /ImageC ] +>> +/Length 1542 0 R +>> +stream +q q 15 0 0 15 0 0 cm /Im0 Do Q Q endstream +endobj +1538 0 obj +<< +/Creator (Adobe Photoshop 7.0) +/CreationDate (D:20030406201258-05'00') +/ModDate (D:20030406201258-05'00') +/Producer (Adobe Photoshop for Windows) +>> +endobj +1539 0 obj +<< +/Filter /FlateDecode +/Size 2638 +/Length 1543 0 R +>> +stream +HVyPW6 V[ +)SR-rUK["I YL6hՙv3R[kţnjh֫3((8h*on.i˼}}޷Mrz^< +8 $ۂ: O98T|8b4°NvaGQ<Nqٍ9[^,Vt +Q7:SzK;} fXGm?w,'jӢN+ֿ&/!wq;/_]v/[O?郾l= /v^v`;zsmS7j*O=U,<@p=]{O`g@{}K{dƶĮkIܞ.zy~3 'Y(}ԓ56;&lz'HHA8L +fpUpHBG"AF! Db{=xAAD">a'h +:qRA3}4tc@76\MIJƇqߏe6y5HZ8RIC<0o 9h'Kr 0_qendstream +endobj +1540 0 obj +<< +/Type /XObject +/Subtype /Image +/Interpolate false +/Filter /FlateDecode +/DecodeParms << +/Predictor 2 +/Colors 3 +/BitsPerComponent 8 +/Columns 20 +>> +/Width 20 +/Height 20 +/BitsPerComponent 8 +/ColorSpace /DeviceRGB +/Length 1544 0 R +>> +stream +H䓿q G`(Vuew<%$Yx7m.I"Y BoWOr%w=çy|ǣrgn^,{YR<jl6L9NC!fnDx1Zv4 U,1E(*~_xV* R`H$d8C ( +pT*VX,V՜N'{^ۅ+[.W*6,]_җ^gt>,o.FB9;;d$D"q}2Pm6b4L^y.x2NjS)l6W l6KI.Nh% Ef KI,OnZpookZe.Tdj~;|?ه!dˬ]шO%m endstream +endobj +1541 0 obj +<< +/Length 1545 0 R +>> +stream +endstream +endobj +1542 0 obj +34 +endobj +1543 0 obj +1483 +endobj +1544 0 obj +463 +endobj +1545 0 obj +0 +endobj +1525 0 obj << +/Type /XObject +/Subtype /Form +/FormType 1 +/PTEX.FileName (c_ttbxspinedititem.pdf) +/PTEX.PageNumber 1 +/PTEX.InfoDict 1546 0 R +/Matrix [1.00000000 0.00000000 0.00000000 1.00000000 0.00000000 0.00000000] +/BBox [0.00000000 0.00000000 15.00000000 15.00000000] +/PieceInfo << +/AdobePhotoshop << +/LastModified (D:20030406201311-05'00') +/Private << +/RoundTrip 1 +/ExportCrispy false +/SaveTransparency false +/ImageResources 1547 0 R +/XObject << +/Im0 1548 0 R +>> +/StandardImageFileData 1549 0 R +>> +>> +>> +/Resources << +/XObject << +/Im0 1548 0 R +>>/ProcSet [ /PDF /ImageC ] +>> +/Length 1550 0 R +>> +stream +q q 15 0 0 15 0 0 cm /Im0 Do Q Q endstream +endobj +1546 0 obj +<< +/Creator (Adobe Photoshop 7.0) +/CreationDate (D:20030406201311-05'00') +/ModDate (D:20030406201311-05'00') +/Producer (Adobe Photoshop for Windows) +>> +endobj +1547 0 obj +<< +/Filter /FlateDecode +/Size 2666 +/Length 1551 0 R +>> +stream +HV{PTU?w>eaEM&DHaTn/Sa˲vٻDŽX 1jh5jE3V&$d#&v;ܻMߝsܩza`)*. 5c`aJYUFS' Ώ|B0P4,z9KwGLXII`8)X}VAP_0{U}@b DQ[@$`Zfb*J2B&S~rUpBjxaa킎Gg \3P=Z͵Ʋ}o)ȝ␢l鯿ʀfW&=c੖\|yr|zבq+edyug6_Kd@[췾}aɝXe؁@ + +)x9 p =A4J8G`8 $"K{%CW&AX_]m:up|G/9M9JuZm\vJ6!,VK1݁qcv> +/Width 20 +/Height 20 +/BitsPerComponent 8 +/ColorSpace /DeviceRGB +/Length 1552 0 R +>> +stream +HēPE,B[Ab}m +"|B-iV2 + + +ael;si^=?0}u8;A$IEi(<*뺦ieY&I{0 mۆcǮ>n p $(Bo|<`= vv]楑}y>u:4c`ݳNb뺾Зe|viy;`Q4M?ܼneo۶44%Hen_sASra/?S endstream +endobj +1549 0 obj +<< +/Length 1553 0 R +>> +stream +endstream +endobj +1550 0 obj +34 +endobj +1551 0 obj +1507 +endobj +1552 0 obj +303 +endobj +1553 0 obj +0 +endobj +1530 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [108.862 592.837 187.316 600.956] +/Subtype /Link +/A << /S /GoTo /D (ttbxcustomitem) >> +>> endobj +1531 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [335.349 508.424 406.721 519.272] +/Subtype /Link +/A << /S /GoTo /D (ttbxmrulist) >> +>> endobj +1532 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [253.182 455.622 324.553 466.47] +/Subtype /Link +/A << /S /GoTo /D (ttbxmrulist) >> +>> endobj +1534 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [223.903 363.717 295.274 374.566] +/Subtype /Link +/A << /S /GoTo /D (ttbxmrulist) >> +>> endobj +1536 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [108.862 143.219 173.825 151.438] +/Subtype /Link +/A << /S /GoTo /D (ttbxedititem) >> +>> endobj +1537 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [108.862 119.558 222.769 129.52] +/Subtype /Link +/A << /S /GoTo /D (ttbxcustomspinedititem) >> +>> endobj +1529 0 obj << +/D [1527 0 R /XYZ 109.858 727.97 null] +>> endobj +254 0 obj << +/D [1527 0 R /XYZ 109.858 703.064 null] +>> endobj +1533 0 obj << +/D [1527 0 R /XYZ 109.858 418.466 null] +>> endobj +1535 0 obj << +/D [1527 0 R /XYZ 109.858 326.561 null] +>> endobj +1299 0 obj << +/D [1527 0 R /XYZ 109.858 274.63 null] +>> endobj +258 0 obj << +/D [1527 0 R /XYZ 109.858 263.907 null] +>> endobj +1526 0 obj << +/Font << /F29 416 0 R /F28 380 0 R /F8 369 0 R /F50 672 0 R /F54 713 0 R /F22 363 0 R /F41 556 0 R >> +/XObject << /Im30 1524 0 R /Im31 1525 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +1556 0 obj << +/Length 3107 +/Filter /FlateDecode +>> +stream +xڥZ[۶~_ +!7;ux&;I2DXK*R^o{nIQ+d;WDBOt+Yf2g&=nP,"&z@"͟{p0*9RVfŹ=B;T&g8ɕɬ|nWl旚0(>EDzry&r3 +!X ~.7s屬W7~E]]#)=Kᮿm]uZ|cwוvuERVik:Wao\& 9NL$Ʊ#plg:VQ:*iDke:Vjjfr+BE$Lh||9_ݛU _OEG/( +*nY/dAvUx\#uUW6:zuYiNaVyTjbVnGat-L#:8DǓMz♉DV9H%G;&A5fu]S;!(>xpL/0 pq}RI@M< =H]r4N$/$bUhςa".0jҌAnq+c䉻 IF p˟H Ob69J[mGzڎY:z^\; t^{Y p蘪$jhKw2gWwHߵ2^8"٭FkY05*"<2}fW L0Pl~slydp=Jc 7Q"GB=jRԍHuDCHJ^>kBʸ}!P֐8Z\Y傲H| 2> ]"֑!Nt<s> +rݩN^%Fb[;bvZG`kl&@hdO.4aٷ7z^>H? Gm樤bg:SF'T*^زi^Wm׺̸^UHQjanZbq*/(Z(0>~MKY@L¾^j< +a#{ſ<+0QYx: X!6YYgL2]-V5^8VYL [.Q/!xY[_xVYrMJz!@?g^p +<JiWeK"~m&յS+ƪY{$h'5Uc1P]W 1LV}48tj0-}ѱ`-^5"(թ>me@v`]*^1rcWQXӐ 4ɇp) T#mfZՕk|q?xPGK [{:ݓrstʽ^.tF׉*3Tԣz*w{_ۭuC˸[p&ұee77 +,ohÿ * 6F;-wEUTwXlǁS^8}gۿ}RnEʀt(HȾAnjWv'3a$| pϑ]Kb a|.2Y`R&*ȓ7EMY Q6gw3$H(b/-zOGUٻq܄]L%󨸈R/iy(/=nf`|!ǙxD HEK^]E?sR˻/Fvw %sQeN*!‹ɬc;N;ƌKiJ$i0ٸkrendstream +endobj +1555 0 obj << +/Type /Page +/Contents 1556 0 R +/Resources 1554 0 R +/MediaBox [0 0 612 792] +/Parent 1496 0 R +/Annots [ 1558 0 R 1559 0 R 1560 0 R 1561 0 R 1562 0 R 1563 0 R 1564 0 R 1566 0 R 1567 0 R ] +>> endobj +1558 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [239.447 565.844 289.343 576.692] +/Subtype /Link +/A << /S /GoTo /D (ttbxcstmspndttm.onconvert) >> +>> endobj +1559 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [137.413 536.952 208.314 547.8] +/Subtype /Link +/A << /S /GoTo /D (ttbxcstmspndttm.ontexttovalue) >> +>> endobj +1560 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [230.105 536.952 301.006 547.8] +/Subtype /Link +/A << /S /GoTo /D (ttbxcstmspndttm.onvaluetotext) >> +>> endobj +1561 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [412.501 508.06 535.484 518.909] +/Subtype /Link +/A << /S /GoTo /D (ttbxcustomspinedititem) >> +>> endobj +1562 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [133.768 403.01 209.072 412.973] +/Subtype /Link +/A << /S /GoTo /D (ttbxcustomlist) >> +>> endobj +1563 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [133.768 389.842 202.642 399.804] +/Subtype /Link +/A << /S /GoTo /D (ttbxstringlist) >> +>> endobj +1564 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [133.768 376.673 199.804 386.636] +/Subtype /Link +/A << /S /GoTo /D (ttbxundolist) >> +>> endobj +1566 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [108.862 250.395 187.316 258.514] +/Subtype /Link +/A << /S /GoTo /D (ttbxcustomitem) >> +>> endobj +1567 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [180.814 80.454 276.124 91.302] +/Subtype /Link +/A << /S /GoTo /D (ttbxcustomlist.onadjustimagndx) >> +>> endobj +1557 0 obj << +/D [1555 0 R /XYZ 109.858 727.97 null] +>> endobj +682 0 obj << +/D [1555 0 R /XYZ 109.858 497.102 null] +>> endobj +262 0 obj << +/D [1555 0 R /XYZ 109.858 482.853 null] +>> endobj +1565 0 obj << +/D [1555 0 R /XYZ 109.858 375.46 null] +>> endobj +266 0 obj << +/D [1555 0 R /XYZ 109.858 367.71 null] +>> endobj +1554 0 obj << +/Font << /F29 416 0 R /F28 380 0 R /F8 369 0 R /F50 672 0 R /F51 675 0 R /F19 516 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +1572 0 obj << +/Length 1701 +/Filter /FlateDecode +>> +stream +xڝXےF}WUf\yԺ\*%Ft P-ZtOtCQ tb$v6UÓVJ)aH boId>~ -H08ەbiފy;NH~%O;JXu}<&\UrW_ֽE99)=xOEϘtߕykVΛ(u.m#IEhHЄp&`c)ܐDŽ9.j"KP׍UϥpӢ 8.z-eB{>sMަ%w_l9\ci#Ux:B*RϧnPkߴu}=:`N=ɜ46!g?x3yWf._{=N#G: &!4V%Q 5?knS5@6W)% 4Ԁnt[.3Y8@9#̵Hf\"`W{,a~3rAPt/{]F]: 9Gu 2mV(*n)Ʌك']auRYdY`,D?&e̛}țBo%!(0.1J<=d@liO +=%y$- +(@cZ 8-2IW# +W`k>h4B6z Ӻ1rUb۴0O4s[caA&tW:Z1^9fҗgSIo<Tѱzx x!d$el /ѱy5'ަz'IS[C"kYBGKv{;ox>+S ߵMmM\G-M U]#9}ýLW{c* AJ39MYͻRSfK)Ti/4 8g؏4VjҌ8Y!~OЖ*̎}+snYOaX5}&4Y6j!qEv(S$׼Oe70:Qa]%Qw^[EМdbۖ)cAd`f"綍%a͔=Ր83}Iq 1cCzޫƄ FH^ƓO:'D;-/PiyYcl`!0վ]5.Ԏ43,,ε:${5CCh* '˛]a2?kՎV9]0n`NDRE$`~ڇ*V/ЅAŅt /ѥ7Uٴ~I<% + "_ OAACiˉR-ԱԱ=3iw}}f~voIS]ҳ}A@*cle1 /ŠFeZͣ@;/(Fㄎx mq9~mH-'26맷ofb2rcTzZվmL>[y<|u +$\h: + ۾cd@7..rҴ Xԕ\M;=.UMnz_3ruxQ]1OdwQD'Kendstream +endobj +1571 0 obj << +/Type /Page +/Contents 1572 0 R +/Resources 1570 0 R +/MediaBox [0 0 612 792] +/Parent 1496 0 R +/Annots [ 1574 0 R 1575 0 R 1579 0 R 1581 0 R ] +>> endobj +1574 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [145.199 690.555 230.831 699.632] +/Subtype /Link +/A << /S /GoTo /D (ttbxstringlist) >> +>> endobj +1575 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [234.013 690.555 317.042 699.632] +/Subtype /Link +/A << /S /GoTo /D (ttbxundolist) >> +>> endobj +1579 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [255.036 447.189 302.414 458.037] +/Subtype /Link +/A << /S /GoTo /D (ttbxcustomlist.minwidth) >> +>> endobj +1581 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [126.573 383.607 175.888 394.455] +/Subtype /Link +/A << /S /GoTo /D (ttbxcustomlist.maxwidth) >> +>> endobj +1573 0 obj << +/D [1571 0 R /XYZ 109.858 727.97 null] +>> endobj +1576 0 obj << +/D [1571 0 R /XYZ 109.858 653.011 null] +>> endobj +1577 0 obj << +/D [1571 0 R /XYZ 109.858 599.259 null] +>> endobj +1578 0 obj << +/D [1571 0 R /XYZ 109.858 525.659 null] +>> endobj +1580 0 obj << +/D [1571 0 R /XYZ 109.858 448.185 null] +>> endobj +1348 0 obj << +/D [1571 0 R /XYZ 109.858 384.603 null] +>> endobj +1582 0 obj << +/D [1571 0 R /XYZ 109.858 282.753 null] +>> endobj +1583 0 obj << +/D [1571 0 R /XYZ 109.858 230.823 null] +>> endobj +1570 0 obj << +/Font << /F29 416 0 R /F55 716 0 R /F34 719 0 R /F28 380 0 R /F22 363 0 R /F41 556 0 R /F8 369 0 R /F19 516 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +1586 0 obj << +/Length 2511 +/Filter /FlateDecode +>> +stream +xYY۸~_UB\<+dJ%U}%H#2O7)'>n^EwKY%c}Z|KF`Y䗫_~RY -WJgL$?\}G%N!/ N+n~/VW~#_mN 66*0)&uUG 'E1aOZ(D.HEKWkѴMyNyX=))1)Fe„֏Ef Tw$"9^5e9@ c"HZwm)7{?+Y*"VˢdarY"lv"ɩET'SCx} FIŴ.se?R`ks. +Ku1k}8qAʧER'I +\nkdRcCT/S ƫ#f!fGp}Ӛ0Mٚ<8(wQt3 )yJMOfG.CmlO[8 +ήh#;u1LfYr23gFз!,殭\ZG>/u@/]\=-!LV7(wn6 +#Um6.Q풬1[./㙢(]uknÃO5 a p0yzy0y +SO["߷B!0=Tg%XR߀%1K`?Iqpe2{/^O8q8pV!פSJ8&P8X3' +;H+ठ6=ڋ/Ϣ_*? +iJ,(T`mAb 'ȏPd/=,w!YE)duV>&?;"3죂C˻u>ƋlQ+#:T3VAU` 2>awXԅЧ}ޠ|RlK^QFUњ dȒnogx AxTޙ]L1bVS{ AB|U'Z5X*(gW6. %$-a;ܒ$6Ge&$[RpgXc-`cуy4&cN:f}ېe'FtBBW(PnuAVHČ`EA%Owm=x,%"hbcCk{rfIof7sw;vBg^ +I-:?xfb'(uK3{0qT>Tx)XHyRlsʃ{.^KflP^xc7I䦗mwQ! Gpe83ݴR&QGr"} ߶641iUI.hݏ\ΚD{m6/FYyi@I }1hZ,ŵ=*~@uMxe|%ܸd4x9>?lsǢ:Zy TTtGf;oxk"/ %^(" O<_b^仨!/C/ŌcΰAءA} j٠԰Qٷ Bo3$]wFkؐ鞑Wמ_ iB2$MRBI +$8*Yиu rSuPdܡQp#\jv?>TTdM,IxYP¹-q> endobj +1588 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [145.199 591.572 192.395 600.649] +/Subtype /Link +/A << /S /GoTo /D (ttbxcustomlist.showimages) >> +>> endobj +1591 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [150.926 408.995 209.817 419.843] +/Subtype /Link +/A << /S /GoTo /D (ttbxcustomlist.ondrawitem) >> +>> endobj +1593 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [244.336 311.369 303.088 320.28] +/Subtype /Link +/A << /S /GoTo /D (ttbxcustomlist.onclearitem) >> +>> endobj +1587 0 obj << +/D [1585 0 R /XYZ 109.858 727.97 null] +>> endobj +1569 0 obj << +/D [1585 0 R /XYZ 109.858 681.914 null] +>> endobj +1589 0 obj << +/D [1585 0 R /XYZ 109.858 592.568 null] +>> endobj +1590 0 obj << +/D [1585 0 R /XYZ 109.858 528.483 null] +>> endobj +1592 0 obj << +/D [1585 0 R /XYZ 109.858 393.055 null] +>> endobj +1594 0 obj << +/D [1585 0 R /XYZ 109.858 245.671 null] +>> endobj +1595 0 obj << +/D [1585 0 R /XYZ 109.858 151.09 null] +>> endobj +1584 0 obj << +/Font << /F29 416 0 R /F28 380 0 R /F22 363 0 R /F41 556 0 R /F8 369 0 R /F55 716 0 R /F34 719 0 R /F19 516 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +1600 0 obj << +/Length 1799 +/Filter /FlateDecode +>> +stream +xXr6}W)BH;-VI@K͖N. !Vc'M&G)O ә +Q0SD,.O3NDr5 +lifAii?*et)D fv6c jG|JIfix=Y(Ld!X_Ts⪫6jv 1yȑME]!trSnx91ۖ;T9 +R0)l2ryn& &옺r3_HaHSnwmKUz_Ms"#lLxe,.w?' CM_]FS@;'yt kP&3MN>Ұ\.tܞU-$K@I{bZI: +q/W_28v#r[ e} T:yK{>n^w@l۹]^.qZ'nޤ\upW +D0`Rj*@ŅkFy#`mt3VӦA:zsk6\(SS% +ؐМcDV.a$QGbؔ61v]:Ȳmji#WCZi V| &X]]U6daZ2mLe{ѻh$XVN>LP-PyⱫ>08zϴ ,NƳjm_C 8->Wgؚ2 7e͖>zbRI/*@ٌ+Y(=vXjF#{/q R;aU緈:G{>[f>X3I+(֞`۴p ޿pjY*%5f:T#=x>7y$!J3}Ibtjh+6D_)ܬZڶ5I4^@  {VWUt#b:(`.0.0 ! 0iJApWp`QnJi|mCqtf@ nj{dpxr c 06`@T9|!g-b{r?%ژ#WHh[f7~7˒LKA$~na[NlKζa'r+-kŕb?ؖ܇mPljܛml"M폗GA;=9+?B+_jc1 + tO6oCA{,Nrendstream +endobj +1599 0 obj << +/Type /Page +/Contents 1600 0 R +/Resources 1598 0 R +/MediaBox [0 0 612 792] +/Parent 1610 0 R +/Annots [ 1602 0 R 1603 0 R 1604 0 R 1605 0 R 1607 0 R 1608 0 R 1609 0 R ] +>> endobj +1596 0 obj << +/Type /XObject +/Subtype /Form +/FormType 1 +/PTEX.FileName (c_ttbxstringlist.pdf) +/PTEX.PageNumber 1 +/PTEX.InfoDict 1611 0 R +/Matrix [1.00000000 0.00000000 0.00000000 1.00000000 0.00000000 0.00000000] +/BBox [0.00000000 0.00000000 15.00000000 15.00000000] +/PieceInfo << +/AdobePhotoshop << +/LastModified (D:20030406201315-05'00') +/Private << +/RoundTrip 1 +/ExportCrispy false +/SaveTransparency false +/ImageResources 1612 0 R +/XObject << +/Im0 1613 0 R +>> +/StandardImageFileData 1614 0 R +>> +>> +>> +/Resources << +/XObject << +/Im0 1613 0 R +>>/ProcSet [ /PDF /ImageC ] +>> +/Length 1615 0 R +>> +stream +q q 15 0 0 15 0 0 cm /Im0 Do Q Q endstream +endobj +1611 0 obj +<< +/Creator (Adobe Photoshop 7.0) +/CreationDate (D:20030406201315-05'00') +/ModDate (D:20030406201315-05'00') +/Producer (Adobe Photoshop for Windows) +>> +endobj +1612 0 obj +<< +/Filter /FlateDecode +/Size 2686 +/Length 1616 0 R +>> +stream +HVyPW !Tq& ؊\UDUJ%,&t$LӱRZXQVGTb-(xT)`۷Kq?:2D&C>%6e>/p'c!{! $.H06ʃ`dV";Ά#܅\:&3nׄ}Sr>C|>t?d Y='o8 GXy ,)t PO3&`Fx22pҕ>rN>Nj4ƒҒVޒst~t2H 4lUɮf'F7&K>5vGIKql@lDSBVB V%)XW+yu7N`8vI+B~02;y?!9`< Ω$8Z4FOj̸2$&} ,RX,K%S-z P(r)"0/OO/L棔dJf)I@r1OrΣaC "{وn7<>O 48Z3%K0gaPbӎطՆ2/:' +,Vﻝ)_ȸMk; +_{ձw;tS=w{O480xMž&P V!9 +AJѴOBhoMYF + DY}|F8Ev@x=`'*r {wwn+_)y kD"oڭUNn*dK~෍uW2 m 7tVvĔ2 "ҵɢ7P^aNL^i0㭏v81aĭ7nZǵu{V&\WPf|k̛txYpփ;=:+y|Rժ+" mA#5_Kϊ/tV1-Eu=RSݙ/*NpSd(XsSqCW`t/C6\]VƮڧ3Ƶ z[[ewd88z77V*ܲof6ho/o!{Siw‹5]%]h+_hp2$|aL9 .z(D@aP a@" @6t𳱡|bj*e& qˊsIzN•D3rI!*UhjT*?DR-4> +/Width 20 +/Height 20 +/BitsPerComponent 8 +/ColorSpace /DeviceRGB +/Length 1617 0 R +>> +stream +H/@Ƈ +XHX@TD/=G%+@  vN-N'ȗ͟˲> +stream +endstream +endobj +1615 0 obj +34 +endobj +1616 0 obj +1535 +endobj +1617 0 obj +292 +endobj +1618 0 obj +0 +endobj +1597 0 obj << +/Type /XObject +/Subtype /Form +/FormType 1 +/PTEX.FileName (c_ttbxundolist.pdf) +/PTEX.PageNumber 1 +/PTEX.InfoDict 1619 0 R +/Matrix [1.00000000 0.00000000 0.00000000 1.00000000 0.00000000 0.00000000] +/BBox [0.00000000 0.00000000 15.00000000 15.00000000] +/PieceInfo << +/AdobePhotoshop << +/LastModified (D:20030406201220-05'00') +/Private << +/RoundTrip 1 +/ExportCrispy false +/SaveTransparency false +/ImageResources 1620 0 R +/XObject << +/Im0 1621 0 R +>> +/StandardImageFileData 1622 0 R +>> +>> +>> +/Resources << +/XObject << +/Im0 1621 0 R +>>/ProcSet [ /PDF /ImageC ] +>> +/Length 1623 0 R +>> +stream +q q 15 0 0 15 0 0 cm /Im0 Do Q Q endstream +endobj +1619 0 obj +<< +/Creator (Adobe Photoshop 7.0) +/CreationDate (D:20030406201220-05'00') +/ModDate (D:20030406201220-05'00') +/Producer (Adobe Photoshop for Windows) +>> +endobj +1620 0 obj +<< +/Filter /FlateDecode +/Size 2678 +/Length 1624 0 R +>> +stream +HVyPW"*tj!XT(VDd! FSq8:[HmV^ EiA`&!o{viRxM>9mv֖_ 0x+m#y!x$]H;0&J +H +aHhѣȧOS h1YF1}v4j4/SO@ KОE}rdk#9|z$`3@.Bpq(ay|zd %lf5Ustds DA0irG`s!jL+>|d/B$h-C% ,\3nCIN"m$qK6 +pY8ڢ7,EԤXFm"3:q*RcMH%m9²:֔ktVʛ|SMWWm&-0NTk'LeHqL@\@ØKUL6Ҋ- 7LKK#y.b11'~pL"([Y ]`7llq0أoX=ųSȑkLT#d"H,2T"U{dF)dex¼R/\Jz+ſI@}"% U`muu("\9_ %Ry#8\`Z'ߟ{6mo(9},Pq4_yub  'VLK9>V}n/ʫ5v7Qn =#bϲ3g:pG΃ގ N-8?/W6XV{wYӶ.eb0'B(oCœ@v.`7J }`ȁ< q<@$T^*LG&|sh.>{P,}Fb.~\ be~0/ kDNQJPBQj:s?ʫy$ 0.M0?6??xl,dVF_ ľLendstream +endobj +1621 0 obj +<< +/Type /XObject +/Subtype /Image +/Interpolate false +/Filter /FlateDecode +/DecodeParms << +/Predictor 2 +/Colors 3 +/BitsPerComponent 8 +/Columns 20 +>> +/Width 20 +/Height 20 +/BitsPerComponent 8 +/ColorSpace /DeviceRGB +/Length 1625 0 R +>> +stream +H-nP $P@Tlf#caXP sѾ}%Ӧpw,=3ciqdYUUU}u]UUuVu˲L4MӔeEя̲<08 Ӣ(8FA9i73IM_~X|0$|"Qge~a$ett:9c6{v˖-dʨ%ZnDQmv8@\.뢎Yka+z߸ +0[G endstream +endobj +1622 0 obj +<< +/Length 1626 0 R +>> +stream +endstream +endobj +1623 0 obj +34 +endobj +1624 0 obj +1529 +endobj +1625 0 obj +289 +endobj +1626 0 obj +0 +endobj +1602 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [378.809 624.79 459.202 635.638] +/Subtype /Link +/A << /S /GoTo /D (ttbxcustomlist.onmeasureheight) >> +>> endobj +1603 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [108.862 485.263 187.316 493.382] +/Subtype /Link +/A << /S /GoTo /D (ttbxcustomitem) >> +>> endobj +1604 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [108.862 463.345 184.165 471.465] +/Subtype /Link +/A << /S /GoTo /D (ttbxcustomlist) >> +>> endobj +1605 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [145.199 362.593 228.228 370.12] +/Subtype /Link +/A << /S /GoTo /D (ttbxundolist) >> +>> endobj +1607 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [108.862 143.163 187.316 151.283] +/Subtype /Link +/A << /S /GoTo /D (ttbxcustomitem) >> +>> endobj +1608 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [108.862 121.245 184.165 129.365] +/Subtype /Link +/A << /S /GoTo /D (ttbxcustomlist) >> +>> endobj +1609 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [108.862 97.584 177.735 107.447] +/Subtype /Link +/A << /S /GoTo /D (ttbxstringlist) >> +>> endobj +1601 0 obj << +/D [1599 0 R /XYZ 109.858 727.97 null] +>> endobj +761 0 obj << +/D [1599 0 R /XYZ 109.858 615.768 null] +>> endobj +270 0 obj << +/D [1599 0 R /XYZ 109.858 605.313 null] +>> endobj +1606 0 obj << +/D [1599 0 R /XYZ 109.858 323.903 null] +>> endobj +1568 0 obj << +/D [1599 0 R /XYZ 109.858 271.731 null] +>> endobj +274 0 obj << +/D [1599 0 R /XYZ 109.858 261.276 null] +>> endobj +1598 0 obj << +/Font << /F29 416 0 R /F22 363 0 R /F41 556 0 R /F8 369 0 R /F28 380 0 R /F50 672 0 R /F55 716 0 R /F34 719 0 R /F54 713 0 R >> +/XObject << /Im32 1596 0 R /Im33 1597 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +1631 0 obj << +/Length 1624 +/Filter /FlateDecode +>> +stream +xڥX[oH~ϯ#sF-@Nlw?2 eB̜9;3U*R2"}\dt'THYK<v[ ˷#-,Gʯenͳ63r}~׳w7;.|#@ %r1x~/n@vm\fY?/^X8* tƟ3@rF(;;Ith7Uϫ_Uwsb-:C|2)2*F[L=^dr0Two+T4;D2(Y |{I\bUKd ,q v큤mj Nˤ:HV"w) y`]#/{q_ }'ظFa PT +iy5K8T(pPY5/hdkU8liQ >" +Tb҆~Y\YЬZJkr%BFCA*G7`|\{P g˕HMpy=mՐq%LǂIlGkɽq.1CGB@zS% +(|l)Tnv Ɔ[ ^RPXt|~F2U qa& ^!3%J%.uͧeH]@"~N ԘN䖮A3F8f!c cFO*HDQ(Xi'OwJjh9'°I C+|A81@4EXU.o+/jWOCZih@M/ۚ~4x[r=(Rt)[һu$:@C+n=D['/֢ԙ<#G-47М&U{~:&EccC/ vw-FJ .eB)BK6F%أ>bEm5,誁{K dlsʶ +lqp0'=VG5䖿xN X'%@ +S NohVꠏ'd8IEH9<}Px 5t>~hZ0iL:}eUAWJ#_D,xچmqaCn'yw<Ұ'>~1,1ҩ m8ͅ5] -[,XCA`xg>Ϧ̄A})Z-"f3 Zad7mxLO ~G+ΑfnQw CB@d>Ol*TF2ib2ޤԙH>$ K> endobj +1627 0 obj << +/Type /XObject +/Subtype /Form +/FormType 1 +/PTEX.FileName (c_ttbxmdihandler.pdf) +/PTEX.PageNumber 1 +/PTEX.InfoDict 1639 0 R +/Matrix [1.00000000 0.00000000 0.00000000 1.00000000 0.00000000 0.00000000] +/BBox [0.00000000 0.00000000 21.00000000 21.00000000] +/PieceInfo << +/AdobePhotoshop << +/LastModified (D:20030406201252-05'00') +/Private << +/RoundTrip 1 +/ExportCrispy false +/SaveTransparency false +/ImageResources 1640 0 R +/XObject << +/Im0 1641 0 R +>> +/StandardImageFileData 1642 0 R +>> +>> +>> +/Resources << +/XObject << +/Im0 1641 0 R +>>/ProcSet [ /PDF /ImageC ] +>> +/Length 1643 0 R +>> +stream +q q 21 0 0 21 0 0 cm /Im0 Do Q Q endstream +endobj +1639 0 obj +<< +/Creator (Adobe Photoshop 7.0) +/CreationDate (D:20030406201252-05'00') +/ModDate (D:20030406201252-05'00') +/Producer (Adobe Photoshop for Windows) +>> +endobj +1640 0 obj +<< +/Filter /FlateDecode +/Size 2620 +/Length 1644 0 R +>> +stream +HV{PTU}²V[IePjB@^tae/G)gr&4M13Y[-jCZ*a"(sϽ*Ns󝝔'MB6K>ĕIMHX1 +}e*w!Db<~,qd/aBEhQfzƈhvkWs*nH";yo{Vzj)" 6S5Asd@B9~&`X 숣g"sܤ.Feb\v34k/(g(b4cR`9e*E(XAI)g O؏Ŀ8ߩyd¸ +*ʀ3  +3hed!!PF ԩfD灄,]V**ZRu!a!AA!AA:5&qMVk4`~ !;:%NIDDG: m]#RJI, 6'J? 6jD*)JGF)'K},(rZ[b[B'w. +{?4S>=WrbQ֨6}-j34\qwޚ1)_t8;p}|΋s!eF{ei5܏] w g=c[7K7w;-神E3Nzޢ|дY;}{μ+_f^bnLhįuš#X`{3uPL{uS-}ɇԤ:[v|FX8@*tQcǀsU#<`?HG8D;>@xMH?++!9ï\eq +RQ+VeVtI$h0'&&FCr19&BxlxFl"x)bOzG=KADKݔ-x[yendstream +endobj +1641 0 obj +<< +/Type /XObject +/Subtype /Image +/Interpolate false +/Filter /FlateDecode +/DecodeParms << +/Predictor 2 +/Colors 3 +/BitsPerComponent 8 +/Columns 28 +>> +/Width 28 +/Height 28 +/BitsPerComponent 8 +/ColorSpace /DeviceRGB +/Length 1645 0 R +>> +stream +H앱@)(4(0 KcYXZ"/=$` `aq AÝKn +2YJzvT̿\.,K$YnAtz"Ay`0PU(0HnEm۲,$`y$ 5P*cN&r|o(X0-nW4 LL:!3냉Ii"k'=-[`K3 C&EI~G(_I\,4Ms]ex! +f`˥ALC/YW@o6`إ~Q(5Y7Z6~QZt*]lp8s06;9 ,rDZ]ؽ rv!`ؤ endstream +endobj +1642 0 obj +<< +/Length 1646 0 R +>> +stream +endstream +endobj +1643 0 obj +34 +endobj +1644 0 obj +1463 +endobj +1645 0 obj +389 +endobj +1646 0 obj +0 +endobj +1628 0 obj << +/Type /XObject +/Subtype /Form +/FormType 1 +/PTEX.FileName (c_ttbxmdiwindowitem.pdf) +/PTEX.PageNumber 1 +/PTEX.InfoDict 1647 0 R +/Matrix [1.00000000 0.00000000 0.00000000 1.00000000 0.00000000 0.00000000] +/BBox [0.00000000 0.00000000 15.00000000 15.00000000] +/PieceInfo << +/AdobePhotoshop << +/LastModified (D:20030406201254-05'00') +/Private << +/RoundTrip 1 +/ExportCrispy false +/SaveTransparency false +/ImageResources 1648 0 R +/XObject << +/Im0 1649 0 R +>> +/StandardImageFileData 1650 0 R +>> +>> +>> +/Resources << +/XObject << +/Im0 1649 0 R +>>/ProcSet [ /PDF /ImageC ] +>> +/Length 1651 0 R +>> +stream +q q 15 0 0 15 0 0 cm /Im0 Do Q Q endstream +endobj +1647 0 obj +<< +/Creator (Adobe Photoshop 7.0) +/CreationDate (D:20030406201254-05'00') +/ModDate (D:20030406201254-05'00') +/Producer (Adobe Photoshop for Windows) +>> +endobj +1648 0 obj +<< +/Filter /FlateDecode +/Size 2642 +/Length 1652 0 R +>> +stream +HVyPW6@H1bB8"AER, lLhhc[kmǢE;Uv:ӎ`=Q< +۷K?:2v2TX,N"1lmV5 +g'b:cQ8, ~,+|q&X d^#a& R!l^_7ӤyR@s>|;"8o{k)6_5^q[~<鄡 T~fX +Ѐq4 &bOuQd@8hq̴iuXR cmuN/MU&'FRB+En.s$؆(4dX([fsўvjF; *:$W{:rRjbQsi8K<[r^ZPMFhS[(G-` +eEfvpO⬰ӮَZR |jV`8zŌ^S+ͶAL~5ɭ ++0n*paT'*3͠>WWl3 f +'{q|Sq"L(LC. FaW +[>pTVLUj,u1=J.+*BQ)5*UDh6ZQaW*juNVIC4&=hh;: 5{m]!J I( 6'HerExH#H,Ȥr 2"E$ٳ$Ku7]zlLq-̑%4;{Nee[ԟ>8ҟ7qͶ]{׫[^EMOv?v~z~aź~8@"B+ƘdRI*g#㵒%uCw̗\KrfG[)} R,1p5ƚ[P`b{T$~-5TE,1tl~vuk>wk/e/r֗Z֧5?;,tvT>wm.}kZu2é1ַ_sg;5xoreV}U[?wz뗯K?s* ij:7T5PogazǴ&:*-G +:-5֬B76efUDpo}+sJZ$/j|{`=>p޵,]e?Mga郍֍C\9σ[G(&<9w=,PZub 5y}Wg d ό.X v3h1WEIxA'K\{>~ g]_\p~~Z?Q%x"vfh]IzH }Zl>Ð&l6^8RIqQr@n2^`2%endstream +endobj +1649 0 obj +<< +/Type /XObject +/Subtype /Image +/Interpolate false +/Filter /FlateDecode +/DecodeParms << +/Predictor 2 +/Colors 3 +/BitsPerComponent 8 +/Columns 20 +>> +/Width 20 +/Height 20 +/BitsPerComponent 8 +/ColorSpace /DeviceRGB +/Length 1653 0 R +>> +stream +H@#X"ŕEG9,-\aE ZXXD"w2rM!ʷ3߬z8 *TU=!a}7MS\ay>u]_mVUeCtZ(9E[rA? <}>EI<̚荁xb1c۶-b֬nEY]Ll5s8~|~nEQ~k?Y;?( +y' ˬ7&&7b̚EE7vYӺxLĶXj$'vgje`_+qfw"{l? endstream +endobj +1650 0 obj +<< +/Length 1654 0 R +>> +stream +endstream +endobj +1651 0 obj +34 +endobj +1652 0 obj +1473 +endobj +1653 0 obj +333 +endobj +1654 0 obj +0 +endobj +1633 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [316.575 666.084 390.88 676.932] +/Subtype /Link +/A << /S /GoTo /D (ttbxstringlist) >> +>> endobj +1634 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [133.768 513.279 213.341 523.242] +/Subtype /Link +/A << /S /GoTo /D (ttbxmdihandler) >> +>> endobj +1635 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [133.768 498.335 233.285 508.298] +/Subtype /Link +/A << /S /GoTo /D (ttbxmdiwindowitem) >> +>> endobj +1637 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [145.199 280.314 258.971 287.841] +/Subtype /Link +/A << /S /GoTo /D (ttbxmdiwindowitem) >> +>> endobj +1632 0 obj << +/D [1630 0 R /XYZ 109.858 727.97 null] +>> endobj +683 0 obj << +/D [1630 0 R /XYZ 109.858 638.189 null] +>> endobj +278 0 obj << +/D [1630 0 R /XYZ 109.858 623.176 null] +>> endobj +1636 0 obj << +/D [1630 0 R /XYZ 109.858 495.347 null] +>> endobj +282 0 obj << +/D [1630 0 R /XYZ 109.858 488.608 null] +>> endobj +1638 0 obj << +/D [1630 0 R /XYZ 109.858 281.31 null] +>> endobj +286 0 obj << +/D [1630 0 R /XYZ 109.858 270.587 null] +>> endobj +1629 0 obj << +/Font << /F29 416 0 R /F28 380 0 R /F8 369 0 R /F50 672 0 R /F51 675 0 R /F55 716 0 R /F34 719 0 R >> +/XObject << /Im34 1627 0 R /Im35 1628 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +1657 0 obj << +/Length 1568 +/Filter /FlateDecode +>> +stream +xڥXnF}WzЖ{#yI<]ѭw.F;1K왝3C$2Y)uI +Q|5ʒ#-s0w @GfDҕwk,{eJ<8ʔjdl)Trt;YwEҙ:!Ϡ4)-οT>.7Xj:, pڰX&^/D)[M>xNlg;A(MY + ,s{LB(k QH#UTH^fJIf֌M"}f=C$S4g:OdzuߵXjuS2ɭ5/T%+?2yI ,4Be$t9;M!\)M=c">UZp.%9Zz–Nr*հ?ʂ?2 75׋ z V^p0dM77kƺC?.lf6.m`:ǟ?8k"> l7|7{r8i#\!~ K=2]H)1 6x-pz-?xD;|1rɐ;N wDJԐI$ +]NGֳôʴAӢ0;C?mfϻXh]1)! +^)u'4G ςO纈<^.. T(PyggdAC beV_}F=0.3Y3HEiQ|Ǻלq Kd=\m+Uܣ )'x8n.j 3˜ '5pyh9 D ֭ϦǑϠ g tS#:px>TǷ[MOt(VL?] <_g3< Gk>G]( %|"=r(=P^^% oV RQa4QFqhͭ-y|9msBPj *B ,5J(q|-D% Y΍u܀ 7BSjD_"w=jTCraZ#̗kJ7k6l/,HF]A#1?я VS|/endstream +endobj +1656 0 obj << +/Type /Page +/Contents 1657 0 R +/Resources 1655 0 R +/MediaBox [0 0 612 792] +/Parent 1610 0 R +/Annots [ 1659 0 R 1660 0 R 1661 0 R 1662 0 R 1663 0 R 1664 0 R ] +>> endobj +1659 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [108.862 646.895 187.316 655.015] +/Subtype /Link +/A << /S /GoTo /D (ttbxcustomitem) >> +>> endobj +1660 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [145.199 530.547 240.639 538.074] +/Subtype /Link +/A << /S /GoTo /D (ttbxmdihandler) >> +>> endobj +1661 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [133.768 416.652 233.923 426.614] +/Subtype /Link +/A << /S /GoTo /D (ttbxcustomstatusbar) >> +>> endobj +1662 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [133.768 401.708 202.898 411.67] +/Subtype /Link +/A << /S /GoTo /D (ttbxstatusbar) >> +>> endobj +1663 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [133.768 386.764 210.56 396.726] +/Subtype /Link +/A << /S /GoTo /D (ttbxstatuspanel) >> +>> endobj +1664 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [133.768 371.82 214.195 381.782] +/Subtype /Link +/A << /S /GoTo /D (ttbxstatuspanels) >> +>> endobj +1658 0 obj << +/D [1656 0 R /XYZ 109.858 727.97 null] +>> endobj +684 0 obj << +/D [1656 0 R /XYZ 109.858 531.543 null] +>> endobj +290 0 obj << +/D [1656 0 R /XYZ 109.858 516.53 null] +>> endobj +1665 0 obj << +/D [1656 0 R /XYZ 109.858 368.831 null] +>> endobj +294 0 obj << +/D [1656 0 R /XYZ 109.858 362.092 null] +>> endobj +1655 0 obj << +/Font << /F29 416 0 R /F28 380 0 R /F50 672 0 R /F8 369 0 R /F55 716 0 R /F34 719 0 R /F51 675 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +1671 0 obj << +/Length 1765 +/Filter /FlateDecode +>> +stream +xڭXMs6WHTMHL-[ITI뻋(JYɇł,U#&Tlf*-rwgVYF< Jq_b;Qzq8,n]$Th]Eo'K^nR5|W!t UGyWvUٴ!ە-2rVh/ +ގ>ʌ4}8WL*YXts_Ml]W["𒈏&TA(V5{3_6zmXy&*aC[aEdg-<+ׄ)[flvk1he8eE{FB %Ca``և -crJknT K$  +>7#u+3_rd} ss0!8gE-EWqY0)ӌ%ZNKc\ P/RpPFRԦ҇ty9LX +miXP\]el<`DRexW=Esr)4OYNjwxE Cݻ& *ϒJ㩾')^ڔ۟Ǖ͊r 3Y&`’FonyKE|;+4t[!%oK#^a~jL,C6ԕ>,/nF&g :+.Þf5s]TwҪJV.Eh=Ϻ^73|G~@.l؄`3&ӿorsc'J J,R{TmwdَX}472NtA܃^]RZj¬Tq/wKBieHMFaokKw\;Hi LT~fڇmmΕiB'Թk'X/$dNl~ +HcwPL'(y@gYendstream +endobj +1670 0 obj << +/Type /Page +/Contents 1671 0 R +/Resources 1669 0 R +/MediaBox [0 0 612 792] +/Parent 1610 0 R +/Annots [ 1673 0 R 1674 0 R 1675 0 R 1678 0 R 1680 0 R 1681 0 R ] +>> endobj +1673 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [392.934 666.084 467.516 676.932] +/Subtype /Link +/A << /S /GoTo /D (ttbxstatusbar) >> +>> endobj +1674 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [489.628 666.084 538.252 676.932] +/Subtype /Link +/A << /S /GoTo /D (ttbxstatusbar) >> +>> endobj +1675 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [108.862 656.066 140.133 664.977] +/Subtype /Link +/A << /S /GoTo /D (ttbxstatusbar) >> +>> endobj +1678 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [145.199 471.572 238.116 479.1] +/Subtype /Link +/A << /S /GoTo /D (ttbxstatuspanel) >> +>> endobj +1680 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [291.538 405.938 374.394 416.786] +/Subtype /Link +/A << /S /GoTo /D (ttbxstatuspanel) >> +>> endobj +1681 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [145.199 390.938 241.456 398.466] +/Subtype /Link +/A << /S /GoTo /D (ttbxstatuspanels) >> +>> endobj +1672 0 obj << +/D [1670 0 R /XYZ 109.858 727.97 null] +>> endobj +1676 0 obj << +/D [1670 0 R /XYZ 109.858 616.972 null] +>> endobj +1677 0 obj << +/D [1670 0 R /XYZ 109.858 551.265 null] +>> endobj +1679 0 obj << +/D [1670 0 R /XYZ 109.858 472.569 null] +>> endobj +1682 0 obj << +/D [1670 0 R /XYZ 109.858 391.935 null] +>> endobj +1683 0 obj << +/D [1670 0 R /XYZ 109.858 314.345 null] +>> endobj +1684 0 obj << +/D [1670 0 R /XYZ 109.858 250.648 null] +>> endobj +1685 0 obj << +/D [1670 0 R /XYZ 109.858 188.887 null] +>> endobj +1669 0 obj << +/Font << /F29 416 0 R /F28 380 0 R /F8 369 0 R /F22 363 0 R /F41 556 0 R /F55 716 0 R /F34 719 0 R /F19 516 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +1688 0 obj << +/Length 1646 +/Filter /FlateDecode +>> +stream +xڭXmo8".X_݇\'q>,nH^6 *fv6 $֎yˣ񈧆LG(),`{Lk+k "~xL`FocAkإ8eBf2D]"UM +pi^`X~N_|qy /Xe"Tl[[lqz|k)⾄{bڋL ~"OBhq[v$vAHf&QI:*ʋ}3Y0eD&>+&UbM2_n;8g4l^m"EmuMsreIG>Mb_ԋzՕM\UOR4K}d;JH/jM7($S"o\*/&Y7ezy؟qo$@TB&y?uWugl(t)%M͡,Rů.ezݥWS7!T`v;msKaX0tv.'P3_dvw6hO ]8:7nv'x +j.B" E0)(̳\| | A`"0N/10D;AH,O*l-vZbT@B~5܁zbb$Jk(UaC{Fv.)`Zx⪲̥iѵ^v@i@#N4B@ B:G#vpl. G;Ѐv` p֔Yp\_m=S'Mw}Sy416Pn +=2.N'K6ݭY0zH5O?&d\zNmH Y/$ [1zkjb30W9Z~,N> d?WN2'.,2i\z< 򩩜q{-Xx_h>}ϰs/{ h*F BNu?Wp68;݃FsCn4Wc NC"ūʋRF fsYA{`w}yA]uBw}K<8g|#wXr*%=m!>?HF9R=dH&ɼHj>ÄЋ:N/B}Z +n)[l-A|-$y2IaN(Z;^>ѡ+TƔ(F,sH&O*@&ptP'YT_|-ې"a*- +C[CG-g 97COt'C?$ endstream +endobj +1687 0 obj << +/Type /Page +/Contents 1688 0 R +/Resources 1686 0 R +/MediaBox [0 0 612 792] +/Parent 1610 0 R +>> endobj +1689 0 obj << +/D [1687 0 R /XYZ 109.858 727.97 null] +>> endobj +1690 0 obj << +/D [1687 0 R /XYZ 109.858 681.914 null] +>> endobj +1691 0 obj << +/D [1687 0 R /XYZ 109.858 606.626 null] +>> endobj +1692 0 obj << +/D [1687 0 R /XYZ 109.858 492.821 null] +>> endobj +1693 0 obj << +/D [1687 0 R /XYZ 109.858 408.069 null] +>> endobj +1694 0 obj << +/D [1687 0 R /XYZ 109.858 325.443 null] +>> endobj +1695 0 obj << +/D [1687 0 R /XYZ 109.858 252.281 null] +>> endobj +1686 0 obj << +/Font << /F29 416 0 R /F28 380 0 R /F22 363 0 R /F41 556 0 R /F8 369 0 R /F19 516 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +1699 0 obj << +/Length 1713 +/Filter /FlateDecode +>> +stream +xڭXYs6~ׯ["8 >G%ՙ$y$:VC +I7]Yu<#Xo`,b4'FHsMrw }?Sc`kDۯ #%RNr#4?aMƔpGT9y]빸5f +'j4oorwGv<'Xn>˻˸lL>/\\/{HEk%R?q%)&khy+hڄ5 ɳ I%HGFꬄ&\s::3FrXZcd 2+m"x\j0Wv3ױLH=m: v +:94 q}( [$Jr+^Ҡ=lpI*=? Wq^38ziNd,ǡIgd4H?&m&!pwz3桙 Uo#,ˇw}N|ր+͔L`q;ǭ^]p}]o2~8A + SCA]]SW-(v?8ޖSk5nW5y)@b;KuUaNdU 6J\}_)RFef#GBEqbseQxsQ2gV:[h# M\d+tDDOrvgw&02xghbOc ]p!m64SCBf m axLGTьP-%sE(ORg,xVn7]- v`L/{z.>A 9[K8q2i&_U}ZsӜyr=~Ȋo:pF' ?OgwOomzpN#fv'_IvMkD؛o}B =Z@x 3*3Urz ,Y< +M(&8,qsB, Ѐ[Dvӌr?퉾} Ps9pjCuQjzC Pn8QlT<}FVqF>!g'T G!2M1!טc8qtz=М! x6k)U<@*3#k+ +> endobj +1696 0 obj << +/Type /XObject +/Subtype /Form +/FormType 1 +/PTEX.FileName (c_ttbxstatusbar.pdf) +/PTEX.PageNumber 1 +/PTEX.InfoDict 1708 0 R +/Matrix [1.00000000 0.00000000 0.00000000 1.00000000 0.00000000 0.00000000] +/BBox [0.00000000 0.00000000 21.00000000 21.00000000] +/PieceInfo << +/AdobePhotoshop << +/LastModified (D:20030406201313-05'00') +/Private << +/RoundTrip 1 +/ExportCrispy false +/SaveTransparency false +/ImageResources 1709 0 R +/XObject << +/Im0 1710 0 R +>> +/StandardImageFileData 1711 0 R +>> +>> +>> +/Resources << +/XObject << +/Im0 1710 0 R +>>/ProcSet [ /PDF /ImageC ] +>> +/Length 1712 0 R +>> +stream +q q 21 0 0 21 0 0 cm /Im0 Do Q Q endstream +endobj +1708 0 obj +<< +/Creator (Adobe Photoshop 7.0) +/CreationDate (D:20030406201313-05'00') +/ModDate (D:20030406201313-05'00') +/Producer (Adobe Photoshop for Windows) +>> +endobj +1709 0 obj +<< +/Filter /FlateDecode +/Size 2614 +/Length 1713 0 R +>> +stream +HV{LSW?ORP"l&"TP>.Z{aQ|m(IT#|d10Y&pn,(Apw/l,}=tj$XT#zy_ٳ?>a:\PU!X%Z'a]̃\V `-g\,/G7|gӰ#dql6 +lEG I^ /K{n7,(8|fR{_duEXd7q!H=:Q䬠#tR[?9"CB8 f-Ǹܙ?{ݖG[L>'e[ݴꌲ$#WF_4FQn! e&r;-0hf ˭~7͆$0Asṭܔ7j.! `aMyYFSf?##F|Q4j v9+KEȟF Xc8S*A ($_+ nLLRhEey& `րc-[ l +T**d2Z#W'*IMFV` *rJR%TvP%p)S9R1L5$Ԑ-]R1 $"D*3@!$BH"Er aJN3ϪI]N/NӜ;.--kw<>G=!}GG&zn[~hfƶO?;+?ؾķ7wVm?pͿ@ @hD,RtB`EF_W"8[t~VwּDo҃b$=\;4ґ_2&C^ # (L50[k7^?E o!v__:kdm(e (·O?ox/wt>jck^_sH?iEgnlm>V29jwulYzO{57w2Ob@4sd:5x| ,D;O_Uסvo48l߉kSQoh=\ؾپ쳮gݍOF;n-U yӝƻk: Mm6wm̀-%ZGm_w߬$<}nprPb#A2 *L#aEh!"L{7dأH`> +/Width 28 +/Height 28 +/BitsPerComponent 8 +/ColorSpace /DeviceRGB +/Length 1714 0 R +>> +stream +H1o@pHp耉 hc2^D~W4F KQIo:./ݽ+˲u+?bEye账>Ǒ ,ks]ײ,IFt:7뚦y>~'8Uii;H3;412ٕY>Y]^;)vƿdڶohĵb1&NkSD R(J!u6s{=ne(ka|ZacuM*A}۩D߇CtFM;m>/RرA|L̖Kdd> +stream +endstream +endobj +1712 0 obj +34 +endobj +1713 0 obj +1456 +endobj +1714 0 obj +375 +endobj +1715 0 obj +0 +endobj +1701 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [108.862 516.035 209.016 524.155] +/Subtype /Link +/A << /S /GoTo /D (ttbxcustomstatusbar) >> +>> endobj +1702 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [425.79 431.623 508.647 442.471] +/Subtype /Link +/A << /S /GoTo /D (ttbxstatuspanel) >> +>> endobj +1703 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [164.265 419.668 194.402 430.516] +/Subtype /Link +/A << /S /GoTo /D (ttbxcustmsttsbr.panels) >> +>> endobj +1704 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [331.661 240.65 418.447 251.498] +/Subtype /Link +/A << /S /GoTo /D (ttbxstatuspanels) >> +>> endobj +1705 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [155.354 228.695 229.936 239.543] +/Subtype /Link +/A << /S /GoTo /D (ttbxstatusbar) >> +>> endobj +1700 0 obj << +/D [1698 0 R /XYZ 109.858 727.97 null] +>> endobj +1666 0 obj << +/D [1698 0 R /XYZ 109.858 645.51 null] +>> endobj +298 0 obj << +/D [1698 0 R /XYZ 109.858 634.786 null] +>> endobj +1667 0 obj << +/D [1698 0 R /XYZ 109.858 420.664 null] +>> endobj +302 0 obj << +/D [1698 0 R /XYZ 109.858 409.94 null] +>> endobj +1706 0 obj << +/D [1698 0 R /XYZ 109.858 191.538 null] +>> endobj +1707 0 obj << +/D [1698 0 R /XYZ 109.858 137.787 null] +>> endobj +1697 0 obj << +/Font << /F29 416 0 R /F22 363 0 R /F41 556 0 R /F8 369 0 R /F28 380 0 R /F50 672 0 R /F54 713 0 R >> +/XObject << /Im36 1696 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +1718 0 obj << +/Length 1732 +/Filter /FlateDecode +>> +stream +xڭXKo6WV Xܞb{E X,dwZlj7937{qGIe"c*nwȻ(˜}5H{\R=@I|ʾ݂kRx(ӕlvSO_-+8e}FrYw: 1,< #K]ZG]qQ"]5 5 x~^{Kxsn2`mPF֫'~U_~`%K"ρБ>WMS Ɵ%d4=>o]ȴ,bDU":&zZU +i ^^UN1v=kU<wQ! ovWtd3%{D|.ގ~HW} +2{O=t}+R5P[7AMjM1+JTp[/6s0Ԃvȃhܙ +ۊd%cs;Ş6g7&h#d 4 pn2 8R:,G'")R&3PBe޽f]Չ/@|D"IdL|&X$$݌p@M +צ`õ'<Ń "]\φj:VSA gZ|t7)vco +C@Vw˺=`,W9X PV!Gr"'eDOa3cA`(֭AP hZ9=vo;pVO:ANzSdw>">G &B|psz +yjEb`1zM *M-3/RaP!YKMꈝmiY!r`27 +6r;Rp/yc-m5|ņX 3Gԩ",rr0ɸ| $dp:NuRI^r#s)H^rξ/(߮뾸37ȿԡ2t*Oу+.Hd=r +_ۡM4EYzbFn=;tsڕ{sએ6R<؜,><0s4ƓN ` m#NV ][Վ躞c.N2i ~Gc8'L&d'|k&'OBf)&Cb7rRt2$G\͈g;q[L B7cU4 +q0tUpQͬ7~Uv -(7md+Dendstream +endobj +1717 0 obj << +/Type /Page +/Contents 1718 0 R +/Resources 1716 0 R +/MediaBox [0 0 612 792] +/Parent 1731 0 R +/Annots [ 1723 0 R 1727 0 R 1729 0 R ] +>> endobj +1723 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [464.612 451.046 521.316 461.894] +/Subtype /Link +/A << /S /GoTo /D (ttbxcustomitem.fontsettings) >> +>> endobj +1727 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [170.077 236.335 202.289 247.183] +/Subtype /Link +/A << /S /GoTo /D (ttbxcustmsttsbr.images) >> +>> endobj +1729 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [356.194 160.682 375.344 171.53] +/Subtype /Link +/A << /S /GoTo /D (ttbxstatuspanel.size) >> +>> endobj +1719 0 obj << +/D [1717 0 R /XYZ 109.858 727.97 null] +>> endobj +1720 0 obj << +/D [1717 0 R /XYZ 109.858 654.974 null] +>> endobj +1721 0 obj << +/D [1717 0 R /XYZ 109.858 579.322 null] +>> endobj +1722 0 obj << +/D [1717 0 R /XYZ 109.858 515.74 null] +>> endobj +1724 0 obj << +/D [1717 0 R /XYZ 109.858 452.042 null] +>> endobj +1725 0 obj << +/D [1717 0 R /XYZ 109.858 378.443 null] +>> endobj +1726 0 obj << +/D [1717 0 R /XYZ 109.858 312.868 null] +>> endobj +1728 0 obj << +/D [1717 0 R /XYZ 109.858 237.331 null] +>> endobj +1730 0 obj << +/D [1717 0 R /XYZ 109.858 151.66 null] +>> endobj +1716 0 obj << +/Font << /F29 416 0 R /F54 713 0 R /F22 363 0 R /F41 556 0 R /F8 369 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +1734 0 obj << +/Length 2448 +/Filter /FlateDecode +>> +stream +x]~J%"/.Z\b5)'ID)Q%)ί|rI_ +oE BeTd"O]@,S q/i4BƋeExl?)] (p2JB݇A$-sd/'Dž@zky 7&}ݻèbKfAŞgڿ$Y$)G0Tù[u}T)"dETVM2J #<Ӝyds4[4+#T4R> aUKJxe8! 4^IV"M2E,KM&2&j$ړ@q0|frRe:QsY` `vx4bQ)+Ge"PLTAG4!JǶ;T `>気4\u<>h(\fe-|p$>3&M{ :&.c'\XXAWGARM<$jag Ұ7?3vx\,NG9R`|\VJb5Pb./g1N}aO.hϱ#>?W$M,)-W.W`uooIe +<{@Ar* V4cfHf<?i3̈́ ^߇Y ~cصG2+|2WW"ZJ%ZTOox9{_t;ǡ"zE l\@[yFplҹђX=8^ ]݁t(,T=ȂuY=X=i2yb7񌮤5Ҳ]؛.X[di1%jg[:\7GC@J7 kA=0 x7;E F=uǔDLC)K Шbd)*cQ!h8 +/ ֙ku9BtjN]U,2CnŸۓKܳα?3r] s?"L8׊"^AN1[n +Y8wǐq&y,A7 ›zfn-i\]%Ü!D*68$ n,]ЁHN+kgI팊q}IB274F;IeJ| @~Cki!īmuODx|$zß?U7gi|v(7cx^2ݷK& +P/K&<৒ db*v !&;>Y/qep"]TG@/YRi<3URFJ*EEX5pse 9ʎ7B/i'z"$S8u,Ȁ4z?Pg zD=:(MԞ<9 ӽ2 > 4|,&- ScA^m1& Aqڦ_Br49E}Q4\Cհ4/LZ +?ŵ277-;ZX^unneLZ?@`5%ģ\L[_aWbyn7G8e6-V Qv +#qC3Nٿ'`D=y$=)^d&{W+eA~*(ZWEd.M)bӱ`SKjS uNxKpXa#|Р~Qz;M/Tݘv,1)uC4(!1 ӕZB U+;:o(̱cFLQ +3 ܵ¾\KMTgͦ$`ɚ?,ENS5R <؟6tӆ$"ZbQ CF|*tߥ`Du*KԻ\pmA ^ W}4-ܐ^ +. n 8n ug'X"VX1kRKNV#ro]h^!~< z=f̚? BPJ+rpk=zXX"=%]Ms7{3CU5Ǟg\]>͡)K#]\CMKle3endstream +endobj +1733 0 obj << +/Type /Page +/Contents 1734 0 R +/Resources 1732 0 R +/MediaBox [0 0 612 792] +/Parent 1731 0 R +/Annots [ 1736 0 R 1738 0 R 1742 0 R ] +>> endobj +1736 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [299.425 642.023 337.947 652.871] +/Subtype /Link +/A << /S /GoTo /D (ttbxstatuspanel.maxsize) >> +>> endobj +1738 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [463.222 544.951 501.744 555.799] +/Subtype /Link +/A << /S /GoTo /D (ttbxstatuspanel.maxsize) >> +>> endobj +1742 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [189.212 159.934 208.362 170.782] +/Subtype /Link +/A << /S /GoTo /D (ttbxstatuspanel.size) >> +>> endobj +1735 0 obj << +/D [1733 0 R /XYZ 109.858 727.97 null] +>> endobj +1737 0 obj << +/D [1733 0 R /XYZ 109.858 643.019 null] +>> endobj +1739 0 obj << +/D [1733 0 R /XYZ 109.858 505.1 null] +>> endobj +1740 0 obj << +/D [1733 0 R /XYZ 109.858 429.563 null] +>> endobj +1741 0 obj << +/D [1733 0 R /XYZ 109.858 247.869 null] +>> endobj +1743 0 obj << +/D [1733 0 R /XYZ 109.858 125.064 null] +>> endobj +1732 0 obj << +/Font << /F29 416 0 R /F54 713 0 R /F22 363 0 R /F41 556 0 R /F8 369 0 R /F20 385 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +1746 0 obj << +/Length 1507 +/Filter /FlateDecode +>> +stream +xڝXr6}W)Q ҧmd7V$y%(b+*Iu)'"K 4$EZ9ˉ̃~_a1(`s$O[0eČB_O_` *! aBH%aya_/f.W3@ Up7LrX k\ +߫MDZUTenrH%œɅM<ˢ"PW->e]mQC!" 2Лp&`wt)焥%fJ%Є~.iSE3Rpdy3k{;"MooMpC$lƒ4:₤Yn Z0ܩWQ̅f;$q]l@d^6bְ]~p %LC̣sWK5 Ҿ1Nfٝq%$gқ釪F >z@/<7P΂ܗGs;(B:ZZ)KЁ97 CڃqszWVmk=kѠlApwexYbb osAgN"[^]]{.Ɯab̫Y^P+Q!(W#2,z7itTo|mh@# gnpfmf0X.2OS)~#]uVmA4!() #)Jxmir̦0BߚMc.7x`7?LN#@ 2+\oSZL`rJF,!ɵB L$@]`oGT=g:>>FB$7b\"ЫpMaC +OAʥ^VmuLJ6R3lco'fLJp=tn·RF! 3[{K5a aW[mA%7c<~\ӄ$1{KcU;'(D"H"_]x )}d J3&%~E?ԟg/]B۫0WifTbܹ"7V=Xrn_\cXåZŒ²UeKܐӷSjYWjo<8ҷw6A6\L^жik$Ƕno^}UկH" ?/(C/vU!9fdF0xL^k ahf<4Oݳܪ}3i7 Be "ϩve-Ugj"O8Y۬dK 8T&-{ao6ou7Rw٧//67r v\CY\5Az56~s6 J4yI_a>OzF~YFEa +tԭ:hU}Npq}\tۑCO#@tmD!endstream +endobj +1745 0 obj << +/Type /Page +/Contents 1746 0 R +/Resources 1744 0 R +/MediaBox [0 0 612 792] +/Parent 1731 0 R +/Annots [ 1748 0 R 1749 0 R 1750 0 R 1753 0 R ] +>> endobj +1748 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [145.199 625.589 194.593 634.666] +/Subtype /Link +/A << /S /GoTo /D (ttbxstatuspanel.viewpriority) >> +>> endobj +1749 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [264.889 446.184 347.745 457.033] +/Subtype /Link +/A << /S /GoTo /D (ttbxstatuspanel) >> +>> endobj +1750 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [403.093 446.184 477.675 457.033] +/Subtype /Link +/A << /S /GoTo /D (ttbxstatusbar) >> +>> endobj +1753 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [230.185 273.53 304.766 284.378] +/Subtype /Link +/A << /S /GoTo /D (ttbxstatusbar) >> +>> endobj +1747 0 obj << +/D [1745 0 R /XYZ 109.858 727.97 null] +>> endobj +1668 0 obj << +/D [1745 0 R /XYZ 109.858 626.586 null] +>> endobj +306 0 obj << +/D [1745 0 R /XYZ 109.858 615.862 null] +>> endobj +1751 0 obj << +/D [1745 0 R /XYZ 109.858 392.091 null] +>> endobj +1752 0 obj << +/D [1745 0 R /XYZ 109.858 338.224 null] +>> endobj +1754 0 obj << +/D [1745 0 R /XYZ 109.858 236.374 null] +>> endobj +685 0 obj << +/D [1745 0 R /XYZ 109.858 182.506 null] +>> endobj +1744 0 obj << +/Font << /F29 416 0 R /F22 363 0 R /F41 556 0 R /F8 369 0 R /F55 716 0 R /F34 719 0 R /F28 380 0 R /F50 672 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +1758 0 obj << +/Length 2228 +/Filter /FlateDecode +>> +stream +xڭX[oF~@DK.@1>3n"E;w4\x/V +T +R4`e`xXImQo[Et*0GrA(=ToR&@JR=7wey*ڕpw2a$K,TRldʹƱJCǗ4v$ '`GG%& S)HRUꓲfPym+p +_y5MeX 1Qh38xY U1xX ܬdw(^@nY . ^qiRpv=B$`HDb,d4QF"]F]T+G_!aJ)0[j8#j^WnOϸ,ai'3ʻYFY|Y*YYk_74C5d~SCg秒2䉉;n/ܬ~SSD"  P:T +X謁l8L%)XkNpJfPC*2tG+qEE@Qby W9{I@%e^B`"BoH7?7ǣf ׺uEC>9/'k]g;䉬g1čA8I ^ +R@0p e;#C› MH*:6m˦^$RPsUQk "oAґHNF7@p7]s ́~rG~or!m<&7q kg喬=paC O`Ԗ[QstY'Jm"-9(JP)FVmSlenб4A ㊖-mSuCao{$ 5GH>M[42$ sʎ(O!l<}_O`s(_KC%*'2ܑ|E;#Ed ^l\rR˾X& 'pmoQ=땂ށc9"ߗۀDUZU6iH 6֑kvr7V%Lk,E%.f{ m|lj!աcM c6 Wo^hM{GzDPCS +8Pq/v/JsYU`KC//Lr#: !īF;4^"qQr`]Vc2>a2z +*- [*>z. 4r 0t?AQ8h>-n; x!5>Ř/Sz3ęy1QYgr +N ߟpZY;0^xK6tJ2߃9!>+,{EXoU[haiNIB,\qt`ļwL H)L[nww' +t2/+KՄCb+l Dw +ȷ< >%`4OL< ƌzPk0L3>Wqל%ZCꮨ/9w (igr,VG.]\Rg 1BOx`o.i;X( +T[T19*opoʂ iK nt1-M. 0i&k`w.Q} = =|Ef!p~</9qVBe˦4g-$_24gL 3(欭 +uvi,=l':endstream +endobj +1757 0 obj << +/Type /Page +/Contents 1758 0 R +/Resources 1756 0 R +/MediaBox [0 0 612 792] +/Parent 1731 0 R +/Annots [ 1760 0 R 1761 0 R 1762 0 R ] +>> endobj +1755 0 obj << +/Type /XObject +/Subtype /Form +/FormType 1 +/PTEX.FileName (c_ttbxswitcher.pdf) +/PTEX.PageNumber 1 +/PTEX.InfoDict 1765 0 R +/Matrix [1.00000000 0.00000000 0.00000000 1.00000000 0.00000000 0.00000000] +/BBox [0.00000000 0.00000000 21.00000000 21.00000000] +/PieceInfo << +/AdobePhotoshop << +/LastModified (D:20030406201319-05'00') +/Private << +/RoundTrip 1 +/ExportCrispy false +/SaveTransparency false +/ImageResources 1766 0 R +/XObject << +/Im0 1767 0 R +>> +/StandardImageFileData 1768 0 R +>> +>> +>> +/Resources << +/XObject << +/Im0 1767 0 R +>>/ProcSet [ /PDF /ImageC ] +>> +/Length 1769 0 R +>> +stream +q q 21 0 0 21 0 0 cm /Im0 Do Q Q endstream +endobj +1765 0 obj +<< +/Creator (Adobe Photoshop 7.0) +/CreationDate (D:20030406201319-05'00') +/ModDate (D:20030406201319-05'00') +/Producer (Adobe Photoshop for Windows) +>> +endobj +1766 0 obj +<< +/Filter /FlateDecode +/Size 2888 +/Length 1770 0 R +>> +stream +HV{TU7`*&vl) DLT26~б~LӋSK ͎8H2L$hJ|J~6ک?:}ws;{Y &_M6n+kK}`ǮlL<8F#ymG1QV@R(GBˌEv">L2 gh>h[%pvi"̀V66gpF#h=C!z +HӁ` z`81!1yEzl #4{n~>_ODẌ́J37Y$|$ t=n_hc{|l mtc82$Y@%"ܦ%45+:KgZC[39)fQg=5 v#hd術q9:0K,6ܙtR>\jiA0{n#Хt 3aT\90K60z5Aa!Ju Ŧ#c{?uR$f :+Pb%0Q߁ `G +38T! Ag DbT,ʽ$^rBP K yd~2̏d~L$ng 9ƕcu=("\9_ %^F p./x+UA ΟV*BWYcNl{|pwZ2{}RZ̉"rЪ5'u\k ݰޱTMSBCۛ>?r]Qk7);S{[80 H!(|" V#Vjz4aH*hhZLB P)jp;1ji_O-m[ALHR2cQtjSma "(6$g_ M8uc no:B\{!c鵩Q>>޼}Z +cR:m{g(p_]~!>G8Ӓݷc3no4䓇/Ľgz6_Oq6_/xuG;<\*t=ù28oթ/w?еsdKNprɘuۺQ>7wɆQc 77uv^TӟyKf:`&HqK?4gQ (5tHBH_@ W F> uH7 't'anL_c;gHee8D/ͨ0%P*Uӕ+F(OCh'|q;IqYlags`!.ce%>=endstream +endobj +1767 0 obj +<< +/Type /XObject +/Subtype /Image +/Interpolate false +/Filter /FlateDecode +/DecodeParms << +/Predictor 2 +/Colors 3 +/BitsPerComponent 8 +/Columns 28 +>> +/Width 28 +/Height 28 +/BitsPerComponent 8 +/ColorSpace /DeviceRGB +/Length 1771 0 R +>> +stream +HĖ10EIAHPKpJJKP4%HPlR@dX@6v +3c)n^%Ij:N>NEj}6rQQy'F۾VſDu~ /tjRJ +{ Rf4#"Dcke_da4uRNHhesdVS7Ƅ%2_O2QT:uH[WnjDppz)3L-̲:upJ|j~Mso6v Fn M `R S[oDj#|z-K endstream +endobj +1768 0 obj +<< +/Length 1772 0 R +>> +stream +endstream +endobj +1769 0 obj +34 +endobj +1770 0 obj +1754 +endobj +1771 0 obj +459 +endobj +1772 0 obj +0 +endobj +1760 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [133.768 630.925 197.091 640.888] +/Subtype /Link +/A << /S /GoTo /D (ttbxswitcher) >> +>> endobj +1761 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [225.084 440.245 312.506 451.093] +/Subtype /Link +/A << /S /GoTo /D (tbxcurrenttheme) >> +>> endobj +1762 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [333.206 440.245 400.648 451.093] +/Subtype /Link +/A << /S /GoTo /D (tbxsettheme) >> +>> endobj +1759 0 obj << +/D [1757 0 R /XYZ 109.858 727.97 null] +>> endobj +310 0 obj << +/D [1757 0 R /XYZ 109.858 703.064 null] +>> endobj +571 0 obj << +/D [1757 0 R /XYZ 109.858 628.136 null] +>> endobj +314 0 obj << +/D [1757 0 R /XYZ 109.858 621.284 null] +>> endobj +1763 0 obj << +/D [1757 0 R /XYZ 109.858 403.218 null] +>> endobj +1764 0 obj << +/D [1757 0 R /XYZ 109.858 337.937 null] +>> endobj +572 0 obj << +/D [1757 0 R /XYZ 109.858 231.476 null] +>> endobj +1756 0 obj << +/Font << /F29 416 0 R /F28 380 0 R /F8 369 0 R /F50 672 0 R /F51 675 0 R /F54 713 0 R /F22 363 0 R /F41 556 0 R /F14 372 0 R >> +/XObject << /Im37 1755 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +1775 0 obj << +/Length 1988 +/Filter /FlateDecode +>> +stream +xڭXݏF e?%U(RUҸR4Ϩ\\5 ;Y 7·kEWt9Wg_ IbUptp vqDIz8֍7uS4&> *L&&s@ Dۮ*pkޮǺ3 Ie@L6QElIlM,5/Ddj0p.Rơ9wB-o ϻRC=p堗ojcI^uqyLH~Wfɬ_>D3-`E +g 8\@Xy*&Tt-,y#6zׅޑiIPV$MOͷHqBS \W.nx/[x2WR]r7vi3rʪjʱv}kD +-# f:AʾtBݺ]:]s_Z|@ e'saD'ugC EA> endobj +1777 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [145.199 665.648 202.812 674.725] +/Subtype /Link +/A << /S /GoTo /D (tbxsettheme) >> +>> endobj +1778 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [205.994 665.648 280.558 674.725] +/Subtype /Link +/A << /S /GoTo /D (tbxcurrenttheme) >> +>> endobj +1781 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [472.926 537.926 531.65 548.774] +/Subtype /Link +/A << /S /GoTo /D (ttbxswitcher.themecount) >> +>> endobj +1783 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [133.768 298.082 209.227 307.945] +/Subtype /Link +/A << /S /GoTo /D (ttbxitemlayout) >> +>> endobj +1776 0 obj << +/D [1774 0 R /XYZ 109.858 727.97 null] +>> endobj +1779 0 obj << +/D [1774 0 R /XYZ 109.858 666.645 null] +>> endobj +1780 0 obj << +/D [1774 0 R /XYZ 109.858 604.497 null] +>> endobj +1782 0 obj << +/D [1774 0 R /XYZ 109.858 488.814 null] +>> endobj +686 0 obj << +/D [1774 0 R /XYZ 109.858 434.947 null] +>> endobj +318 0 obj << +/D [1774 0 R /XYZ 109.858 419.933 null] +>> endobj +322 0 obj << +/D [1774 0 R /XYZ 109.858 288.355 null] +>> endobj +1784 0 obj << +/D [1774 0 R /XYZ 109.858 257.515 null] +>> endobj +1785 0 obj << +/D [1774 0 R /XYZ 109.858 257.515 null] +>> endobj +687 0 obj << +/D [1774 0 R /XYZ 109.858 102.028 null] +>> endobj +1773 0 obj << +/Font << /F29 416 0 R /F14 372 0 R /F8 369 0 R /F55 716 0 R /F34 719 0 R /F22 363 0 R /F41 556 0 R /F28 380 0 R /F54 713 0 R /F50 672 0 R /F51 675 0 R /F20 385 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +1790 0 obj << +/Length 1850 +/Filter /FlateDecode +>> +stream +xڭXK8W,m'fVQr$ƻIS0˟nwaVKǧŃdže: R2"> $"Y#~={|JA$ J~^|X5R& s̄2na"vqx۬Bci,5RKmut¥O CڀE{&ოs U ]ֳ˭^7nY؟gcRVAvc.4i,dOQц[&6T@6 /%,]F`AGf:/s 3> # 'հ/ڵxaA@b'j"$dM4NQzoO~(-$.ݼ)nuzC  3F<Hbԛ~8PC$0Dma2EHXϋ)(`1T=&("~ɡF]nS}rp>j8V<E)j8 x-16cgNdV!,b-z +q-o})&8q:Ť%M\槓k>FqZ|_s˒L;[2WFd!MLu0=n.\7L exMcnځ/+cZQgakOJcSGYBAU4&+{ {+ +=3۱&r`/]LӨ#ϔ~zm=oJ?"6^XwSl!#={Љx]sVGX͌Yog[!8w bB_6y'u(r?k {h};[ ՞_?гT>]F4=QgymXߴzPp +.fzdun*%ƞw :Ժ0k.{q$%pT^>>ʷ~fԙ:4p;HRUt$2@ +Q{ +TQÿu&  +XkVTol}P +8B< h/ a_Y㨐P-F*a12cv[h\F$,ˡulFaD‹8ЉؙofAp׎ +9*\_~A^2znɩ!cw@x'{<]?كM'ջYZV$Sm-c}׹6endstream +endobj +1789 0 obj << +/Type /Page +/Contents 1790 0 R +/Resources 1788 0 R +/MediaBox [0 0 612 792] +/Parent 1731 0 R +/Annots [ 1792 0 R 1793 0 R 1794 0 R 1795 0 R 1796 0 R 1798 0 R 1799 0 R 1800 0 R 1801 0 R ] +>> endobj +1786 0 obj << +/Type /XObject +/Subtype /Form +/FormType 1 +/PTEX.FileName (c_ttbxcolorpalette.pdf) +/PTEX.PageNumber 1 +/PTEX.InfoDict 1804 0 R +/Matrix [1.00000000 0.00000000 0.00000000 1.00000000 0.00000000 0.00000000] +/BBox [0.00000000 0.00000000 15.00000000 15.00000000] +/PieceInfo << +/AdobePhotoshop << +/LastModified (D:20030406201231-05'00') +/Private << +/RoundTrip 1 +/ExportCrispy false +/SaveTransparency false +/ImageResources 1805 0 R +/XObject << +/Im0 1806 0 R +>> +/StandardImageFileData 1807 0 R +>> +>> +>> +/Resources << +/XObject << +/Im0 1806 0 R +>>/ProcSet [ /PDF /ImageC ] +>> +/Length 1808 0 R +>> +stream +q q 15 0 0 15 0 0 cm /Im0 Do Q Q endstream +endobj +1804 0 obj +<< +/Creator (Adobe Photoshop 7.0) +/CreationDate (D:20030406201231-05'00') +/ModDate (D:20030406201231-05'00') +/Producer (Adobe Photoshop for Windows) +>> +endobj +1805 0 obj +<< +/Filter /FlateDecode +/Size 2718 +/Length 1809 0 R +>> +stream +HVyPW@ Tc%\jQAX2IK(?VFi+֩*ҪJAbiŋ۷(NG{^ĥ K9mx/oSY0+k##Q$$w>$0.ʕqeeN"B +4km(4Р fLe Yj=ܧ`7x${8y9R 5!O#ܗr{^ l|/uCo0$\,4-e6Lڕ{f>fJ6U@R-MQ@hL}!=JȢ|´L3#B6T $HHM[7R'2 \ %YbtPvטi*0F M5%9֒Zdvl;kMzI#֐tF邏0XMRӴEMRHc"RSlj:@c&i}ap_bS;iIGW% ,7(TI6 JBi)ąϻS@,$$y2V[ڈHƫ񒠪]OMQv7a.t=˷5ئ3̿%|~nXRr۾sm݃6WןlaEQ0/!DP- +߰U"hμ8b˸*>'$HGn |u9h8 0@w*@ YwPPzꉾ^RؔtNbKCKSѷV-ʎXזYk$GwXMm;-'wǕe͹R=scklEዶ#m u=Ik'r_9w3}o#GgR~][,+-,o)}͍]Pz.溜OǗmǀ':,Z[MOO V޳o $xV?вA£Ҟ Hd@nj7f@>g;#?4^a'G/1?k4]a> +/Width 20 +/Height 20 +/BitsPerComponent 8 +/ColorSpace /DeviceRGB +/Length 1810 0 R +>> +stream +HĔn0H0tH 1CG<#<c- Y +E5<#<@<0$'&ihXzQ|/lht I +T*E(`nnV*DVVrRjtlU2p0|)q~UeᜃŦժc/ +>Q$Ea4]Ț~#ϳGJ oE!|n}á++[h<3vTvYJ2uߜ$)eZ\ؗɤj5M~bnQ#7,ޠG'@)ڴi endstream +endobj +1807 0 obj +<< +/Length 1811 0 R +>> +stream +endstream +endobj +1808 0 obj +34 +endobj +1809 0 obj +1558 +endobj +1810 0 obj +392 +endobj +1811 0 obj +0 +endobj +1787 0 obj << +/Type /XObject +/Subtype /Form +/FormType 1 +/PTEX.FileName (colorset.pdf) +/PTEX.PageNumber 1 +/PTEX.InfoDict 1812 0 R +/Matrix [1.00000000 0.00000000 0.00000000 1.00000000 0.00000000 0.00000000] +/BBox [0.00000000 0.00000000 142.00000000 88.00000000] +/Resources << +/ProcSet [ /PDF /ImageC /ImageI ] +/XObject << +/Im1 1813 0 R +>>/ExtGState << +/GS1 1814 0 R +>>/ColorSpace << +/Cs6 1815 0 R +/Cs9 1816 0 R +>>>> +/Length 89 +/Filter /FlateDecode +>> +stream +H*2TT230V0׳0Q041Գ45RR݃ ҋ + +, ȄjO5Tp +B +endstream +endobj +1812 0 obj +<< +/CreationDate (D:20030406193524-04'00') +/ModDate (D:20030406193524-04'00') +/Producer (Acrobat Distiller 5.0.5 \(Windows\)) +/Creator (Corel PHOTO-PAINT 10) +/Title (colorset.ep$) +>> +endobj +1813 0 obj +<< +/Type /XObject +/Subtype /Image +/Width 142 +/Height 88 +/BitsPerComponent 8 +/ColorSpace 1816 0 R +/Length 228 +/Filter /FlateDecode +>> +stream +HֹnAQ|sD]"A$+y&dveߗrEJ)=!)Hyk\״yMU/fuK9R!R^2k\״yMU/fu91ARH!ew|5qkڼAR9o ) ,׸59_sku +9F)[쐲G)G5qMT2蒓]G@ +endstream +endobj +1814 0 obj +<< +/Type /ExtGState +/SA false +/SM 0.02 +/OP false +/op false +/OPM 1 +/BG2 /Default +/UCR2 /Default +/TR2 /Default +>> +endobj +1815 0 obj +[/ICCBased 1817 0 R] +endobj +1816 0 obj +[/Indexed 1815 0 R 40 1818 0 R] +endobj +1817 0 obj +<< +/N 3 +/Alternate /DeviceRGB +/Length 2575 +/Filter /FlateDecode +>> +stream +HyTSwoɞc [5laQIBHADED2mtFOE.c}08׎8GNg9w߽'0 ֠Jb  + 2y.-;!KZ ^i"L0- @8(r;q7Ly&Qq4j|9 +V)gB0iW8#8wթ8_٥ʨQQj@&A)/g>'Kt;\ ӥ$պFZUn(4T%)뫔0C&Zi8bxEB;Pӓ̹A om?W= +x-[0}y)7ta>jT7@tܛ`q2ʀ&6ZLĄ?_yxg)˔zçLU*uSkSeO4?׸c. R ߁-25 S>ӣVd`rn~Y&+`;A4 A9=-tl`;~p Gp| [`L`< "A YA+Cb(R,*T2B- +ꇆnQt}MA0alSx k&^>0|>_',G!"F$H:R!zFQd?r 9\A&G rQ hE]a4zBgE#H *B=0HIpp0MxJ$D1D, VĭKĻYdE"EI2EBGt4MzNr!YK ?%_&#(0J:EAiQ(()ӔWT6U@P+!~mD eԴ!hӦh/']B/ҏӿ?a0nhF!X8܌kc&5S6lIa2cKMA!E#ƒdV(kel }}Cq9 +N')].uJr + wG xR^[oƜchg`>b$*~ :Eb~,m,-ݖ,Y¬*6X[ݱF=3뭷Y~dó ti zf6~`{v.Ng#{}}jc1X6fm;'_9 r:8q:˜O:ϸ8uJqnv=MmR 4 +n3ܣkGݯz=[==<=GTB(/S,]6*-W:#7*e^YDY}UjAyT`#D="b{ų+ʯ:!kJ4Gmt}uC%K7YVfFY .=b?SƕƩȺy چ k5%4m7lqlioZlG+Zz͹mzy]?uuw|"űNwW&e֥ﺱ*|j5kyݭǯg^ykEklD_p߶7Dmo꿻1ml{Mś nLl<9O[$h՛BdҞ@iءG&vVǥ8nRĩ7u\ЭD-u`ֲK³8%yhYѹJº;.! +zpg_XQKFAǿ=ȼ:ɹ8ʷ6˶5̵5͵6ζ7ϸ9к<Ѿ?DINU\dlvۀ܊ݖޢ)߯6DScs 2F[p(@Xr4Pm8Ww)Km +endstream +endobj +1818 0 obj +<< +/Length 86 +/Filter /FlateDecode +>> +stream +H4 @ ى> +>> endobj +1793 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [133.768 599.798 197.091 609.761] +/Subtype /Link +/A << /S /GoTo /D (ttbxcolorset) >> +>> endobj +1794 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [133.768 584.854 228.372 594.817] +/Subtype /Link +/A << /S /GoTo /D (ttbxcustomcolorset) >> +>> endobj +1795 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [133.768 569.91 240.001 579.873] +/Subtype /Link +/A << /S /GoTo /D (ttbxcustomtoolpalette) >> +>> endobj +1796 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [133.768 554.966 208.976 564.929] +/Subtype /Link +/A << /S /GoTo /D (ttbxtoolpalette) >> +>> endobj +1798 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [108.862 426.394 187.316 434.514] +/Subtype /Link +/A << /S /GoTo /D (ttbxcustomitem) >> +>> endobj +1799 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [108.862 404.476 215.095 412.695] +/Subtype /Link +/A << /S /GoTo /D (ttbxcustomtoolpalette) >> +>> endobj +1800 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [443.453 219.168 483.11 230.016] +/Subtype /Link +/A << /S /GoTo /D (ttbxcolorpalett.colorset) >> +>> endobj +1801 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [203.037 207.213 271.336 218.061] +/Subtype /Link +/A << /S /GoTo /D (ttbxcolorset) >> +>> endobj +1791 0 obj << +/D [1789 0 R /XYZ 109.858 727.97 null] +>> endobj +326 0 obj << +/D [1789 0 R /XYZ 109.858 703.064 null] +>> endobj +1797 0 obj << +/D [1789 0 R /XYZ 109.858 551.977 null] +>> endobj +330 0 obj << +/D [1789 0 R /XYZ 109.858 545.239 null] +>> endobj +1802 0 obj << +/D [1789 0 R /XYZ 109.858 170.056 null] +>> endobj +1803 0 obj << +/D [1789 0 R /XYZ 109.858 116.189 null] +>> endobj +1788 0 obj << +/Font << /F29 416 0 R /F28 380 0 R /F8 369 0 R /F50 672 0 R /F51 675 0 R /F54 713 0 R /F22 363 0 R /F41 556 0 R >> +/XObject << /Im38 1786 0 R /Im39 1787 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +1825 0 obj << +/Length 1950 +/Filter /FlateDecode +>> +stream +xڝX[6~УDx)IX4/Pb˱[:䞓s!%vpNL3Ù7C(2-BʢoJzTKQ05Ql$~i̢T W:kǟYiqeL(X'TQ$׊huPxJif;vg"^"O ?O.Q&ɟ_WZOetxaM5]('Re߶y~:qEuVqu)cP ,siZRs }N@rCs);Lu\6i\88&SDpzh}Xo+sQjyhO.Y_ui֓}{{psYm#'.m5ʻ2:I1NicXȁ՚R8r;%,:IeAu:$5uDE :\k}I$=d GUA!8zQ'd1^f"X(:iac3!\^/40n-p*o6Y~QL")lY{!1<𘔿u]I +rkq=7mx{?@0i2|=)|wաeahY[l}M3sע'itqch; )9?C[R4Ok3>^_;ty,:⿂Q}\"{L/S6*:_  ٌ: IGĩtRF ~%&+T m%*p`XO= 3baV]pe*{8jPr/= $nB +>˳fo>,8+|}RM{vWJPo@ gcӺKOtá GV(WnU.>B2R qJL(>7gmYϴ3ʸynK9-dHᢤ=Çv:/"XC@|Y"ߴ7/D${Ys?աh&@ס詟_*yǐ?r@K\;GԈ'(PkqW\㏁w9PӾѵDNѳo %V*寂Í;RENܻ-W2M}7n=t@<=߉"OueꟄLCSzG ,86Y؜S捿p ;ofOk<<"+nU@_1/Ү(D\\%_&~VWdz''.ݿ(,YMWptEܗ6/6T/k99wzRBHGOrYt##\)/R>Tf,ȅA5̤kv .^q5-SevJ\;#8 Js%—k&knVAjvM/&endstream +endobj +1824 0 obj << +/Type /Page +/Contents 1825 0 R +/Resources 1823 0 R +/MediaBox [0 0 612 792] +/Parent 1833 0 R +/Annots [ 1827 0 R 1830 0 R 1832 0 R ] +>> endobj +1822 0 obj << +/Type /XObject +/Subtype /Form +/FormType 1 +/PTEX.FileName (c_ttbxcolorset.pdf) +/PTEX.PageNumber 1 +/PTEX.InfoDict 1834 0 R +/Matrix [1.00000000 0.00000000 0.00000000 1.00000000 0.00000000 0.00000000] +/BBox [0.00000000 0.00000000 21.00000000 21.00000000] +/PieceInfo << +/AdobePhotoshop << +/LastModified (D:20030406201233-05'00') +/Private << +/RoundTrip 1 +/ExportCrispy false +/SaveTransparency false +/ImageResources 1835 0 R +/XObject << +/Im0 1836 0 R +>> +/StandardImageFileData 1837 0 R +>> +>> +>> +/Resources << +/XObject << +/Im0 1836 0 R +>>/ProcSet [ /PDF /ImageC ] +>> +/Length 1838 0 R +>> +stream +q q 21 0 0 21 0 0 cm /Im0 Do Q Q endstream +endobj +1834 0 obj +<< +/Creator (Adobe Photoshop 7.0) +/CreationDate (D:20030406201233-05'00') +/ModDate (D:20030406201233-05'00') +/Producer (Adobe Photoshop for Windows) +>> +endobj +1835 0 obj +<< +/Filter /FlateDecode +/Size 2902 +/Length 1839 0 R +>> +stream +HV{\SU?wؘ"Z&PQ(öˆlݡQYV0J$?j>p߈/DG02n{7ڧos}ww~王IH4ڸ-6^I{#0Q<7$2 b{DF0x\hѣHlhYF16~yP4ՠLަ Y='g"3XGyqSa@& O A:8p:%yNzY $)Y9_kOUA-y: Iijɾr IYHh>Q ]>AB$$'Pc$yN*apY%I\tPv2܀H\п.3- z٨K\|gMI;iY:2=K㤓p/"LIJ],ƂIR2fv5]]5e1q>n$aW;*50) 00zD^4} 碃|J+Q$,SzWO%G,"O$/u$X(`9*p:9a28Q$53cH%t&"X$"H,K&ȼ=<<<Dl\]ݤnRT*''"7 \GqunCƢ!J>- nEbWI#8\`{]?޴ed():Rw#|Lw7loC80 PaXP?DσؓFp ԃ畍ekbӼT4a@q3H# $\L9~~Mv5VΉ:vڍ gU5qߴ U)WjolN o\Yqb[BO6eVM3λ?t(yvV|3\ʒ4H?;BU<`k6 +<~\ֵcgV55D\hѾXf*o^Zpe\ѹn@dް3v~]3$Uws >0Դ,u.?7ZV1Ktn)vqf坴/T}Ϻ4XBkj>&F]Ciӗ_Qes"owZv}QE!m;{V- ?޵ru}u?~M_}<}V=²}e-=+;oiؑ0M+wx4Cmn–{卭֝U8곰Mu;R-ovϕgޱn17àj9rAM^QvaSw lx}q.5s]^)܆]C)Iw2 4Wd7)PA<ӭ7_I@ /%}t< qy<|A8 +6C; ) H_@oB |3*~>6XL v+a,pG&+KZ$LZx*@B VDGִcGQl8ll`\/~/~lH_9Non;ų2Z`>?endstream +endobj +1836 0 obj +<< +/Type /XObject +/Subtype /Image +/Interpolate false +/Filter /FlateDecode +/DecodeParms << +/Predictor 2 +/Colors 3 +/BitsPerComponent 8 +/Columns 28 +>> +/Width 28 +/Height 28 +/BitsPerComponent 8 +/ColorSpace /DeviceRGB +/Length 1840 0 R +>> +stream +Hܕ@3 *¶i,.-}`ka _6iT +Zߙud&ʲlS$3?g80r9ϸ/}>_0 s&G: Y]#H, *Ye2xa4[x<*Ybx:ݮ ER9NBG(bXɁ.aNLÑ B!J+2^LBXj*JbyT0I[* {eC*X.3 ESd:Ju1vRA 1U"PPC2x&Iw݁zVUSf3Ko[-p8L+-`^!R$4νJ&my`'N^Dpc. DQ<9NmۦuD `#tU_0[l6a0Y =/K+ endstream +endobj +1837 0 obj +<< +/Length 1841 0 R +>> +stream +endstream +endobj +1838 0 obj +34 +endobj +1839 0 obj +1766 +endobj +1840 0 obj +692 +endobj +1841 0 obj +0 +endobj +1827 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [145.199 615.068 225.73 622.596] +/Subtype /Link +/A << /S /GoTo /D (ttbxcolorset) >> +>> endobj +1830 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [164.542 409.593 204.199 420.441] +/Subtype /Link +/A << /S /GoTo /D (ttbxcolorpalett.colorset) >> +>> endobj +1832 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [108.862 205.562 203.465 213.781] +/Subtype /Link +/A << /S /GoTo /D (ttbxcustomcolorset) >> +>> endobj +1826 0 obj << +/D [1824 0 R /XYZ 109.858 727.97 null] +>> endobj +1828 0 obj << +/D [1824 0 R /XYZ 109.858 575.975 null] +>> endobj +1829 0 obj << +/D [1824 0 R /XYZ 109.858 500.134 null] +>> endobj +1831 0 obj << +/D [1824 0 R /XYZ 109.858 410.589 null] +>> endobj +1819 0 obj << +/D [1824 0 R /XYZ 109.858 334.936 null] +>> endobj +334 0 obj << +/D [1824 0 R /XYZ 109.858 324.213 null] +>> endobj +1823 0 obj << +/Font << /F29 416 0 R /F54 713 0 R /F22 363 0 R /F41 556 0 R /F8 369 0 R /F55 716 0 R /F34 719 0 R /F28 380 0 R /F50 672 0 R >> +/XObject << /Im40 1822 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +1844 0 obj << +/Length 1949 +/Filter /FlateDecode +>> +stream +xڭXr6}W)QOۤL4Qg2䁑蘭D:$]\(^dv2HpX=MrG[bI4dȓO xoDDddXcQŻym,aMr9a& !-aڄś?-NU #L4nﰿϙM: A`}.WLe[֛raA#As"gEk)ƫgL2LW]i}v:mݫgiV.؀괚[.&LsG&pes")uTvĂ]峜pipz}hv{jvMfE6OGP ^oɜXRxti%qf66>\}]ؕ}+'.-Ȝ3eM!+K_'ނ%m|3W7~k99,mni(0:[/fw}` d +@)R9hu.ҍ}[}EVLn7L +|}o$@.e߈3 jUަ LCmXYwbKP *z/ڋCE @orƻ4h%rBzDl4uv"9@m/H=1fG/rvUɉfrjQoi~gMvEZ?!}r9  o]BZiQSyB*+(K2#\6q$n' 9!3-?/UvVnWO76zKf)3Eg!/ޕᗵ`KLZ /sn}!5j~Jά{!Dq_vEׅ=Udc/*2 Vx8kݣ A_Yow1h%He;WPcʾ;xalTeВA7p'R$Bs [laشӵ1 XLnAeÓIg 32㱡W~^E 9.2i$ج&?"b#ZV$PIǢ+I70QK`+#u&ԇg\r:\?]C h-L'Ԇ83M]L j4:  +9=MޢL68ɛ905 dޔ"nC,$I\ 8`px؀PZZWOqf65Z{=5WHyz +C˂s jף¼n +W[$xY jbDRp&Lb lrDt(X셇>WAD + M}"}Y'e +S3(|xȋ+x2+p3Sgp$+ȯF;<&Єsƅ2~(.Q`7F ;Ũ8(FWrHoele/n==jj +荄^ؔA&C̢sw|#9 "0 +^;UpCS@3:)XcX7 ®;:pl*Eli[?=:-1 i_≅ޏ +Ҡ"rwSm[i[ڱǝfO((˝83M]4Ǟ(A'V-`dή'/O>)"_sې ͚NXKw ڲ +n \P-ȸզ`DF +?ff oX'..IYS㞘!̀]nzﹻ C/W uBO~N%6bDk51}~EP7.zk/MMJVɡнw> endobj +1846 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [249.953 666.084 335.272 676.932] +/Subtype /Link +/A << /S /GoTo /D (ttbxcolorpalette) >> +>> endobj +1847 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [306.786 637.192 350.567 648.041] +/Subtype /Link +/A << /S /GoTo /D (ttbxcustomclrst.colcount) >> +>> endobj +1848 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [372.934 637.192 421.004 648.041] +/Subtype /Link +/A << /S /GoTo /D (ttbxcustomclrst.rowcount) >> +>> endobj +1849 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [382.863 625.237 455.244 636.086] +/Subtype /Link +/A << /S /GoTo /D (ttbxcustomclrst.ongetcolorinfo) >> +>> endobj +1850 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [489.351 448.257 538.252 457.168] +/Subtype /Link +/A << /S /GoTo /D (ttbxcolorset) >> +>> endobj +1851 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [108.862 436.301 133.575 445.102] +/Subtype /Link +/A << /S /GoTo /D (ttbxcolorset) >> +>> endobj +1852 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [145.199 419.365 240.193 426.892] +/Subtype /Link +/A << /S /GoTo /D (ttbxcolorpalette) >> +>> endobj +1856 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [108.862 159.672 181.243 168.583] +/Subtype /Link +/A << /S /GoTo /D (ttbxcustomclrst.ongetcolorinfo) >> +>> endobj +1857 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [299.65 140.798 384.97 151.646] +/Subtype /Link +/A << /S /GoTo /D (ttbxcolorpalette) >> +>> endobj +1845 0 obj << +/D [1843 0 R /XYZ 109.858 727.97 null] +>> endobj +1820 0 obj << +/D [1843 0 R /XYZ 109.858 626.234 null] +>> endobj +338 0 obj << +/D [1843 0 R /XYZ 109.858 615.51 null] +>> endobj +1853 0 obj << +/D [1843 0 R /XYZ 109.858 380.271 null] +>> endobj +1854 0 obj << +/D [1843 0 R /XYZ 109.858 326.404 null] +>> endobj +1855 0 obj << +/D [1843 0 R /XYZ 109.858 224.553 null] +>> endobj +1858 0 obj << +/D [1843 0 R /XYZ 109.858 129.839 null] +>> endobj +1842 0 obj << +/Font << /F29 416 0 R /F28 380 0 R /F8 369 0 R /F50 672 0 R /F55 716 0 R /F34 719 0 R /F22 363 0 R /F41 556 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +1862 0 obj << +/Length 1941 +/Filter /FlateDecode +>> +stream +xڭXYs6~ׯ#9SAt&CLf<d塒T4:$=jr+s>Kkvh_D+sá5uc_/:]m |b.*M"!2E~f3Ϟa&6W~IS Ч'|z"FAp3$AmJ::/&oudh@7BI 9//HFx'- yp9P|@1c 6 *vnЁ++X9Cx-IuM؇m[q0Rӝlhx +%i3؛:n"M +Cqʜe}m~ިT"/ȋy֗dew=nrn}:9 kMCpR[PmcTwv,l2 IY0^A:h=ON uu~g,qVjM\( &F߯Ig[Xmmu;kLnwDN`~}Imt磃f$? )t8:a'sE]Hc 68m.hXLya.."|lq;7(/<C- +Ώv0m7|@\; " m++Vn" ,eW"GKк<2m/ 9%v}kأ (dNEIf6vfMloK]ÕNKUj܍dPO4~DoN~D endstream +endobj +1861 0 obj << +/Type /Page +/Contents 1862 0 R +/Resources 1860 0 R +/MediaBox [0 0 612 792] +/Parent 1833 0 R +/Annots [ 1864 0 R 1865 0 R 1866 0 R 1867 0 R 1870 0 R ] +>> endobj +1864 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [126.02 643.96 198.401 652.871] +/Subtype /Link +/A << /S /GoTo /D (ttbxcustomclrst.ongetcolorinfo) >> +>> endobj +1865 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [108.862 390.74 187.316 398.859] +/Subtype /Link +/A << /S /GoTo /D (ttbxcustomitem) >> +>> endobj +1866 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [350.491 320.22 431.632 329.131] +/Subtype /Link +/A << /S /GoTo /D (ttbxtoolpalette) >> +>> endobj +1867 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [457.111 320.22 538.251 329.131] +/Subtype /Link +/A << /S /GoTo /D (ttbxtoolpalette) >> +>> endobj +1870 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [145.199 115.131 215.286 124.209] +/Subtype /Link +/A << /S /GoTo /D (ttbxcustmtlpltt.ondrawcellimage) >> +>> endobj +1863 0 obj << +/D [1861 0 R /XYZ 109.858 727.97 null] +>> endobj +1859 0 obj << +/D [1861 0 R /XYZ 109.858 604.866 null] +>> endobj +1821 0 obj << +/D [1861 0 R /XYZ 109.858 520.114 null] +>> endobj +342 0 obj << +/D [1861 0 R /XYZ 109.858 509.391 null] +>> endobj +1868 0 obj << +/D [1861 0 R /XYZ 109.858 269.171 null] +>> endobj +1869 0 obj << +/D [1861 0 R /XYZ 109.858 205.839 null] +>> endobj +1871 0 obj << +/D [1861 0 R /XYZ 109.858 116.128 null] +>> endobj +1860 0 obj << +/Font << /F29 416 0 R /F22 363 0 R /F41 556 0 R /F8 369 0 R /F28 380 0 R /F50 672 0 R /F54 713 0 R /F55 716 0 R /F34 719 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +1875 0 obj << +/Length 2288 +/Filter /FlateDecode +>> +stream +xڭYs6_GifE:]әmܹ޴}PlVWr\vN+~?A&(]$a"d[XDžd"Mak" SO, )w/bܾ]:KO0D2&)./n.qdѱ)(^2c~u񗿇^- VOgS껋 N% HE'J9 cCU4ZqgWG_^^})=Q/2Y#O-3B : $jDQtNsGrDs)E+;L)!I&QPlcb nxhHyuk(l-cp'<7:.Ĥ{8՜IX0Ӏ}&v)-"YRiNW]2e&tY>I'iKRoLt, YH.AM:㿷3Rz -wm|>,>qB{LT Miѹ`J1\|+"P"NWzEO|+ ^1<~RlY\Whb^*`s48V4 $̼h8 +5"e J wE*jb1uyp,N::JQGlWMJ@:*xb0tmLHPlw%}%eE55cL>gDf.o +/ Vf#n7`*E^ۙV4T t!P:搃 3eӴz?IQh^5u"tDׅրTh9}-wT:K8Hş(U}Ta4EU}PWjF26B>6%`YfFRF + %e\m}o'T{1ᓗֈnc[ѓ6.?[>2d6$TIk\Нն44^w* ‚wGZf_QYUz-0ZL-&s;s7n/2!AD82HI:2#vSaP7<Ą;dDYDBGg$-tb]7$T#jk2X}x}r}}oMW* o@| +y#8[}%7*Ds +)(q >l͜JE*)"6NLH DWDV:@I + F^w;dzs#HhLB'<׀SJ1%k)6?.5P\,j4g%N0c`^ +u<,X⊄&.cq`Ä.qtI-Ҿv?(X6c5#\\ye>mwVL쟉+mY?CiyId*Yy9N:|=<#@Muydte0 NJ 1'QDUʭuft >%lh@mME?-#?]wB1IwVw.[gЄ{DegP3NFͺ#9ȤiR ]abWrبK8%R>⚮ے`c`®0zrV 9nɧd`<~cu 뷃q^5v24j],e[4inhA!M ɯ[M86<S#y[AY*mqoc;y/u?37MŽ!]JKaƭ C#PԘs*f1,e4| ZB_޹lyŜŕ {=Rl+LsV : +6kݢP!MD$F`PwXH M3ꮺ7Tp@/l!!$?Rj`Qeendstream +endobj +1874 0 obj << +/Type /Page +/Contents 1875 0 R +/Resources 1873 0 R +/MediaBox [0 0 612 792] +/Parent 1833 0 R +/Annots [ 1879 0 R 1880 0 R 1883 0 R 1884 0 R 1886 0 R ] +>> endobj +1879 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [394.276 447.949 438.057 458.797] +/Subtype /Link +/A << /S /GoTo /D (ttbxcustmtlpltt.colcount) >> +>> endobj +1880 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [458.377 447.949 506.447 458.797] +/Subtype /Link +/A << /S /GoTo /D (ttbxcustmtlpltt.rowcount) >> +>> endobj +1883 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [490.32 229.909 538.252 241.864] +/Subtype /Link +/A << /S /GoTo /D (ttbxcustmtlpltt.onchange) >> +>> endobj +1884 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [367.89 217.954 422.463 229.909] +/Subtype /Link +/A << /S /GoTo /D (ttbxcustmtlpltt.selectedcell) >> +>> endobj +1886 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [440.767 142.855 495.34 153.703] +/Subtype /Link +/A << /S /GoTo /D (ttbxcustmtlpltt.selectedcell) >> +>> endobj +1876 0 obj << +/D [1874 0 R /XYZ 109.858 727.97 null] +>> endobj +1877 0 obj << +/D [1874 0 R /XYZ 109.858 645.51 null] +>> endobj +1878 0 obj << +/D [1874 0 R /XYZ 109.858 519.749 null] +>> endobj +1881 0 obj << +/D [1874 0 R /XYZ 109.858 398.837 null] +>> endobj +1882 0 obj << +/D [1874 0 R /XYZ 109.858 314.085 null] +>> endobj +1885 0 obj << +/D [1874 0 R /XYZ 109.858 207.549 null] +>> endobj +1872 0 obj << +/D [1874 0 R /XYZ 109.858 133.833 null] +>> endobj +1873 0 obj << +/Font << /F29 416 0 R /F54 713 0 R /F22 363 0 R /F41 556 0 R /F8 369 0 R /F28 380 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +1890 0 obj << +/Length 2809 +/Filter /FlateDecode +>> +stream +xZKsWV0恗S9{*q` _~ 0(u*r"j^ktѫ$a*E2xxԾ^\m~ >Km-r?\Ur&}(`N̤Y' <Ӧtؤr"gR*̡&s&T_4(*.˺~+n?v0te$PzCMt2YTfF/4 s;ZyDv _Ct4][Տ26YzU>X\]?V꙲0yMEa2X]S;dar(D>]]Z*TˮW]8(nP;']/0eS?C#aauZ8R{-'Qt(g}Mˍ~~|V*(Q$,5h>ChB>9$Z*QYhΠl*St[tx'8b[>hk68n4Q/1yhrN,74}s#WPJ!ϋvt,]&uU?N2#f,!20Ճ&0.6-Z%yЍCIm,meje.8mȦmha4/4[U4Oe_)NȂQUv ?7ip1%AĤ(Վ ;d˾3&Ry,cp#WPړSBdmYvH7'3,Oǩ +u i);d}9Pq GN俢gӁ3:4Tte>CI8y=!ObLSs5`kjݢE;@lBٚ'ڽi*kD:U?Y* eMd> fmB>&3F:淈g{S:$dez?! bm₨se<0-m8-ՠ Y7,VL0E޻"E,{F[Rue<m U93:CoHqoj Dw&t [sס3Rw۪.`kzz/ 1JxKNn13X}Dox F06cP{u>c:KAPŝȟAqv30탘sLts^̡= q>AGvFȮ#:w ;=NM aX1%u?&[8־dlH$%?4T6<ے?zٰFRRx0il(Vd{Zz(n.z!:\ T&%hjTF~99ێ0Zmx5CRH\`2b}JX__9dLCtox12e[ +"ȡ(LP-˃ G؁̅ i8@ereT *ikt H+3:X[hSdhe]v `>_-Y[{ +:1ky9mf7 Q|Wv혝D~bkHf F/,lEɇowԯ_.Cv%V.& +?* lt"ʲKt^-h ;$8F_1wo1N3`tQ2UNlgjR]^T{) +0pr2 ^ zqxo1XyqqZf X[ZR7k؂Q>>#LnA' vWM'cwd*Z< +9F\*4y dx*pllEwe4yܟuі~9 nqPPx:o ]v|бnƋĢnK 2=o +{>j~Q x-qj%)=!=診e;0h4r? +h9`/5X_9/zR+;+╪C X!&ZРPjQ=w^m[()VK_~D*|Urn>C0hn+iE?Qz ++o? zhY36 Xdb9 m#V .1KUpP4y:JMy9w; )wNUG8-nby7%୿{ 7(҇X)Gu}QF*78~O.`j_ԑlC!*șG ̂d=#.OOʅKi +ISr2PmE X-#%qZYgF:LE' [f{>#F aM:ߪA"Ȟ:Np^WR٦~ 3_p۞6;.endstream +endobj +1889 0 obj << +/Type /Page +/Contents 1890 0 R +/Resources 1888 0 R +/MediaBox [0 0 612 792] +/Parent 1833 0 R +/Annots [ 1892 0 R 1893 0 R 1896 0 R 1897 0 R 1898 0 R 1899 0 R 1900 0 R ] +>> endobj +1887 0 obj << +/Type /XObject +/Subtype /Form +/FormType 1 +/PTEX.FileName (c_ttbxtoolpalette.pdf) +/PTEX.PageNumber 1 +/PTEX.InfoDict 1902 0 R +/Matrix [1.00000000 0.00000000 0.00000000 1.00000000 0.00000000 0.00000000] +/BBox [0.00000000 0.00000000 15.00000000 15.00000000] +/PieceInfo << +/AdobePhotoshop << +/LastModified (D:20030406201212-05'00') +/Private << +/RoundTrip 1 +/ExportCrispy false +/SaveTransparency false +/ImageResources 1903 0 R +/XObject << +/Im0 1904 0 R +>> +/StandardImageFileData 1905 0 R +>> +>> +>> +/Resources << +/XObject << +/Im0 1904 0 R +>>/ProcSet [ /PDF /ImageC ] +>> +/Length 1906 0 R +>> +stream +q q 15 0 0 15 0 0 cm /Im0 Do Q Q endstream +endobj +1902 0 obj +<< +/Creator (Adobe Photoshop 7.0) +/CreationDate (D:20030406201212-05'00') +/ModDate (D:20030406201212-05'00') +/Producer (Adobe Photoshop for Windows) +>> +endobj +1903 0 obj +<< +/Filter /FlateDecode +/Size 2616 +/Length 1907 0 R +>> +stream +HV{PTU?g>ee_)"!4Y@ԴP>.e/EIPiƑL315|de+m|Z3 shv9η|g3 +ţGe !>ئEXQh,шHeE QQO'zٍ|0Y(4K(^uÇA o91Ő 'gmx`>EC8Dϓ^Z`AXf}(++I'n@DŐET.!TȨ%ģb)V]e&~/M+9dKY~&G6~kvy_W>nw<JwФu._KScצ5?4 /Z}8w}}Ԟc/vg՞{XM7%YKI߬iDdlRK ܕ\5GHc}$W7<5B 5_ÀD86L | +:U|Ah 2^q/HBCX0 񙆴!hB_|@y, Q0~ S(M +QrdQ(w 0zendstream +endobj +1904 0 obj +<< +/Type /XObject +/Subtype /Image +/Interpolate false +/Filter /FlateDecode +/DecodeParms << +/Predictor 2 +/Colors 3 +/BitsPerComponent 8 +/Columns 20 +>> +/Width 20 +/Height 20 +/BitsPerComponent 8 +/ColorSpace /DeviceRGB +/Length 1908 0 R +>> +stream +HTDP5b $-_1@gi%BAB!y{fn"$f=w;{>.cUvi~neI |].?Wf^npGXsG endstream +endobj +1905 0 obj +<< +/Length 1909 0 R +>> +stream +endstream +endobj +1906 0 obj +34 +endobj +1907 0 obj +1458 +endobj +1908 0 obj +310 +endobj +1909 0 obj +0 +endobj +1892 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [237.993 636.465 305.213 647.314] +/Subtype /Link +/A << /S /GoTo /D (ttbxcustmtlpltt.paletteoptions) >> +>> endobj +1893 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [145.199 596.006 202.632 605.083] +/Subtype /Link +/A << /S /GoTo /D (ttbxcustmtlpltt.paletteoptions) >> +>> endobj +1896 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [108.862 258.123 187.316 266.242] +/Subtype /Link +/A << /S /GoTo /D (ttbxcustomitem) >> +>> endobj +1897 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [108.862 236.205 215.095 244.424] +/Subtype /Link +/A << /S /GoTo /D (ttbxcustomtoolpalette) >> +>> endobj +1898 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [120.485 142.111 211.726 151.023] +/Subtype /Link +/A << /S /GoTo /D (ttbxsubmenuitem) >> +>> endobj +1899 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [359.596 123.238 444.251 134.086] +/Subtype /Link +/A << /S /GoTo /D (ttbxcustomitem) >> +>> endobj +1900 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [401.754 94.346 516.435 105.194] +/Subtype /Link +/A << /S /GoTo /D (ttbxcustomtoolpalette) >> +>> endobj +1891 0 obj << +/D [1889 0 R /XYZ 109.858 727.97 null] +>> endobj +1894 0 obj << +/D [1889 0 R /XYZ 109.858 597.002 null] +>> endobj +1895 0 obj << +/D [1889 0 R /XYZ 109.858 493.656 null] +>> endobj +762 0 obj << +/D [1889 0 R /XYZ 109.858 386.824 null] +>> endobj +346 0 obj << +/D [1889 0 R /XYZ 109.858 376.325 null] +>> endobj +1901 0 obj << +/D [1889 0 R /XYZ 109.858 83.387 null] +>> endobj +1888 0 obj << +/Font << /F29 416 0 R /F54 713 0 R /F22 363 0 R /F41 556 0 R /F8 369 0 R /F55 716 0 R /F34 719 0 R /F28 380 0 R /F50 672 0 R >> +/XObject << /Im41 1887 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +1912 0 obj << +/Length 1679 +/Filter /FlateDecode +>> +stream +xڽYMFWpDUf9w7vbdUJdPy>b|X<ѯL`:)Rg[F~[P`$!lУ~H2?q4")8|x" +CF%qH(uM'IQ(_ܫ}{xI B3Hxk8LINz*X/$OR˜$x,|5Ln7 > "WR&׋z*1Mf&/Id\sȜM +7bYz-jΈ$+baH*0rf=0O,vvIݮjK/dG]*~<-FWb YaZ h6 ă0pPb.Uc ц({.`+۷Mm!`,YuP9& CL>U*q'T宴Of|`KlS:X-[!mPX2qnNfv8Kn7m/XCѪI^*Fጢ']QUtP+: S{SA/<oaAuUnZq@YN +F̧Ae{4fǟh 6fDU%tg__.{% +k*e3:쉒DMD e]!u)#Qÿ9v} ɛ%( ,Hm9@v%fV)B-pLF\ƻj*<[ؗew\]K3ZJ}?JpN9 $VYUU9U' CUMCU5֯~+W+iM^]ɀ"Vt6xbK3@v%fV)B-pL~\~hձooSڻX++|17Q{7\Z9{@v}%fV)BpL_ob¸.6 +t:SUݺ=lj\ +qlcDk@tû^0}|\[}e +e=JIJ߫-λ:;AL0I dO&oP'o@8<=^[dfD)(q"̎|]׆s} 1錊']EUqP8 STFָg x)iE{nqfϊlnճC `ޯJޛwHͪȃ*qETRaW k>f.*C‘||[_{ ,.;iG̚{TBRILX2\dWJbf"J ǔ2ĖHMٍjԁVЖ{*,:QGrVFτ'}i zP]8'M[ g%TT*$OH:n$JG3%] 1.".3 ]?:tLg.Qh'LfU +X +Ss&;Jou)|kșoqw aESȷ+xU_}METN $dSl d ҇R_CF~:C7g鋒E8T٧+d9 ^A$4̷'%׿nԌ?endstream +endobj +1911 0 obj << +/Type /Page +/Contents 1912 0 R +/Resources 1910 0 R +/MediaBox [0 0 612 792] +/Parent 1833 0 R +>> endobj +1913 0 obj << +/D [1911 0 R /XYZ 109.858 727.97 null] +>> endobj +350 0 obj << +/D [1911 0 R /XYZ 109.858 703.064 null] +>> endobj +1910 0 obj << +/Font << /F28 380 0 R /F22 363 0 R /F20 385 0 R /F14 372 0 R /F8 369 0 R /F29 416 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +1916 0 obj << +/Length 2493 +/Filter /FlateDecode +>> +stream +xڵZێ}$%@|kzXGHIQ!Oߪn_?ׇ + dM*1^ȗ+2/LVb}{yZXO @>Po +x(a? >?<ˣ6֒0 \] >V}E (.̷6#??#3PN#^]mOpmx}Z쾅\4'R +d0Ni3BRڱ+ۖӨ`RcO-p?wEك4̱<چ>?|?8޾#@'1.V/ȋٽ$5B mr?R=GЩ'b>Myİh |FcG;f1[,E6B~Q^)~Fh^[NR%l,01r[͐/+D&Ϙ- l7#/  +KUBРηsԟEbB(/TFdIzA=P%By2)Ԕ랦,0͗3lZ=˥la.Jf&4Kb<ߔUXI<,k]NK!٥$S5B)$ƷO,Aj "1zPJAY33R@O\ױH{D4/d)q@p>Ga7jT9% d70NC!3B!!ß<ڒ+^*Y=|6^;Pv +dW0N53BR۩mdv(eg _2,J"-PlgC#P8jfVD?[S"e(8pM;Gskҹ9{4;]gJ8xȳ͊w#V493RtÉi'oY&!Ӟ5Biόdgob"pmU h5.IݴkLkRIcᄏuG+lz`{x²ΰoz^ZuMi&x@X/Y +cu .3؄36٢B mG~jJ`HupߙzwnY+ao1k6j&'q]ܡlC|*qh_b'\/n78^av߲Vd8 %eOy/EEJm!$i|>N U3*T+_!Gيȱ;^fٽ!Ӝ5BΌdN*B戙s!_[) ;p +8GAM+{"֌ئW>G92~q]Ax~I45,",愆^bl}/Ho_-Uc9m0nHa.aJAf&A4eJ+@Ĉ/\ѡ@v1cP1#4.( +; $[mfT[%⽒L^Kg Y^ /AkҌ eze-'1?p^j&,_-2FK6YxTUC}.;%|:?ˎĕ*z$8ۘv ~[DǓwԚ.[=jjmn "Fa!@W>b;uƪbD4wG783uwߩ:\=W]o|Wendstream +endobj +1915 0 obj << +/Type /Page +/Contents 1916 0 R +/Resources 1914 0 R +/MediaBox [0 0 612 792] +/Parent 1918 0 R +>> endobj +1917 0 obj << +/D [1915 0 R /XYZ 109.858 727.97 null] +>> endobj +1914 0 obj << +/Font << /F29 416 0 R /F14 372 0 R /F8 369 0 R /F20 385 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +1921 0 obj << +/Length 2672 +/Filter /FlateDecode +>> +stream +xڝZ[~_Y;47g;7֮}`n44tV~|Υ(.Id@ա\J8*r#;VӅ:?.xŽc9;DNYm\;:='ۍb\\_SsJ/jCJ&ϊᪿj{[7Yq%%vu}LC֬tqk Ƿ̩JvcwxX>Ly0|;u7azC_%!7$\XqWJw#WboePʼ ~{综|RYTGS_3*O0M~1͵^1b?ň v !4%ĈY@ň!#L~,o)%cdQ_)iKMxBR];HuBӪ2Ԫ;vy #@ařX2Y-Z#䫪-ޠx>R8L+H[ܥUk(A]k{˼U4?eX=chhPμoP+u` =4һ$Y^ִPv$ MC,cPc8SvхfiQ"'zKlβr'rwH=[aQg_t}st YVy+W'&tBf2ff;@ Pzzny,Uk~j_8rj0_eWޝ#K9GS4$xu,ΆK,]J)"m}a7ۀAN X$q"yȯ$/G>r +k#E!6G<8veO(Z8 bcYu2 "KCS^?h-({A {hz8c$B+r*dVҔ B=jMJ,*kPkk8.o2H*Mo sGj:T;}tv4J~+<`Q##ԤK ChZRfQsZ1ex2=uJK *&xB<+cm8xa~Sb;1pv!U1r | licum +"]yRP15/3%۾HՉ[m^0j1 ŏ'd(%ȹȩeVU>`vRBT2KTĻlzxRّSrsT=JoSdY#&&se սœq&_!t}a*#K3)#YH~g*m~{:H`*1]A' L5JژY!Sk}`נw2+)ўYNv17 +:^1)ӂ6uʑO Zz?q?'n]NPؓ⹶x M{Y9@-1o1ӺKs,d%U79R:'xIoW|@K]7i>@}=K-10Q$U Na' tNc%{ K>CSJslzAg3AďNhRfs1~x9]k֦O|8J9>o0ҚxVg{_GΦGƯ~N#|/BӴL~m6S7A!'Z,$~fnap0&IdH0 H0!7LX䪧WǺU[S48w53ܙ}Cycڝw u T bKD<>].~l3@$1BY,p +&떀?8=sCT->T/5yG'KNhZRfQsZ1xWW|V畺 ^Nu)V ]*#|_g]F$\^Q9;$UA W)R.ё7 Ukִ"݅d "vAfY3 AC*kSaN,:`LZ'3%)94ڈ JwͿfriKU@\ m`O~2oPI嘓cendstream +endobj +1920 0 obj << +/Type /Page +/Contents 1921 0 R +/Resources 1919 0 R +/MediaBox [0 0 612 792] +/Parent 1918 0 R +>> endobj +1922 0 obj << +/D [1920 0 R /XYZ 109.858 727.97 null] +>> endobj +1919 0 obj << +/Font << /F29 416 0 R /F14 372 0 R /F8 369 0 R /F20 385 0 R /F11 520 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +1925 0 obj << +/Length 2220 +/Filter /FlateDecode +>> +stream +xZr6+T5B{W8㎓&q*ɂ2iIPTN܋ EtW>pAO<, I,bƓ7YAϿ.B}Β~bek c&s$E.~՛070*H~{Ld{)q7ߛY/bI+yŻ"D!`<^gUva^I!=t KB20\3rCX!ΣgfA< L~x|8'\ +sFX|8 +O._g|:dZduٜO l + ^i>[nj'L8DG5uMӪDz5dE-\ ,) +TH,(Bhzqs 3.g?]~0 >9Kp̷si O3D) ݝ\5&;3!Mn.P{|"F +5[qdo{,343%Yl`'t\źJ'aYOp"΄pD ,A:f/Z[f&1:u<!F k1]cE>Q4鵼sxԋՕ, ⾬:R-Nz"Y-WxA@^0N 83Fh!3w2/r媨#f9efZՖo6,(Y@8\ 1.uF :]ul +tSk;=4l={_aY-а i1Bca ,>LRa<̖\-zc֔в,7xiŁТ k0N->-,hN?Ul=z]ەs>BeX^=}BGnj+#>58dmAò*S1B#kOVC BF=B3AŻ*m|ZWmqZ+= n*ũ$調/Wkʷ7Z]6@1`*$uD4Ƹ5J%17e|z?KiD!ߨhVb-@F،l}d+ṡaRF?,}4)\0-Zа +Tc!{_JS§w2> i&|! CbYM }lb8bq:"L߭ LJ]nrR1=>cZf΀L|ٖtc"v Xc\%;5Hre%;4͆:ͺ PS"oO&MZdkg#P7^åKl6dZlsf-KuXX6k +o9h77N&](v ־2SkaPkw؟&[JiK)Iuv_^HS{ ꑔ~ي]Qg2' i*D k0NM>M->KȻަΦ[ 9U'PPk)96"KX:Xa)C'zF,JU[g "&,v .ش-UxGf@b(S1B#GOÔⱤ#?=W7<=#n&t~#LpTŮ=5y@Xg''2 tXL xx"y)v6gs?zNŧ|=&7j8樣6T 8iSϟ,G7O Ρkۥ<;,gղRٿf泌9nTxG=(}7նCV;PE+,fZ1zꮟ!9-Р95eQBm.a9m7YT+nQÆm.yov88ׄܜldzq#yƠ8X_jGQ) ݇AÄ!՗68 3Fh !3w^/*,Ǭxz}vccsȫ!}X%Qa:;}:Z|:vْ$ؠXE- 1 WIoPcFaGr^+M$ ë NWOz#Z> endobj +1926 0 obj << +/D [1924 0 R /XYZ 109.858 727.97 null] +>> endobj +1923 0 obj << +/Font << /F29 416 0 R /F14 372 0 R /F8 369 0 R /F20 385 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +1929 0 obj << +/Length 2491 +/Filter /FlateDecode +>> +stream +xZMs8WHUY=N&kT́he~hH*/A$f[|h4+wS*bƫ]uW\"6>gI"X +|< ci_~sW{V&g2/HWŰY.{xz5 CYw靗}\Il8wǬ>퇫[wpI*KXEz)sDŽIp1E@4m,ҙu7Q3r= R1 =сFW/'5ļ"L >18 +G|7k/q>h5ws| 7hݝ+ ("i ŋOgg<Zm첦.ksbם!;y^A53s +ǵV $[+Uב 3ϳXYcLشlS?NQJ!A~=gM !^*s>˿}WQZd@:JU%Bᔔ >W#(#'{(s$pYuCj˘ wO)ӎ Ȕ-j̼~ʷM7q+]SRiGB͙ +Yù#};p䛶N|p1ڨDʬW0evٛZzb1, F_$#t-q4Bm\%=*_yw 9!3t% @vg\,H,/9"K 38PæUdjڢP".NOjÂ!Ҁ8c%K?xHo*)qK0 +,v@v]].b%T[crÆ )ǼNPUr iNXe͈uI40[T_d +̹@=O!)K; R5(1V;.j;^Nscj`??(BYAL

asL fe{N=J/HmtK/1VS|{A ָg._Φe|enhSL ;>y5=3U^i\gs} ȗ%[Y[+֋֗6aUYpuJAz9U +~((>ޫ#)|<[Ǫ~@Z񜊦*SaNl·#a0,'*G qެ7R_Ū$i:X'@~!1VX"~qA8!Սl. RJz;Q=xM|)EZHalZ$T$rarPl 3LQ1gNsea< +{[5n*{j(xF%O +0 ǀ#n-aOEHdX0"v2#y mTw9J(tl2EbDpQ j:yZǏ`(ΐؿ:z+)v;uΙː p )1V!SB|:Νmn,/?=lu +J=L &? 4~b!kZb м-$j%Bm )[|tNY4ýRao ^Y}\rtFB>iWeAC_&:Ʈhw"=h٦Y> endobj +1930 0 obj << +/D [1928 0 R /XYZ 109.858 727.97 null] +>> endobj +1927 0 obj << +/Font << /F29 416 0 R /F14 372 0 R /F8 369 0 R /F20 385 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +1933 0 obj << +/Length 2139 +/Filter /FlateDecode +>> +stream +xڭZme$VDݻ+HAkkmHr hZ\qY&geʰHUW]CDlb_]$Tjg*lSݿb:0Q )VҜdnAWhSt<9 4<*KW%BE8$ws><2] OK+ea3X-xZ"bYsb|5[m*D{EAi+sBԻFvj8ݭP6œB0';kfrY<<@n HK Me> +Wzh +iG=v/ }ߟĒ2^6rJa|Z$T gLey2OgbI{S [Dձ1nnGv88 +t?lcO__tW*Bb^THtP9E;)zřdmzb=3zı+QS|plGaTxX6x D m8BjJ|i&AZdG8L '-oF>.mY2_9cJW%BE8gimV}TݪNrglC"/|)\*y}A%:8 Qc&0@NC)PP6ጡL>P"o޵fd|RP 304 ivg5*q&*,Se Vɣ*UU&*E8gK7񚽺C2ӥC3*2Kvl68p[G|K>JOabJW%B-E8'w٫:_Q?'pPWݥٔzUT. \&[.ʵD2nz|RW(U7G1u +JHĮӾ6݇qGsߤN@.ŗrGbY"cY;g\]BwAFGP.]u5@iTӯp?DQ fF?@$Zϕ067p y&j[1X4|&d'h۟sƫ +Ҥ/>&Gcg{IX\,k +EBk6ጯ|{v_ά?Xa[.uXԓ :UgPcΩc=Te^~w^5'>g[5!˟ +_kendstream +endobj +1932 0 obj << +/Type /Page +/Contents 1933 0 R +/Resources 1931 0 R +/MediaBox [0 0 612 792] +/Parent 1918 0 R +>> endobj +1934 0 obj << +/D [1932 0 R /XYZ 109.858 727.97 null] +>> endobj +1931 0 obj << +/Font << /F29 416 0 R /F14 372 0 R /F8 369 0 R /F20 385 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +1937 0 obj << +/Length 1433 +/Filter /FlateDecode +>> +stream +xڥXَ6}WQ*V\m LIela,ɵND˒`D< LGdq,%ymUaՈSe13@t~@F^H{Kma0K 0{J9aiߏUXKl aKaٟ7,ã<~_ޮ^?kH% d.#y _r]fɘ+)a"!c!$K(I h!*6qC w9ai=k[B!,>pW|:>{ +BιxjnMu*:/%?]2yYMh^qD1"{qS +!J63tJYv(lRx +/^W~ՃNNYEc N9z5٦pnnUo?~s#5g>6(سuM: +E+xB@sHn^v w>K#)-wJzVx. |(keZn !5y0\ڲHȸO .(F5-~' *a*r" +⌓eYYddc |cgG!ZnHQ&C .h 7DŽCUߪԪ)㫵&QY_!RXlge$ u>eK#)-[_Ӟ!oK Gn96mZ_`;L]S3~2XcG3K֕GbCb:[]p ՕTZȖkfk0.. 'k,b`VQ՜`#"U±t`T0Կ;1j]9Y +b{5kT3ȹQI/sendstream +endobj +1936 0 obj << +/Type /Page +/Contents 1937 0 R +/Resources 1935 0 R +/MediaBox [0 0 612 792] +/Parent 1918 0 R +>> endobj +1938 0 obj << +/D [1936 0 R /XYZ 109.858 727.97 null] +>> endobj +1935 0 obj << +/Font << /F29 416 0 R /F14 372 0 R /F8 369 0 R /F20 385 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +1941 0 obj << +/Length 4968 +/Filter /FlateDecode +>> +stream +x]YsǑ~#MJ! #D`AXf5uM)ba +$@VU֑v[*{aWs,HHo-oNr1yQ}o6_A$|6clbZfZ狿}߼|\_HËw/WLJ/qfeDr1{u${&N=JwŃ/]qҳg SmbGk⪰ɏ CiK!yxƂ?~İn2جPE%-kN]j +nWvYg?̂v2*0lo9~5 +VVq`mCADC. +D 2(X'뇻Ή}l9)'Z%[qR0=r"Wiݾ{x<:*0f˴SmX†v2 bykl2d (@H‚6 ,dh>3"͎lȠlȍgCn0m)mSxis~ܚ(!p:#JnWU9 + hR PbH3<3k<8tӻrBEK$Rk{AZd/ %YaC[k{R[ 5CWǛX*sEːbfV9<13n̍׍ úЖ*^ɝfƇں-Smd XaC^.fҚAGKknxim.Z'.:CķWzAʒʵe^\ОWzR[ӯ(tO=$mB5 J;dHm15뵼<ڟl*| " {iV{i2 +11#67̀8 0 ,! BH # >*\KCSЌ CjI!>#PhFfv 5ƪRདྷ yoMy8J0[ 2hd.5/lh /CjxK=6<R3A{dHeO[+g=$iB>8xY̵28H-ˎ03`XU`ܿ}iv<ɠ!'! 7!em.^_ l-}C$ٲ)[˒}p0Y:JWZ ՙw;طG2hCΎ{WS{2gp-\$M؝ÝSi,p!_a1<20@IHytFmwqSkn@{EU1V F{y<Gǩ¥z2W:t3eO@\}|ÐPt5Q|2gFpr ԄEar{RDRE5{*Oh|tL/ER[ӝ8Z4bwoZlP{Imh ;..zIP _2K:eHm<]mQnZ>=Iut1e(m)or\Hf)aSw0T!kqC)%/Nx +pY=,=9Iu, ՟eHm19acw9F]3%O°; +#=)ΗRؐ)7D$S{܅)8QVK&0{H҄ VumѦ ?Σ$ځ*~0$lqQ!TpM<1EዿkBp;Óv1;"D ^(CisDJ]{_=ͮ 8ՎnjvWr/ +F2`t-HI.'X;q"[dWxlI[P;oy;sAV vx 8 s)EEJ[uX2;bIPa20~~6lw8 iJvQVr^$Mݑ@;Y+&Zi ; Gg +@Ҁyۖ6?@RY6w6dwD[C;dHmOςY#4bw7DgNAUtUu۽Hڂyb^ ;\gH҄MK yAVKw{vDR5x.Z l!*bIP;m[i -?V'P{?^PTz:",RY=I?QҖ"i1B͜IuRBO(CiK ׿:uFѲTy_1lX2G|G VmI ]feV=PRHFOXiԬTy>*{?@uGJ[^Ŋf$o09! S_E&/C)K!Rffqc%-GN}K6ڀ벰} -I*o-xaMmG(2h%g\U +'(ԕ>Y.ķo1[MHc X rʠGJ˪ +2K OG0 ݬg-a)a)GR҅ mX -eYg&,x?gݩ<Ӂ*#Qm %gJ̕YPbHj`OR(<Ä# ڞ<)(B[KQ)maD)m>}W mue(m^5Sx +3Sd-&[2h{ S8%cdfC{ eHm1Ycq{ $HfYPQGIRzɻf&VTKy m)=`_?e\s$ {|$Sm'ђ} י $e(m)MpٱΠpnx?0Rv,}6|Ya°ķz[afpSkZ +†6ʐBv_bwl2h[މS6 7{Cf=yE\IhGNM}:؊! +2:v2:Lr"u2Ʃ3֖RvH".B'G\N-]ubڲNyAudl|suː*3=q8 iJ~k h+ (e6z#"Ͷq)E>v V(CiK!l^ 9N"Ӏ ? ȍ4UX)`6ΕLbSmÕa642"E\4Qh3t8j2#Q05cm1Eگ0~֭ʹb1Do=83tebO]@J\֤ARU KZ鷻{P2L˔Y~uL]0eʬ 47cMɸx=D]G9fendstream +endobj +1940 0 obj << +/Type /Page +/Contents 1941 0 R +/Resources 1939 0 R +/MediaBox [0 0 612 792] +/Parent 2054 0 R +/Annots [ 1943 0 R 1944 0 R 1945 0 R 1946 0 R 1947 0 R 1948 0 R 1949 0 R 1950 0 R 1951 0 R 1952 0 R 1953 0 R 1954 0 R 1955 0 R 1956 0 R 1957 0 R 1958 0 R 1959 0 R 1960 0 R 1961 0 R 1962 0 R 1963 0 R 1964 0 R 1965 0 R 1966 0 R 1967 0 R 1968 0 R 1969 0 R 1970 0 R 1971 0 R 1972 0 R 1973 0 R 1974 0 R 1975 0 R 1976 0 R 1977 0 R 1978 0 R 1979 0 R 1980 0 R 1981 0 R 1982 0 R 1983 0 R 1984 0 R 1985 0 R 1986 0 R 1987 0 R 1988 0 R 1989 0 R 1990 0 R 1991 0 R 1992 0 R 1993 0 R 1994 0 R 1995 0 R 1996 0 R 1997 0 R 1998 0 R 1999 0 R 2000 0 R 2001 0 R 2002 0 R 2003 0 R 2004 0 R 2005 0 R 2006 0 R 2007 0 R 2008 0 R 2009 0 R 2010 0 R 2011 0 R 2012 0 R 2013 0 R 2014 0 R 2015 0 R 2016 0 R 2017 0 R 2018 0 R 2019 0 R 2020 0 R 2021 0 R 2022 0 R 2023 0 R 2024 0 R 2025 0 R 2026 0 R 2027 0 R 2028 0 R 2029 0 R 2030 0 R 2031 0 R 2032 0 R 2033 0 R 2034 0 R 2035 0 R 2036 0 R 2037 0 R 2038 0 R 2039 0 R 2040 0 R 2041 0 R 2042 0 R 2043 0 R 2044 0 R 2045 0 R 2046 0 R 2047 0 R 2048 0 R 2049 0 R 2050 0 R 2051 0 R 2052 0 R 2053 0 R ] +>> endobj +1943 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [214.577 605.253 226.532 616.101] +/Subtype /Link +/A << /S /GoTo /D (page.25) >> +>> endobj +1944 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [160.336 593.298 172.291 604.146] +/Subtype /Link +/A << /S /GoTo /D (page.30) >> +>> endobj +1945 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [176.386 593.298 188.342 604.146] +/Subtype /Link +/A << /S /GoTo /D (page.45) >> +>> endobj +1946 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [192.437 593.298 204.393 604.146] +/Subtype /Link +/A << /S /GoTo /D (page.56) >> +>> endobj +1947 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [208.488 593.298 220.444 604.146] +/Subtype /Link +/A << /S /GoTo /D (page.68) >> +>> endobj +1948 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [228.192 581.342 240.147 592.08] +/Subtype /Link +/A << /S /GoTo /D (page.30) >> +>> endobj +1949 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [202.954 569.387 214.909 580.235] +/Subtype /Link +/A << /S /GoTo /D (page.56) >> +>> endobj +1950 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [215.739 557.432 227.694 568.28] +/Subtype /Link +/A << /S /GoTo /D (page.68) >> +>> endobj +1951 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [213.331 545.477 225.286 556.325] +/Subtype /Link +/A << /S /GoTo /D (page.45) >> +>> endobj +1952 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [199.079 533.522 211.034 544.37] +/Subtype /Link +/A << /S /GoTo /D (page.30) >> +>> endobj +1953 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [228.192 521.567 240.147 532.304] +/Subtype /Link +/A << /S /GoTo /D (page.30) >> +>> endobj +1954 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [171.225 509.611 183.18 520.46] +/Subtype /Link +/A << /S /GoTo /D (page.32) >> +>> endobj +1955 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [240.922 497.656 252.877 508.504] +/Subtype /Link +/A << /S /GoTo /D (page.32) >> +>> endobj +1956 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [192.437 485.701 204.393 496.549] +/Subtype /Link +/A << /S /GoTo /D (page.17) >> +>> endobj +1957 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [217.538 473.746 229.493 484.483] +/Subtype /Link +/A << /S /GoTo /D (page.17) >> +>> endobj +1958 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [156.821 461.791 168.776 472.528] +/Subtype /Link +/A << /S /GoTo /D (page.51) >> +>> endobj +1959 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [255.866 449.836 267.822 460.684] +/Subtype /Link +/A << /S /GoTo /D (page.51) >> +>> endobj +1960 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [178.324 437.88 190.279 448.729] +/Subtype /Link +/A << /S /GoTo /D (page.48) >> +>> endobj +1961 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [231.735 425.925 243.69 436.773] +/Subtype /Link +/A << /S /GoTo /D (page.48) >> +>> endobj +1962 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [164.071 413.97 176.027 424.708] +/Subtype /Link +/A << /S /GoTo /D (page.35) >> +>> endobj +1963 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [250.94 402.015 262.895 412.863] +/Subtype /Link +/A << /S /GoTo /D (page.35) >> +>> endobj +1964 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [161.193 390.06 173.149 400.908] +/Subtype /Link +/A << /S /GoTo /D (page.35) >> +>> endobj +1965 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [250.94 378.105 262.895 388.953] +/Subtype /Link +/A << /S /GoTo /D (page.35) >> +>> endobj +1966 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [135.29 356.187 147.246 367.035] +/Subtype /Link +/A << /S /GoTo /D (page.15) >> +>> endobj +1967 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [196.782 344.232 208.737 354.969] +/Subtype /Link +/A << /S /GoTo /D (page.15) >> +>> endobj +1968 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [161.913 332.276 173.868 343.125] +/Subtype /Link +/A << /S /GoTo /D (page.30) >> +>> endobj +1969 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [177.964 332.276 189.919 343.125] +/Subtype /Link +/A << /S /GoTo /D (page.37) >> +>> endobj +1970 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [228.192 320.321 240.147 331.059] +/Subtype /Link +/A << /S /GoTo /D (page.30) >> +>> endobj +1971 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [227.445 308.366 239.4 319.214] +/Subtype /Link +/A << /S /GoTo /D (page.37) >> +>> endobj +1972 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [148.021 296.411 159.976 307.148] +/Subtype /Link +/A << /S /GoTo /D (page.29) >> +>> endobj +1973 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [231.707 284.456 243.662 295.304] +/Subtype /Link +/A << /S /GoTo /D (page.29) >> +>> endobj +1974 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [162.965 272.501 174.92 283.238] +/Subtype /Link +/A << /S /GoTo /D (page.35) >> +>> endobj +1975 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [250.94 260.545 262.895 271.394] +/Subtype /Link +/A << /S /GoTo /D (page.35) >> +>> endobj +1976 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [167.392 248.59 179.348 259.438] +/Subtype /Link +/A << /S /GoTo /D (page.30) >> +>> endobj +1977 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [228.192 236.635 240.147 247.373] +/Subtype /Link +/A << /S /GoTo /D (page.30) >> +>> endobj +1978 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [149.819 214.717 161.775 225.455] +/Subtype /Link +/A << /S /GoTo /D (page.57) >> +>> endobj +1979 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [165.87 214.717 177.826 225.455] +/Subtype /Link +/A << /S /GoTo /D (page.69) >> +>> endobj +1980 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [208.212 202.762 220.167 213.61] +/Subtype /Link +/A << /S /GoTo /D (page.57) >> +>> endobj +1981 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [215.739 190.807 227.694 201.655] +/Subtype /Link +/A << /S /GoTo /D (page.69) >> +>> endobj +1982 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [188.148 178.852 200.103 189.589] +/Subtype /Link +/A << /S /GoTo /D (page.38) >> +>> endobj +1983 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [227.445 166.897 239.4 177.745] +/Subtype /Link +/A << /S /GoTo /D (page.38) >> +>> endobj +1984 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [151.203 154.941 163.158 165.79] +/Subtype /Link +/A << /S /GoTo /D (page.30) >> +>> endobj +1985 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [167.254 154.941 179.209 165.79] +/Subtype /Link +/A << /S /GoTo /D (page.32) >> +>> endobj +1986 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [183.305 154.941 195.26 165.79] +/Subtype /Link +/A << /S /GoTo /D (page.37) >> +>> endobj +1987 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [228.192 142.986 240.147 153.724] +/Subtype /Link +/A << /S /GoTo /D (page.30) >> +>> endobj +1988 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [240.922 131.031 252.877 141.879] +/Subtype /Link +/A << /S /GoTo /D (page.32) >> +>> endobj +1989 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [253.791 119.076 265.746 129.924] +/Subtype /Link +/A << /S /GoTo /D (page.37) >> +>> endobj +1990 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [156.738 107.121 168.693 117.969] +/Subtype /Link +/A << /S /GoTo /D (page.76) >> +>> endobj +1991 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [172.789 107.121 184.744 117.969] +/Subtype /Link +/A << /S /GoTo /D (page.77) >> +>> endobj +1992 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [235 95.166 246.955 106.014] +/Subtype /Link +/A << /S /GoTo /D (page.76) >> +>> endobj +1993 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [247.564 83.21 259.519 94.059] +/Subtype /Link +/A << /S /GoTo /D (page.77) >> +>> endobj +1994 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [357.457 605.253 369.413 616.101] +/Subtype /Link +/A << /S /GoTo /D (page.15) >> +>> endobj +1995 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [373.508 605.253 385.464 616.101] +/Subtype /Link +/A << /S /GoTo /D (page.47) >> +>> endobj +1996 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [389.559 605.253 401.514 616.101] +/Subtype /Link +/A << /S /GoTo /D (page.74) >> +>> endobj +1997 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [415.462 593.298 427.417 604.035] +/Subtype /Link +/A << /S /GoTo /D (page.15) >> +>> endobj +1998 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [426.227 581.342 438.183 592.191] +/Subtype /Link +/A << /S /GoTo /D (page.47) >> +>> endobj +1999 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [436.882 569.387 448.837 580.235] +/Subtype /Link +/A << /S /GoTo /D (page.74) >> +>> endobj +2000 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [371.294 557.432 383.25 568.28] +/Subtype /Link +/A << /S /GoTo /D (page.75) >> +>> endobj +2001 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [436.882 545.477 448.837 556.325] +/Subtype /Link +/A << /S /GoTo /D (page.75) >> +>> endobj +2002 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [395.398 533.522 407.354 544.37] +/Subtype /Link +/A << /S /GoTo /D (page.75) >> +>> endobj +2003 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [436.882 521.567 448.837 532.415] +/Subtype /Link +/A << /S /GoTo /D (page.75) >> +>> endobj +2004 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [366.59 509.611 378.545 520.46] +/Subtype /Link +/A << /S /GoTo /D (page.25) >> +>> endobj +2005 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [382.641 509.611 394.596 520.46] +/Subtype /Link +/A << /S /GoTo /D (page.69) >> +>> endobj +2006 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [434.419 497.656 446.374 508.504] +/Subtype /Link +/A << /S /GoTo /D (page.69) >> +>> endobj +2007 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [470.81 485.701 482.765 496.549] +/Subtype /Link +/A << /S /GoTo /D (page.25) >> +>> endobj +2008 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [396.588 473.746 408.544 484.329] +/Subtype /Link +/A << /S /GoTo /D (page.10) >> +>> endobj +2009 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [362.491 461.791 374.447 472.528] +/Subtype /Link +/A << /S /GoTo /D (page.21) >> +>> endobj +2010 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [378.595 461.791 390.55 472.528] +/Subtype /Link +/A << /S /GoTo /D (page.22) >> +>> endobj +2011 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [394.699 461.791 406.654 472.528] +/Subtype /Link +/A << /S /GoTo /D (page.24) >> +>> endobj +2012 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [410.803 461.791 422.758 472.528] +/Subtype /Link +/A << /S /GoTo /D (page.34) >> +>> endobj +2013 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [426.906 461.791 438.862 472.528] +/Subtype /Link +/A << /S /GoTo /D (page.36) >> +>> endobj +2014 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [443.01 461.791 454.965 472.528] +/Subtype /Link +/A << /S /GoTo /D (page.40) >> +>> endobj +2015 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [459.114 461.791 471.069 472.528] +/Subtype /Link +/A << /S /GoTo /D (page.49) >> +>> endobj +2016 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [475.218 461.791 487.173 472.528] +/Subtype /Link +/A << /S /GoTo /D (page.53) >> +>> endobj +2017 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [491.321 461.791 503.277 472.528] +/Subtype /Link +/A << /S /GoTo /D (page.58) >> +>> endobj +2018 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [507.425 461.791 519.38 472.528] +/Subtype /Link +/A << /S /GoTo /D (page.59) >> +>> endobj +2019 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [523.529 461.791 535.484 472.528] +/Subtype /Link +/A << /S /GoTo /D (page.61) >> +>> endobj +2020 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [367.392 449.836 379.347 460.186] +/Subtype /Link +/A << /S /GoTo /D (page.75) >> +>> endobj +2021 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [383.443 449.836 395.398 460.186] +/Subtype /Link +/A << /S /GoTo /D (page.78) >> +>> endobj +2022 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [436.882 437.88 448.837 448.729] +/Subtype /Link +/A << /S /GoTo /D (page.75) >> +>> endobj +2023 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [450.414 425.925 462.37 436.773] +/Subtype /Link +/A << /S /GoTo /D (page.49) >> +>> endobj +2024 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [440.23 413.97 452.186 424.818] +/Subtype /Link +/A << /S /GoTo /D (page.34) >> +>> endobj +2025 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [432.814 402.015 444.769 412.752] +/Subtype /Link +/A << /S /GoTo /D (page.61) >> +>> endobj +2026 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [469.62 390.06 481.575 400.908] +/Subtype /Link +/A << /S /GoTo /D (page.36) >> +>> endobj +2027 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [474.546 378.105 486.501 388.953] +/Subtype /Link +/A << /S /GoTo /D (page.53) >> +>> endobj +2028 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [466.244 366.149 478.199 376.998] +/Subtype /Link +/A << /S /GoTo /D (page.78) >> +>> endobj +2029 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [446.125 354.194 458.08 365.042] +/Subtype /Link +/A << /S /GoTo /D (page.40) >> +>> endobj +2030 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [426.892 342.239 438.847 353.087] +/Subtype /Link +/A << /S /GoTo /D (page.58) >> +>> endobj +2031 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [443.136 330.284 455.091 341.021] +/Subtype /Link +/A << /S /GoTo /D (page.59) >> +>> endobj +2032 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [444.797 318.329 456.752 329.066] +/Subtype /Link +/A << /S /GoTo /D (page.21) >> +>> endobj +2033 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [442.804 306.374 454.759 317.222] +/Subtype /Link +/A << /S /GoTo /D (page.21) >> +>> endobj +2034 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [416.265 294.418 428.22 305.267] +/Subtype /Link +/A << /S /GoTo /D (page.22) >> +>> endobj +2035 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [437.823 282.463 449.778 293.311] +/Subtype /Link +/A << /S /GoTo /D (page.24) >> +>> endobj +2036 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [397.612 270.508 409.568 281.356] +/Subtype /Link +/A << /S /GoTo /D (page.26) >> +>> endobj +2037 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [368.914 248.59 380.87 259.438] +/Subtype /Link +/A << /S /GoTo /D (page.51) >> +>> endobj +2038 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [474.546 236.635 486.501 247.483] +/Subtype /Link +/A << /S /GoTo /D (page.51) >> +>> endobj +2039 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [414.77 224.68 426.726 235.528] +/Subtype /Link +/A << /S /GoTo /D (page.36) >> +>> endobj +2040 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [469.62 212.725 481.575 223.573] +/Subtype /Link +/A << /S /GoTo /D (page.36) >> +>> endobj +2041 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [394.375 200.77 406.33 211.618] +/Subtype /Link +/A << /S /GoTo /D (page.38) >> +>> endobj +2042 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [446.125 188.814 458.08 199.663] +/Subtype /Link +/A << /S /GoTo /D (page.38) >> +>> endobj +2043 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [393.544 176.859 405.5 187.707] +/Subtype /Link +/A << /S /GoTo /D (page.38) >> +>> endobj +2044 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [446.125 164.904 458.08 175.752] +/Subtype /Link +/A << /S /GoTo /D (page.38) >> +>> endobj +2045 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [409.9 152.949 421.855 163.797] +/Subtype /Link +/A << /S /GoTo /D (page.21) >> +>> endobj +2046 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [425.951 152.949 437.906 163.797] +/Subtype /Link +/A << /S /GoTo /D (page.30) >> +>> endobj +2047 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [446.872 140.994 458.827 151.731] +/Subtype /Link +/A << /S /GoTo /D (page.30) >> +>> endobj +2048 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [442.804 129.039 454.759 139.887] +/Subtype /Link +/A << /S /GoTo /D (page.21) >> +>> endobj +2049 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [403.258 117.083 415.213 127.932] +/Subtype /Link +/A << /S /GoTo /D (page.30) >> +>> endobj +2050 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [446.872 105.128 458.827 115.866] +/Subtype /Link +/A << /S /GoTo /D (page.30) >> +>> endobj +2051 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [394.956 83.21 406.911 94.059] +/Subtype /Link +/A << /S /GoTo /D (page.22) >> +>> endobj +2052 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [411.007 83.21 422.962 94.059] +/Subtype /Link +/A << /S /GoTo /D (page.23) >> +>> endobj +2053 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [427.058 83.21 439.013 94.059] +/Subtype /Link +/A << /S /GoTo /D (page.38) >> +>> endobj +1942 0 obj << +/D [1940 0 R /XYZ 109.858 727.97 null] +>> endobj +1939 0 obj << +/Font << /F28 380 0 R /F8 369 0 R /F29 416 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +2057 0 obj << +/Length 5179 +/Filter /FlateDecode +>> +stream +xڵ][s~ׯ#Y nQeKY)tlcyJG>E J"=ƥar2 :TZ|y2\xQ)("wt2Q+m$?9\ku;<듛'\J~r俣w$* +piY +{vS}bKxܟQ~y"jlcsjl )7ڒ`rB`ږ:`SLINfpLںxv6ӿww6Py 뙘OwgTnïi!jDS>kIrHkڍ笈e 5̇u f-I9řb.Vwwj ZB,rHw+;JXL yC /Z H4i!zL#a:顇C G݆f>p20Fzڋ6\`/Knt(nx@ V `:g>dPk\Tm&Dd,U@M:062`B2>?n8q<* C Ds +2󡌅AJP22Qt_>n|r?z-^K`Â,Ɗ\w#3$9Z" :3.=|Fx@ Vڍ[.*2܅bp"-帚IM|WzAQ(t0Y0"]8Cښ8P0‹ # x~:?#Rˠ"8$\Rڰ%'yP0ˠE$VpYdB':x@ #B HAP`"Kg?{}ҫp ;Qgp!Eݶ]HPNqA>Ow2ZME%=ÅC /rPh d0k DdpaW1Ohd9$2̵2˄3,ɠ#0={!Ԁ!x[@tIǂNAQ8 6$OgpE~*ҞW}-le ()FОYN0/$1yP/N5إ$dCs=ua6+5'{Z\cvfKGX͎8tćvGh[!a΍]T.3NF%=rHu\{#t)Pg"8.yqk}_cFC-Yiol{$^0q:7o 7 y޼I}hn !,c/]ƿj0) ,nXjnM #Xjf)Ҙ8øPmSy91'^3k7Uz j? 4,fG ͘ҿ,k[)*1W#E$rTP/XZ{/pRACRL.8nFejm%_\kw%[Z2`b$*Ւ]͔K$V^TV + 25FAl^/DDyCd@b5ku + Z[驎_``D]XiwA +"\Kf_-H܃\{5@A{Ye*譃]ffqJ7v2 4M`$f"ehc@`Ym-F+Ϧ#qV6ԕFG1Lt6 i(}zCl@bk6H9( 25ψJlvuwxѼ%ågհtm9ab*"3}u}̉ii mqOŸd +He0f9WO6_cLjC%n@bά{lm*q5Wk,5Űk$^|{Q-֍P+HQZ3vb%e/xtʎAQ wߎᑘ7k퍎@̇kxp=۝Ë='Y>IՏ? +}|+Qy!QoVF4n ɠ'ao/8dQ$W禗~Q$$Cb&"A40{kyۧnM~ZR '͠tP#ZPa NA  f-Ra""Sa@J>E"gw!xݸ+Ӹ94dPk+=XO3nWy6"-Ԛ?R +rwc"gE "Q[G_!}aNn$|("e0k12uI5F>+#l4ٳ/bC,E2 vpS]' MG]`s^,=ӂC rw: Rd>ӂAx &i{.haC Dn*_&Pr`"'7N3N'Ͷovl.LS:RA)0q3:@4^{SjJ]('P+يɤd&]3H8@H[)3P8ZɤF24nR$rHe&kdLEg>Ay* Jʡ7./ׇ0fTf +}pQг!A+Lw=vYyP.ĝ f,0Q'>fcqX=PԐH߁A vjڃ@M32fmyՖ: @q|A3^5x?S|"p–@[Gl3ԇ!b-D+ڼ=+{h<}HP&N. =C %sv& R3|(sI'Z ߬e4u765:~.Z- rHUtsCuye.u "&> +7_m{> endobj +2059 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [227.445 690.167 239.4 701.016] +/Subtype /Link +/A << /S /GoTo /D (page.38) >> +>> endobj +2060 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [197.585 678.212 209.54 689.06] +/Subtype /Link +/A << /S /GoTo /D (page.22) >> +>> endobj +2061 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [219.143 666.257 231.098 677.105] +/Subtype /Link +/A << /S /GoTo /D (page.23) >> +>> endobj +2062 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [161.027 654.302 172.983 665.15] +/Subtype /Link +/A << /S /GoTo /D (page.23) >> +>> endobj +2063 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [197.585 642.347 209.54 653.195] +/Subtype /Link +/A << /S /GoTo /D (page.23) >> +>> endobj +2064 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [194.098 630.392 206.053 641.24] +/Subtype /Link +/A << /S /GoTo /D (page.36) >> +>> endobj +2065 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [250.94 618.436 262.895 629.285] +/Subtype /Link +/A << /S /GoTo /D (page.36) >> +>> endobj +2066 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [150.511 606.481 162.466 617.329] +/Subtype /Link +/A << /S /GoTo /D (page.69) >> +>> endobj +2067 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [215.739 594.526 227.694 605.374] +/Subtype /Link +/A << /S /GoTo /D (page.69) >> +>> endobj +2068 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [184.744 582.571 196.699 593.419] +/Subtype /Link +/A << /S /GoTo /D (page.72) >> +>> endobj +2069 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [201.182 570.616 213.138 581.464] +/Subtype /Link +/A << /S /GoTo /D (page.72) >> +>> endobj +2070 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [152.448 549.694 164.404 560.542] +/Subtype /Link +/A << /S /GoTo /D (page.75) >> +>> endobj +2071 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [218.202 537.739 230.157 548.587] +/Subtype /Link +/A << /S /GoTo /D (page.75) >> +>> endobj +2072 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [159.505 525.784 171.46 536.632] +/Subtype /Link +/A << /S /GoTo /D (page.71) >> +>> endobj +2073 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [219.669 513.829 231.624 524.677] +/Subtype /Link +/A << /S /GoTo /D (page.71) >> +>> endobj +2074 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [153.002 501.874 164.957 512.722] +/Subtype /Link +/A << /S /GoTo /D (page.66) >> +>> endobj +2075 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [241.005 489.918 252.961 500.656] +/Subtype /Link +/A << /S /GoTo /D (page.66) >> +>> endobj +2076 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [179.016 477.963 190.971 488.811] +/Subtype /Link +/A << /S /GoTo /D (page.72) >> +>> endobj +2077 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [201.182 466.008 213.138 476.856] +/Subtype /Link +/A << /S /GoTo /D (page.72) >> +>> endobj +2078 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [180.122 454.053 192.078 464.901] +/Subtype /Link +/A << /S /GoTo /D (page.38) >> +>> endobj +2079 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [227.445 442.098 239.4 452.946] +/Subtype /Link +/A << /S /GoTo /D (page.38) >> +>> endobj +2080 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [179.292 430.143 191.247 440.991] +/Subtype /Link +/A << /S /GoTo /D (page.38) >> +>> endobj +2081 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [227.445 418.187 239.4 429.036] +/Subtype /Link +/A << /S /GoTo /D (page.38) >> +>> endobj +2082 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [172.733 406.232 184.689 417.08] +/Subtype /Link +/A << /S /GoTo /D (page.33) >> +>> endobj +2083 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [221.55 394.277 233.506 405.125] +/Subtype /Link +/A << /S /GoTo /D (page.33) >> +>> endobj +2084 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [169.662 382.322 181.617 393.059] +/Subtype /Link +/A << /S /GoTo /D (page.17) >> +>> endobj +2085 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [185.713 382.322 197.668 393.059] +/Subtype /Link +/A << /S /GoTo /D (page.56) >> +>> endobj +2086 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [201.764 382.322 213.719 393.059] +/Subtype /Link +/A << /S /GoTo /D (page.57) >> +>> endobj +2087 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [217.815 382.322 229.77 393.059] +/Subtype /Link +/A << /S /GoTo /D (page.69) >> +>> endobj +2088 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [217.538 370.367 229.493 381.104] +/Subtype /Link +/A << /S /GoTo /D (page.17) >> +>> endobj +2089 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [202.954 358.412 214.909 369.26] +/Subtype /Link +/A << /S /GoTo /D (page.56) >> +>> endobj +2090 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [208.212 346.456 220.167 357.305] +/Subtype /Link +/A << /S /GoTo /D (page.57) >> +>> endobj +2091 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [215.739 334.501 227.694 345.349] +/Subtype /Link +/A << /S /GoTo /D (page.69) >> +>> endobj +2092 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [147.771 322.546 159.727 333.394] +/Subtype /Link +/A << /S /GoTo /D (page.69) >> +>> endobj +2093 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [215.739 310.591 227.694 321.439] +/Subtype /Link +/A << /S /GoTo /D (page.69) >> +>> endobj +2094 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [154.898 289.669 166.853 300.517] +/Subtype /Link +/A << /S /GoTo /D (page.76) >> +>> endobj +2095 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [235 277.714 246.955 288.562] +/Subtype /Link +/A << /S /GoTo /D (page.76) >> +>> endobj +2096 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [192.396 265.759 204.351 276.607] +/Subtype /Link +/A << /S /GoTo /D (page.25) >> +>> endobj +2097 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [156.254 253.804 168.209 264.541] +/Subtype /Link +/A << /S /GoTo /D (page.77) >> +>> endobj +2098 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [235 241.849 246.955 252.697] +/Subtype /Link +/A << /S /GoTo /D (page.77) >> +>> endobj +2099 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [166.355 229.893 178.31 240.742] +/Subtype /Link +/A << /S /GoTo /D (page.67) >> +>> endobj +2100 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [241.005 217.938 252.961 228.676] +/Subtype /Link +/A << /S /GoTo /D (page.67) >> +>> endobj +2101 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [175.349 205.983 187.304 216.831] +/Subtype /Link +/A << /S /GoTo /D (page.67) >> +>> endobj +2102 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [241.005 194.028 252.961 204.765] +/Subtype /Link +/A << /S /GoTo /D (page.67) >> +>> endobj +2103 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [175.625 182.073 187.581 192.921] +/Subtype /Link +/A << /S /GoTo /D (page.31) >> +>> endobj +2104 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [228.192 170.118 240.147 180.855] +/Subtype /Link +/A << /S /GoTo /D (page.31) >> +>> endobj +2105 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [167.074 158.162 179.029 169.011] +/Subtype /Link +/A << /S /GoTo /D (page.31) >> +>> endobj +2106 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [183.125 158.162 195.08 169.011] +/Subtype /Link +/A << /S /GoTo /D (page.37) >> +>> endobj +2107 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [228.192 146.207 240.147 156.945] +/Subtype /Link +/A << /S /GoTo /D (page.31) >> +>> endobj +2108 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [253.791 134.252 265.746 145.1] +/Subtype /Link +/A << /S /GoTo /D (page.37) >> +>> endobj +2109 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [134.322 113.331 146.277 124.068] +/Subtype /Link +/A << /S /GoTo /D (page.69) >> +>> endobj +2110 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [215.739 101.375 227.694 112.224] +/Subtype /Link +/A << /S /GoTo /D (page.69) >> +>> endobj +2111 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [165.594 80.454 177.549 91.302] +/Subtype /Link +/A << /S /GoTo /D (page.31) >> +>> endobj +2112 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [181.645 80.454 193.6 91.302] +/Subtype /Link +/A << /S /GoTo /D (page.34) >> +>> endobj +2113 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [197.695 80.454 209.651 91.302] +/Subtype /Link +/A << /S /GoTo /D (page.69) >> +>> endobj +2114 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [446.872 690.167 458.827 700.905] +/Subtype /Link +/A << /S /GoTo /D (page.31) >> +>> endobj +2115 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [435.803 678.212 447.758 689.06] +/Subtype /Link +/A << /S /GoTo /D (page.34) >> +>> endobj +2116 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [434.419 666.257 446.374 677.105] +/Subtype /Link +/A << /S /GoTo /D (page.69) >> +>> endobj +2117 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [363.85 654.302 375.805 665.039] +/Subtype /Link +/A << /S /GoTo /D (page.31) >> +>> endobj +2118 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [379.901 654.302 391.856 665.039] +/Subtype /Link +/A << /S /GoTo /D (page.34) >> +>> endobj +2119 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [395.952 654.302 407.907 665.039] +/Subtype /Link +/A << /S /GoTo /D (page.66) >> +>> endobj +2120 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [446.872 642.347 458.827 653.084] +/Subtype /Link +/A << /S /GoTo /D (page.31) >> +>> endobj +2121 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [435.803 630.392 447.758 641.24] +/Subtype /Link +/A << /S /GoTo /D (page.34) >> +>> endobj +2122 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [459.685 618.436 471.64 629.174] +/Subtype /Link +/A << /S /GoTo /D (page.66) >> +>> endobj +2123 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [377.383 606.481 389.338 617.219] +/Subtype /Link +/A << /S /GoTo /D (page.51) >> +>> endobj +2124 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [474.546 594.526 486.501 605.374] +/Subtype /Link +/A << /S /GoTo /D (page.51) >> +>> endobj +2125 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [404.741 582.571 416.696 593.308] +/Subtype /Link +/A << /S /GoTo /D (page.18) >> +>> endobj +2126 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [375.268 570.616 387.224 581.353] +/Subtype /Link +/A << /S /GoTo /D (page.18) >> +>> endobj +2127 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [419.962 558.661 431.917 569.398] +/Subtype /Link +/A << /S /GoTo /D (page.18) >> +>> endobj +2128 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [394.502 546.705 406.457 557.443] +/Subtype /Link +/A << /S /GoTo /D (page.18) >> +>> endobj +2129 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [406.955 534.75 418.91 545.488] +/Subtype /Link +/A << /S /GoTo /D (page.18) >> +>> endobj +2130 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [356.046 522.795 368.001 533.643] +/Subtype /Link +/A << /S /GoTo /D (page.16) >> +>> endobj +2131 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [415.462 510.84 427.417 521.577] +/Subtype /Link +/A << /S /GoTo /D (page.16) >> +>> endobj +2132 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [378.185 498.885 390.14 509.733] +/Subtype /Link +/A << /S /GoTo /D (page.48) >> +>> endobj +2133 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [394.236 498.885 406.191 509.733] +/Subtype /Link +/A << /S /GoTo /D (page.61) >> +>> endobj +2134 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [450.414 486.93 462.37 497.778] +/Subtype /Link +/A << /S /GoTo /D (page.48) >> +>> endobj +2135 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [432.814 474.974 444.769 485.712] +/Subtype /Link +/A << /S /GoTo /D (page.61) >> +>> endobj +2136 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [357.762 463.019 369.717 473.757] +/Subtype /Link +/A << /S /GoTo /D (page.71) >> +>> endobj +2137 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [438.349 451.064 450.304 461.912] +/Subtype /Link +/A << /S /GoTo /D (page.71) >> +>> endobj +2138 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [411.782 439.109 423.737 449.846] +/Subtype /Link +/A << /S /GoTo /D (page.22) >> +>> endobj +2139 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [416.265 427.154 428.22 438.002] +/Subtype /Link +/A << /S /GoTo /D (page.22) >> +>> endobj +2140 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [371.82 405.236 383.775 416.084] +/Subtype /Link +/A << /S /GoTo /D (page.58) >> +>> endobj +2141 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [422.934 393.281 434.889 404.018] +/Subtype /Link +/A << /S /GoTo /D (page.58) >> +>> endobj +2142 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [363.933 371.363 375.888 382.1] +/Subtype /Link +/A << /S /GoTo /D (page.17) >> +>> endobj +2143 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [379.984 371.363 391.939 382.1] +/Subtype /Link +/A << /S /GoTo /D (page.31) >> +>> endobj +2144 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [446.872 359.408 458.827 370.145] +/Subtype /Link +/A << /S /GoTo /D (page.31) >> +>> endobj +2145 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [436.218 347.453 448.173 358.19] +/Subtype /Link +/A << /S /GoTo /D (page.17) >> +>> endobj +2146 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [351.203 335.497 363.158 346.346] +/Subtype /Link +/A << /S /GoTo /D (page.29) >> +>> endobj +2147 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [450.387 323.542 462.342 334.39] +/Subtype /Link +/A << /S /GoTo /D (page.29) >> +>> endobj +2148 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [386.82 301.624 398.775 312.473] +/Subtype /Link +/A << /S /GoTo /D (page.44) >> +>> endobj +2149 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [402.87 301.624 414.826 312.473] +/Subtype /Link +/A << /S /GoTo /D (page.61) >> +>> endobj +2150 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [432.814 289.669 444.769 300.407] +/Subtype /Link +/A << /S /GoTo /D (page.61) >> +>> endobj +2151 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [436.301 277.714 448.256 288.562] +/Subtype /Link +/A << /S /GoTo /D (page.44) >> +>> endobj +2152 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [364.929 265.759 376.885 276.496] +/Subtype /Link +/A << /S /GoTo /D (page.35) >> +>> endobj +2153 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [380.98 265.759 392.936 276.496] +/Subtype /Link +/A << /S /GoTo /D (page.57) >> +>> endobj +2154 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [469.62 253.804 481.575 264.652] +/Subtype /Link +/A << /S /GoTo /D (page.35) >> +>> endobj +2155 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [426.892 241.849 438.847 252.697] +/Subtype /Link +/A << /S /GoTo /D (page.57) >> +>> endobj +2156 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [368.859 229.893 380.814 240.631] +/Subtype /Link +/A << /S /GoTo /D (page.27) >> +>> endobj +2157 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [384.91 229.893 396.865 240.631] +/Subtype /Link +/A << /S /GoTo /D (page.46) >> +>> endobj +2158 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [452.075 217.938 464.03 228.786] +/Subtype /Link +/A << /S /GoTo /D (page.27) >> +>> endobj +2159 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [432.011 205.983 443.966 216.831] +/Subtype /Link +/A << /S /GoTo /D (page.46) >> +>> endobj +2160 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [408.073 194.028 420.028 204.876] +/Subtype /Link +/A << /S /GoTo /D (page.38) >> +>> endobj +2161 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [446.125 182.073 458.08 192.921] +/Subtype /Link +/A << /S /GoTo /D (page.38) >> +>> endobj +2162 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [407.243 170.118 419.198 180.966] +/Subtype /Link +/A << /S /GoTo /D (page.39) >> +>> endobj +2163 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [446.125 158.162 458.08 169.011] +/Subtype /Link +/A << /S /GoTo /D (page.39) >> +>> endobj +2164 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [397.751 146.207 409.706 157.055] +/Subtype /Link +/A << /S /GoTo /D (page.48) >> +>> endobj +2165 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [450.414 134.252 462.37 145.1] +/Subtype /Link +/A << /S /GoTo /D (page.48) >> +>> endobj +2166 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [370.16 122.297 382.115 133.034] +/Subtype /Link +/A << /S /GoTo /D (page.69) >> +>> endobj +2167 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [434.419 110.342 446.374 121.19] +/Subtype /Link +/A << /S /GoTo /D (page.69) >> +>> endobj +2168 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [377.355 98.387 389.31 109.235] +/Subtype /Link +/A << /S /GoTo /D (page.52) >> +>> endobj +2169 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [474.546 86.431 486.501 97.28] +/Subtype /Link +/A << /S /GoTo /D (page.52) >> +>> endobj +2058 0 obj << +/D [2056 0 R /XYZ 109.858 727.97 null] +>> endobj +2055 0 obj << +/Font << /F29 416 0 R /F8 369 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +2172 0 obj << +/Length 5092 +/Filter /FlateDecode +>> +stream +xڵ]]sƭХ<~\^Nڸ7tV,֛__`YFLdxb#'/ +;ًE-b].}|6^ Z'@$|f/%V?o h=j/~GzV~{ٟ"*?åa˲gWjp?_"H^9=W]WWI۪Ų.VAbΊuޤV14EiLE-{);[ro|?>~CUH$ .o?G@;蟱+l|#ʰvzZqj\pDr.쵣 ,| " j \˗|}x˸h%-@E\vDPF ̇"0A"3VYFon_>B6d\wj{P pRj 艤noC f-Լ&HG.ȁ@ v/*A)`&x$`\b>|oZJBZpt8}}}WY0JE#-\;:rQ)9e>aE"()a|y%?bd%S72JJ#Ah4ԁ,A1b4kd~9AEJ%|[½ g- +ֲ*r' ߟ^F*CqUu,Z pk-,J͙ km3d]iwm#{An ۹EDmR_+TVCXKFLȡo9d@#͖c,eQi,FGHoovݧp ȲtgK!, k,pA[Tre4(XM_߹I]2PQop,WV deՋ0"IDI⃋1\iT%)iT{@e:^ی eډ"WY,ULQ O6MZfK&#CY)=@@'T;kO.'(Zi>X|w!.x=_pa46Zv9rɺrg1^ol47ڣ6"Yv[eH ZiTɳzw!H\&_pas:ԍK'*a*ר'{!,3#[+m40R0(6 +/ QSڅ1Y3R Ɉ77/r>?W'0E%=ăv6C u㏲`^p4[PnJzZ-~#*F,<(-^3Ai5 )=%\3gs8'tORgVyeeXk;=ZZ# z ,1Z*:h9hD}m͖c-EfZr ++R++c,%i,I fsu(6v7F.CDpj9E1ɠ!~ÐQ߁Ð: I-c:R!k$ +'IE:@ܼ9=;v޿ yw&Dlڡ%Y;՜P;2)WLj dhk"z^S>4g2k? +!tt.c +q`F=qa]]Z9#n[55_2Ƌpa4ꢞnz بډǕg=?< +*mMt>VM" aZ:"e7_eXkɘ_߇:"F(p=^v:p#rΈV*DuDrS{z֌R:7Se8k{=խMb_o\ȵ׋W#^pa2}|kc&#koPG<ΗGZL|X+ϗ3kn0 f<0R: #!ߊޟe.qzw?lt>qrV`3jOC4c+CڎxTف|TDZcfl̇;P1YqvGرA A\hm+JvC ;nG ++ũp2E8ʰ%U`u#fF*M\{#* &byZbj)+{K˜4=9hIhZS5DZd#Al&GDi[K1J*‘e&,;rF@Z^?WN|(ΝZ643fd6}ȁ@ Vcc\|(Xd8kO3{*^gp wlQ)<Q8Je6h2[2ć6e"e +ρpV_.xta}  Y[gn@ז#g@mATdU|H"6rMkȁ@G}l}xZłOj6^c K IuICOaC#n@͍mԞѿDYE>]$m%m%2!1PɃH2s$~&,B![ FMT"Ž!mx&LZ" \z{~J[V6 Q@o; T~/PA8' +S {G\ɲe ܵu[-wN~)n 9hy70ʩe|(/YK!Xw'5~ƻٌZ` Snx@ekoC/8F]( 'يiAZ)'τ|s%&J7luG"7iqL'kPvü k-AΫ_@`T ӕ[ԃ/X"ʴ))QA-" ]\ekuC23 $]@W@[]1g>4bD"xt t_KM2{2 Xe2#,n5Z/s`DV( t (YVp Ph%Ue%:4׍s^ݿ =) YfL-* ā2?xT N6^? +ZZUi`"8Ьڦ" ` 7JN#7$`Ih׌z4ֿ5/*2X5Vendstream +endobj +2171 0 obj << +/Type /Page +/Contents 2172 0 R +/Resources 2170 0 R +/MediaBox [0 0 612 792] +/Parent 2054 0 R +/Annots [ 2174 0 R 2175 0 R 2176 0 R 2177 0 R 2178 0 R 2179 0 R 2180 0 R 2181 0 R 2182 0 R 2183 0 R 2184 0 R 2185 0 R 2186 0 R 2187 0 R 2188 0 R 2189 0 R 2190 0 R 2191 0 R 2192 0 R 2193 0 R 2194 0 R 2195 0 R 2196 0 R 2197 0 R 2198 0 R 2199 0 R 2200 0 R 2201 0 R 2202 0 R 2203 0 R 2204 0 R 2205 0 R 2206 0 R 2207 0 R 2208 0 R 2209 0 R 2210 0 R 2211 0 R 2212 0 R 2213 0 R 2214 0 R 2215 0 R 2216 0 R 2217 0 R 2218 0 R 2219 0 R 2220 0 R 2221 0 R 2222 0 R 2223 0 R 2224 0 R 2225 0 R 2226 0 R 2227 0 R 2228 0 R 2229 0 R 2230 0 R 2231 0 R 2232 0 R 2233 0 R 2234 0 R 2235 0 R 2236 0 R 2237 0 R 2238 0 R 2239 0 R 2240 0 R 2241 0 R 2242 0 R 2243 0 R 2244 0 R 2245 0 R 2246 0 R 2247 0 R 2248 0 R 2249 0 R 2250 0 R 2251 0 R 2252 0 R 2253 0 R 2254 0 R 2255 0 R 2256 0 R 2257 0 R 2258 0 R 2259 0 R 2260 0 R 2261 0 R 2262 0 R 2263 0 R 2264 0 R 2265 0 R 2266 0 R 2267 0 R 2268 0 R 2269 0 R 2270 0 R 2271 0 R 2272 0 R 2273 0 R 2274 0 R 2275 0 R 2276 0 R 2277 0 R 2278 0 R 2279 0 R 2280 0 R 2281 0 R 2282 0 R 2283 0 R 2284 0 R 2285 0 R 2286 0 R 2287 0 R 2288 0 R ] +>> endobj +2174 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [188.12 690.167 200.075 701.016] +/Subtype /Link +/A << /S /GoTo /D (page.48) >> +>> endobj +2175 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [204.171 690.167 216.126 701.016] +/Subtype /Link +/A << /S /GoTo /D (page.61) >> +>> endobj +2176 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [231.735 678.212 243.69 689.06] +/Subtype /Link +/A << /S /GoTo /D (page.48) >> +>> endobj +2177 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [214.134 666.257 226.089 676.995] +/Subtype /Link +/A << /S /GoTo /D (page.61) >> +>> endobj +2178 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [162.273 654.302 174.228 665.15] +/Subtype /Link +/A << /S /GoTo /D (page.61) >> +>> endobj +2179 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [214.134 642.347 226.089 653.084] +/Subtype /Link +/A << /S /GoTo /D (page.61) >> +>> endobj +2180 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [187.456 630.392 199.411 641.24] +/Subtype /Link +/A << /S /GoTo /D (page.39) >> +>> endobj +2181 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [227.445 618.436 239.4 629.285] +/Subtype /Link +/A << /S /GoTo /D (page.39) >> +>> endobj +2182 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [186.626 606.481 198.581 617.329] +/Subtype /Link +/A << /S /GoTo /D (page.39) >> +>> endobj +2183 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [227.445 594.526 239.4 605.374] +/Subtype /Link +/A << /S /GoTo /D (page.39) >> +>> endobj +2184 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [161.166 582.571 173.121 593.419] +/Subtype /Link +/A << /S /GoTo /D (page.17) >> +>> endobj +2185 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [217.538 570.616 229.493 581.353] +/Subtype /Link +/A << /S /GoTo /D (page.17) >> +>> endobj +2186 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [177.134 558.661 189.089 569.509] +/Subtype /Link +/A << /S /GoTo /D (page.48) >> +>> endobj +2187 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [231.735 546.705 243.69 557.554] +/Subtype /Link +/A << /S /GoTo /D (page.48) >> +>> endobj +2188 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [156.738 534.75 168.693 545.598] +/Subtype /Link +/A << /S /GoTo /D (page.52) >> +>> endobj +2189 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [255.866 522.795 267.822 533.643] +/Subtype /Link +/A << /S /GoTo /D (page.52) >> +>> endobj +2190 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [160.336 510.84 172.291 521.688] +/Subtype /Link +/A << /S /GoTo /D (page.17) >> +>> endobj +2191 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [176.386 510.84 188.342 521.688] +/Subtype /Link +/A << /S /GoTo /D (page.61) >> +>> endobj +2192 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [217.538 498.885 229.493 509.622] +/Subtype /Link +/A << /S /GoTo /D (page.17) >> +>> endobj +2193 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [214.134 486.93 226.089 497.667] +/Subtype /Link +/A << /S /GoTo /D (page.61) >> +>> endobj +2194 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [155.409 474.974 167.365 485.712] +/Subtype /Link +/A << /S /GoTo /D (page.59) >> +>> endobj +2195 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [224.456 463.019 236.411 473.757] +/Subtype /Link +/A << /S /GoTo /D (page.59) >> +>> endobj +2196 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [140.133 441.101 152.089 451.839] +/Subtype /Link +/A << /S /GoTo /D (page.16) >> +>> endobj +2197 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [196.782 429.146 208.737 439.884] +/Subtype /Link +/A << /S /GoTo /D (page.16) >> +>> endobj +2198 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [212.556 407.228 224.512 418.077] +/Subtype /Link +/A << /S /GoTo /D (page.67) >> +>> endobj +2199 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [241.005 395.273 252.961 406.011] +/Subtype /Link +/A << /S /GoTo /D (page.67) >> +>> endobj +2200 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [177.41 383.318 189.366 394.166] +/Subtype /Link +/A << /S /GoTo /D (page.18) >> +>> endobj +2201 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [193.461 383.318 205.417 394.166] +/Subtype /Link +/A << /S /GoTo /D (page.58) >> +>> endobj +2202 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [209.512 383.318 221.468 394.166] +/Subtype /Link +/A << /S /GoTo /D (page.67) >> +>> endobj +2203 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [217.538 371.363 229.493 382.1] +/Subtype /Link +/A << /S /GoTo /D (page.18) >> +>> endobj +2204 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [241.005 359.408 252.961 370.145] +/Subtype /Link +/A << /S /GoTo /D (page.67) >> +>> endobj +2205 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [208.212 347.453 220.167 358.301] +/Subtype /Link +/A << /S /GoTo /D (page.58) >> +>> endobj +2206 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [208.267 335.497 220.222 346.346] +/Subtype /Link +/A << /S /GoTo /D (page.49) >> +>> endobj +2207 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [224.318 335.497 236.273 346.346] +/Subtype /Link +/A << /S /GoTo /D (page.62) >> +>> endobj +2208 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [231.735 323.542 243.69 334.39] +/Subtype /Link +/A << /S /GoTo /D (page.49) >> +>> endobj +2209 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [214.134 311.587 226.089 322.325] +/Subtype /Link +/A << /S /GoTo /D (page.62) >> +>> endobj +2210 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [191.054 299.632 203.009 310.48] +/Subtype /Link +/A << /S /GoTo /D (page.78) >> +>> endobj +2211 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [247.564 287.677 259.519 298.525] +/Subtype /Link +/A << /S /GoTo /D (page.78) >> +>> endobj +2212 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [167.531 275.722 179.486 286.57] +/Subtype /Link +/A << /S /GoTo /D (page.78) >> +>> endobj +2213 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [247.564 263.766 259.519 274.615] +/Subtype /Link +/A << /S /GoTo /D (page.78) >> +>> endobj +2214 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [160.889 251.811 172.844 262.659] +/Subtype /Link +/A << /S /GoTo /D (page.33) >> +>> endobj +2215 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [176.94 251.811 188.895 262.659] +/Subtype /Link +/A << /S /GoTo /D (page.37) >> +>> endobj +2216 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [192.991 251.811 204.946 262.659] +/Subtype /Link +/A << /S /GoTo /D (page.57) >> +>> endobj +2217 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [209.042 251.811 220.997 262.659] +/Subtype /Link +/A << /S /GoTo /D (page.62) >> +>> endobj +2218 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [225.093 251.811 237.048 262.659] +/Subtype /Link +/A << /S /GoTo /D (page.78) >> +>> endobj +2219 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [240.922 239.856 252.877 250.704] +/Subtype /Link +/A << /S /GoTo /D (page.33) >> +>> endobj +2220 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [214.134 227.901 226.089 238.638] +/Subtype /Link +/A << /S /GoTo /D (page.62) >> +>> endobj +2221 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [253.791 215.946 265.746 226.794] +/Subtype /Link +/A << /S /GoTo /D (page.37) >> +>> endobj +2222 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [247.564 203.991 259.519 214.839] +/Subtype /Link +/A << /S /GoTo /D (page.78) >> +>> endobj +2223 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [202.954 192.035 214.909 202.884] +/Subtype /Link +/A << /S /GoTo /D (page.57) >> +>> endobj +2224 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [171.71 180.08 183.665 190.928] +/Subtype /Link +/A << /S /GoTo /D (page.49) >> +>> endobj +2225 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [187.76 180.08 199.716 190.928] +/Subtype /Link +/A << /S /GoTo /D (page.62) >> +>> endobj +2226 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [231.735 168.125 243.69 178.973] +/Subtype /Link +/A << /S /GoTo /D (page.49) >> +>> endobj +2227 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [214.134 156.17 226.089 166.907] +/Subtype /Link +/A << /S /GoTo /D (page.62) >> +>> endobj +2228 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [162.854 144.215 174.809 154.952] +/Subtype /Link +/A << /S /GoTo /D (page.54) >> +>> endobj +2229 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [255.866 132.26 267.822 143.108] +/Subtype /Link +/A << /S /GoTo /D (page.54) >> +>> endobj +2230 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [196.367 120.304 208.322 131.153] +/Subtype /Link +/A << /S /GoTo /D (page.41) >> +>> endobj +2231 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [227.445 108.349 239.4 119.197] +/Subtype /Link +/A << /S /GoTo /D (page.41) >> +>> endobj +2232 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [195.094 96.394 207.049 107.242] +/Subtype /Link +/A << /S /GoTo /D (page.79) >> +>> endobj +2233 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [247.564 84.439 259.519 95.287] +/Subtype /Link +/A << /S /GoTo /D (page.79) >> +>> endobj +2234 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [396.616 690.167 408.571 700.905] +/Subtype /Link +/A << /S /GoTo /D (page.18) >> +>> endobj +2235 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [436.218 678.212 448.173 688.95] +/Subtype /Link +/A << /S /GoTo /D (page.18) >> +>> endobj +2236 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [390.528 666.257 402.483 676.995] +/Subtype /Link +/A << /S /GoTo /D (page.49) >> +>> endobj +2237 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [406.579 666.257 418.534 676.995] +/Subtype /Link +/A << /S /GoTo /D (page.62) >> +>> endobj +2238 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [450.414 654.302 462.37 665.15] +/Subtype /Link +/A << /S /GoTo /D (page.49) >> +>> endobj +2239 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [432.814 642.347 444.769 653.084] +/Subtype /Link +/A << /S /GoTo /D (page.62) >> +>> endobj +2240 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [393.987 630.392 405.942 641.129] +/Subtype /Link +/A << /S /GoTo /D (page.32) >> +>> endobj +2241 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [446.872 618.436 458.827 629.174] +/Subtype /Link +/A << /S /GoTo /D (page.32) >> +>> endobj +2242 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [399.563 606.481 411.519 617.329] +/Subtype /Link +/A << /S /GoTo /D (page.79) >> +>> endobj +2243 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [466.244 594.526 478.199 605.374] +/Subtype /Link +/A << /S /GoTo /D (page.79) >> +>> endobj +2244 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [409.858 582.571 421.813 593.419] +/Subtype /Link +/A << /S /GoTo /D (page.79) >> +>> endobj +2245 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [466.244 570.616 478.199 581.464] +/Subtype /Link +/A << /S /GoTo /D (page.79) >> +>> endobj +2246 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [404.019 558.661 415.974 569.509] +/Subtype /Link +/A << /S /GoTo /D (page.77) >> +>> endobj +2247 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [453.68 546.705 465.635 557.554] +/Subtype /Link +/A << /S /GoTo /D (page.77) >> +>> endobj +2248 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [389.255 534.75 401.21 545.598] +/Subtype /Link +/A << /S /GoTo /D (page.50) >> +>> endobj +2249 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [450.414 522.795 462.37 533.643] +/Subtype /Link +/A << /S /GoTo /D (page.50) >> +>> endobj +2250 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [412.031 510.84 423.986 521.688] +/Subtype /Link +/A << /S /GoTo /D (page.50) >> +>> endobj +2251 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [428.082 510.84 440.037 521.688] +/Subtype /Link +/A << /S /GoTo /D (page.62) >> +>> endobj +2252 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [450.414 498.885 462.37 509.733] +/Subtype /Link +/A << /S /GoTo /D (page.50) >> +>> endobj +2253 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [432.814 486.93 444.769 497.667] +/Subtype /Link +/A << /S /GoTo /D (page.62) >> +>> endobj +2254 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [411.2 474.974 423.156 485.823] +/Subtype /Link +/A << /S /GoTo /D (page.50) >> +>> endobj +2255 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [427.251 474.974 439.207 485.823] +/Subtype /Link +/A << /S /GoTo /D (page.63) >> +>> endobj +2256 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [450.414 463.019 462.37 473.867] +/Subtype /Link +/A << /S /GoTo /D (page.50) >> +>> endobj +2257 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [432.814 451.064 444.769 461.802] +/Subtype /Link +/A << /S /GoTo /D (page.63) >> +>> endobj +2258 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [399.162 439.109 411.117 449.846] +/Subtype /Link +/A << /S /GoTo /D (page.44) >> +>> endobj +2259 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [436.301 427.154 448.256 438.002] +/Subtype /Link +/A << /S /GoTo /D (page.44) >> +>> endobj +2260 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [399.688 415.199 411.643 425.936] +/Subtype /Link +/A << /S /GoTo /D (page.44) >> +>> endobj +2261 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [436.301 403.243 448.256 414.092] +/Subtype /Link +/A << /S /GoTo /D (page.44) >> +>> endobj +2262 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [393.268 391.288 405.223 402.136] +/Subtype /Link +/A << /S /GoTo /D (page.67) >> +>> endobj +2263 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [459.685 379.333 471.64 390.071] +/Subtype /Link +/A << /S /GoTo /D (page.67) >> +>> endobj +2264 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [409.18 367.378 421.135 378.226] +/Subtype /Link +/A << /S /GoTo /D (page.68) >> +>> endobj +2265 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [459.685 355.423 471.64 366.16] +/Subtype /Link +/A << /S /GoTo /D (page.68) >> +>> endobj +2266 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [366.285 343.468 378.241 354.205] +/Subtype /Link +/A << /S /GoTo /D (page.54) >> +>> endobj +2267 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [474.546 331.512 486.501 342.361] +/Subtype /Link +/A << /S /GoTo /D (page.54) >> +>> endobj +2268 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [402.538 319.557 414.494 330.405] +/Subtype /Link +/A << /S /GoTo /D (page.54) >> +>> endobj +2269 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [474.546 307.602 486.501 318.45] +/Subtype /Link +/A << /S /GoTo /D (page.54) >> +>> endobj +2270 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [409.457 295.647 421.412 306.495] +/Subtype /Link +/A << /S /GoTo /D (page.73) >> +>> endobj +2271 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [419.862 283.692 431.817 294.54] +/Subtype /Link +/A << /S /GoTo /D (page.73) >> +>> endobj +2272 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [403.922 271.737 415.877 282.585] +/Subtype /Link +/A << /S /GoTo /D (page.55) >> +>> endobj +2273 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [474.546 259.781 486.501 270.63] +/Subtype /Link +/A << /S /GoTo /D (page.55) >> +>> endobj +2274 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [402.538 247.826 414.494 258.674] +/Subtype /Link +/A << /S /GoTo /D (page.55) >> +>> endobj +2275 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [474.546 235.871 486.501 246.719] +/Subtype /Link +/A << /S /GoTo /D (page.55) >> +>> endobj +2276 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [383.748 223.916 395.703 234.653] +/Subtype /Link +/A << /S /GoTo /D (page.35) >> +>> endobj +2277 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [399.799 223.916 411.754 234.653] +/Subtype /Link +/A << /S /GoTo /D (page.57) >> +>> endobj +2278 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [469.62 211.961 481.575 222.809] +/Subtype /Link +/A << /S /GoTo /D (page.35) >> +>> endobj +2279 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [426.892 200.006 438.847 210.854] +/Subtype /Link +/A << /S /GoTo /D (page.57) >> +>> endobj +2280 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [398.858 178.088 410.813 188.936] +/Subtype /Link +/A << /S /GoTo /D (page.77) >> +>> endobj +2281 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [466.244 166.133 478.199 176.981] +/Subtype /Link +/A << /S /GoTo /D (page.77) >> +>> endobj +2282 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [361.774 154.177 373.73 165.026] +/Subtype /Link +/A << /S /GoTo /D (page.66) >> +>> endobj +2283 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [459.685 142.222 471.64 152.96] +/Subtype /Link +/A << /S /GoTo /D (page.66) >> +>> endobj +2284 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [395.924 130.267 407.879 141.115] +/Subtype /Link +/A << /S /GoTo /D (page.56) >> +>> endobj +2285 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [421.633 118.312 433.589 129.16] +/Subtype /Link +/A << /S /GoTo /D (page.56) >> +>> endobj +2286 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [368.97 106.357 380.925 117.094] +/Subtype /Link +/A << /S /GoTo /D (page.36) >> +>> endobj +2287 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [469.62 94.402 481.575 105.25] +/Subtype /Link +/A << /S /GoTo /D (page.36) >> +>> endobj +2288 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [363.712 82.446 375.667 93.295] +/Subtype /Link +/A << /S /GoTo /D (page.52) >> +>> endobj +2173 0 obj << +/D [2171 0 R /XYZ 109.858 727.97 null] +>> endobj +2170 0 obj << +/Font << /F29 416 0 R /F8 369 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +2291 0 obj << +/Length 5353 +/Filter /FlateDecode +>> +stream +xڵ][s7r~ׯ#UeLfmvǎSZ:ˋCtvb2Euh4?y!mZ)7mݳg2J-uow"OPӶn(?-h ̶^ϓ23lrkճZEVJ%V3?W7j?"JDoz2_}:k*JṰf-[6ͥm[ZԲL%bSMI0V}a-9Ko믞 y_zk_(r+i'}>"Gp~ )t^;z()>Cdz*'i#<?H8`< )9^\@J‡}LZ&}FzD}m҃xۡMLiow +#%K0" rFm9#v-|2]kz\~wzp{{xANvYR('Beal['BYDPzV"p#{zW}əu0#"2vx̰dRe3 +fpcJ 1i[^ HFRw=JNcEKXm2 e5ÿ?o3xqK[V?"ӎΫst*P@GBsp{k #idV00"R(sog|XAj6lE8LQsP#:Nj@?v!QYez2? r5~`qbyWĈHA̯1>3TlF(ӵ՜CI dć6121@:[#ƫ{^^~QZڬc")yޠ\>0DDX9jΡ ڤqCC"mk"ry?q!ۧJu"ae$ Ԏ~c֦(Ag-UdyCij?l|\D PFLHkIYKl1Kdͻ>^L2Fv)/J ")|K ӵ a!bk}ehWAH]p"yUJ5׃%yE$v2 6g/xQ84#G@ +G=s|E` u WAkmUjrGd߅R G4eڶ*-َ#&%# G@+\6Ac*k\& JCZ. Y'@I@P$ PN҅,BQg, &)C;^XFȼ!he_xLG{,rr{Kkj_ـʤzHA2V+>(ӳy!+:f~YR,5mı~H@'|:IH$ I'l +x$e:);lkv4o3pdV +HA|V*7V ӵxΆ+ll_QWԃUXĬ`[xN͵b PNR;f+}m2>pbH ůmT62pd8qɆj?R <[aO5Ac)@Aegxn?"^uSa HA)iU+|HZK\vrN'?+02xH5dYs=" ib'hXbs +{wa hWs/r"rLjC#Pk-bZCk @󬒢5La +5 "SzV5f\V;aO:(.U\Pm>4N!HtCN&E$i[,)’6gƳ&0""2ovikgf +#LNOnps9#Bo|w (ӵS4*8 ;37|Xc;c +1[iN[`D PN{jv (ӵ)`Kշur@w@ ++R{}P(֑2=k9,NN󲱰j4dE#ʗQZWAg-M >cz?-|E6r6 Ujo >u+|giLZ63 Ig^>4녎L wĸ}aSebq}L,)O,v2|b) +d9.J`}n.+I)'R{=ďsʌrRkbD765^[y +[''N +䝼BwqtwLX˶? U?![-pvNh6ۦV{.l]_W& +$  .'EKۄ,0BS@ h1s.&d^{=fA0iLP m5Лzx3 +&d^ey4fRk`Y. 58!.HHn?pZ?ZծVمհ4\׀ )^0Ϭ2]k%f +6>%VK=oWԇf۱Yͮ1?ݼ*WfW)'ٹ:ɭZK\SWsr6BҶ"V{yxlS +[6uF% r%ާ>pĖߩyxo%#;z8V;UD +D L0"` )'o Vpƅ(ӵ`qskC '![V3^q Qg-Â|dV'$h@W;~W[4Rx{he- d[!Fo6K6 HA|9SjG@>MY2ώяJqV6C@C;h\v] 1LZ"Ʒɴ +.=u 'huaKCK +jk[YL1)50/2+{ P(׏f>GZKgǏh))3Y&Ȼ)Ag-1EofR2&XQ͆*FfgR{L^Cg ӵW5FZ=) P*׃aFdz2!pIRBt" Pc~hYYAɤxd w]5۴Α7ɷ +ݍލ;oL&''g㢞{\ԇfc-hn%/4Gp¶o} bA[59x 8!\3Z;>%JoalH' ~O^j R>~OZH9;]<):>'V}Nlԇf}ޱ`ˠ,/_*U!#y@ +QݏSX`O}yZKɥ%=^?ۢF~#R(K< +TdzrH 4m@rYH HANlZ v6 b N2iR(/K퍄*AyFƋzmk9,vfHM$#KHdԀ3jݗcVl>dzrPݺ'MzY0 +HA|}ht6 ӳCcu=PM>yAf:BSj2Q= ;^g+G)=/=kp_aC"h'2']"k7VCoy2X`_6)@0ۭ𡶯2]kmJ'^PG찃SPo02x8dB5c kusij$Ac)aq|?3k͞vjlR8ۂ@qB6[V:PjAu4>5M.2|d8|ޠ 2r%oeuZzKddIendstream +endobj +2290 0 obj << +/Type /Page +/Contents 2291 0 R +/Resources 2289 0 R +/MediaBox [0 0 612 792] +/Parent 2054 0 R +/Annots [ 2293 0 R 2294 0 R 2295 0 R 2296 0 R 2297 0 R 2298 0 R 2299 0 R 2300 0 R 2301 0 R 2302 0 R 2303 0 R 2304 0 R 2305 0 R 2306 0 R 2307 0 R 2308 0 R 2309 0 R 2310 0 R 2311 0 R 2312 0 R 2313 0 R 2314 0 R 2315 0 R 2316 0 R 2317 0 R 2318 0 R 2319 0 R 2320 0 R 2321 0 R 2322 0 R 2323 0 R 2324 0 R 2325 0 R 2326 0 R 2327 0 R 2328 0 R 2329 0 R 2330 0 R 2331 0 R 2332 0 R 2333 0 R 2334 0 R 2335 0 R 2336 0 R 2337 0 R 2338 0 R 2339 0 R 2340 0 R 2341 0 R 2342 0 R 2343 0 R 2344 0 R 2345 0 R 2346 0 R 2347 0 R 2348 0 R 2349 0 R 2350 0 R 2351 0 R 2352 0 R 2353 0 R 2354 0 R 2355 0 R 2356 0 R 2357 0 R 2358 0 R 2359 0 R 2360 0 R 2361 0 R 2362 0 R 2363 0 R 2364 0 R 2365 0 R 2366 0 R 2367 0 R 2368 0 R 2369 0 R 2370 0 R 2371 0 R 2372 0 R 2373 0 R 2374 0 R 2375 0 R 2376 0 R 2377 0 R 2378 0 R 2379 0 R 2380 0 R 2381 0 R 2382 0 R 2383 0 R 2384 0 R 2385 0 R 2386 0 R 2387 0 R 2388 0 R 2389 0 R 2390 0 R 2391 0 R 2392 0 R 2393 0 R 2394 0 R 2395 0 R 2396 0 R 2397 0 R 2398 0 R 2399 0 R ] +>> endobj +2293 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [255.866 690.167 267.822 701.016] +/Subtype /Link +/A << /S /GoTo /D (page.52) >> +>> endobj +2294 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [140.853 678.212 152.808 689.06] +/Subtype /Link +/A << /S /GoTo /D (page.52) >> +>> endobj +2295 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [255.866 666.257 267.822 677.105] +/Subtype /Link +/A << /S /GoTo /D (page.52) >> +>> endobj +2296 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [142.209 644.339 154.164 655.077] +/Subtype /Link +/A << /S /GoTo /D (page.36) >> +>> endobj +2297 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [250.94 632.384 262.895 643.232] +/Subtype /Link +/A << /S /GoTo /D (page.36) >> +>> endobj +2298 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [157.706 620.429 169.662 631.277] +/Subtype /Link +/A << /S /GoTo /D (page.56) >> +>> endobj +2299 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [202.954 608.474 214.909 619.322] +/Subtype /Link +/A << /S /GoTo /D (page.56) >> +>> endobj +2300 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [230.212 596.519 242.168 607.367] +/Subtype /Link +/A << /S /GoTo /D (page.25) >> +>> endobj +2301 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [169.745 584.563 181.7 595.412] +/Subtype /Link +/A << /S /GoTo /D (page.31) >> +>> endobj +2302 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [228.192 572.608 240.147 583.346] +/Subtype /Link +/A << /S /GoTo /D (page.31) >> +>> endobj +2303 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [159.09 560.653 171.045 571.391] +/Subtype /Link +/A << /S /GoTo /D (page.31) >> +>> endobj +2304 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [228.192 548.698 240.147 559.435] +/Subtype /Link +/A << /S /GoTo /D (page.31) >> +>> endobj +2305 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [179.32 536.743 191.275 547.591] +/Subtype /Link +/A << /S /GoTo /D (page.31) >> +>> endobj +2306 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [228.192 524.788 240.147 535.525] +/Subtype /Link +/A << /S /GoTo /D (page.31) >> +>> endobj +2307 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [200.075 512.832 212.031 523.681] +/Subtype /Link +/A << /S /GoTo /D (page.42) >> +>> endobj +2308 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [210.149 500.877 222.104 511.725] +/Subtype /Link +/A << /S /GoTo /D (page.42) >> +>> endobj +2309 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [139.165 488.922 151.12 499.77] +/Subtype /Link +/A << /S /GoTo /D (page.29) >> +>> endobj +2310 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [231.707 476.967 243.662 487.815] +/Subtype /Link +/A << /S /GoTo /D (page.29) >> +>> endobj +2311 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [161.027 465.012 172.983 475.749] +/Subtype /Link +/A << /S /GoTo /D (page.76) >> +>> endobj +2312 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [177.078 465.012 189.033 475.749] +/Subtype /Link +/A << /S /GoTo /D (page.78) >> +>> endobj +2313 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [235 453.057 246.955 463.905] +/Subtype /Link +/A << /S /GoTo /D (page.76) >> +>> endobj +2314 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [247.564 441.101 259.519 451.95] +/Subtype /Link +/A << /S /GoTo /D (page.78) >> +>> endobj +2315 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [179.763 419.184 191.718 430.032] +/Subtype /Link +/A << /S /GoTo /D (page.36) >> +>> endobj +2316 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [250.94 407.228 262.895 418.077] +/Subtype /Link +/A << /S /GoTo /D (page.36) >> +>> endobj +2317 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [167.531 395.273 179.486 406.121] +/Subtype /Link +/A << /S /GoTo /D (page.78) >> +>> endobj +2318 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [247.564 383.318 259.519 394.166] +/Subtype /Link +/A << /S /GoTo /D (page.78) >> +>> endobj +2319 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [183.056 371.363 195.011 382.211] +/Subtype /Link +/A << /S /GoTo /D (page.46) >> +>> endobj +2320 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [213.331 359.408 225.286 370.256] +/Subtype /Link +/A << /S /GoTo /D (page.46) >> +>> endobj +2321 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [230.489 347.453 242.444 358.301] +/Subtype /Link +/A << /S /GoTo /D (page.39) >> +>> endobj +2322 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [227.445 335.497 239.4 346.346] +/Subtype /Link +/A << /S /GoTo /D (page.39) >> +>> endobj +2323 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [164.21 323.542 176.165 334.39] +/Subtype /Link +/A << /S /GoTo /D (page.56) >> +>> endobj +2324 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [202.954 311.587 214.909 322.435] +/Subtype /Link +/A << /S /GoTo /D (page.56) >> +>> endobj +2325 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [168.14 299.632 180.095 310.48] +/Subtype /Link +/A << /S /GoTo /D (page.61) >> +>> endobj +2326 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [214.134 287.677 226.089 298.414] +/Subtype /Link +/A << /S /GoTo /D (page.61) >> +>> endobj +2327 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [184.938 275.722 196.893 286.57] +/Subtype /Link +/A << /S /GoTo /D (page.48) >> +>> endobj +2328 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [231.735 263.766 243.69 274.615] +/Subtype /Link +/A << /S /GoTo /D (page.48) >> +>> endobj +2329 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [168.499 251.811 180.455 262.659] +/Subtype /Link +/A << /S /GoTo /D (page.66) >> +>> endobj +2330 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [241.005 239.856 252.961 250.594] +/Subtype /Link +/A << /S /GoTo /D (page.66) >> +>> endobj +2331 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [164.21 227.901 176.165 238.749] +/Subtype /Link +/A << /S /GoTo /D (page.66) >> +>> endobj +2332 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [241.005 215.946 252.961 226.683] +/Subtype /Link +/A << /S /GoTo /D (page.66) >> +>> endobj +2333 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [132.108 203.991 144.063 214.728] +/Subtype /Link +/A << /S /GoTo /D (page.16) >> +>> endobj +2334 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [148.159 203.991 160.114 214.728] +/Subtype /Link +/A << /S /GoTo /D (page.20) >> +>> endobj +2335 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [164.21 203.991 176.165 214.728] +/Subtype /Link +/A << /S /GoTo /D (page.70) >> +>> endobj +2336 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [196.782 192.035 208.737 202.773] +/Subtype /Link +/A << /S /GoTo /D (page.16) >> +>> endobj +2337 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [226.117 180.08 238.072 190.818] +/Subtype /Link +/A << /S /GoTo /D (page.20) >> +>> endobj +2338 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [215.739 168.125 227.694 178.973] +/Subtype /Link +/A << /S /GoTo /D (page.70) >> +>> endobj +2339 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [152.13 156.17 164.085 166.907] +/Subtype /Link +/A << /S /GoTo /D (page.66) >> +>> endobj +2340 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [241.005 144.215 252.961 154.952] +/Subtype /Link +/A << /S /GoTo /D (page.66) >> +>> endobj +2341 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [166.368 132.26 178.324 142.997] +/Subtype /Link +/A << /S /GoTo /D (page.44) >> +>> endobj +2342 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [217.621 120.304 229.576 131.153] +/Subtype /Link +/A << /S /GoTo /D (page.44) >> +>> endobj +2343 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [207.713 108.349 219.669 119.197] +/Subtype /Link +/A << /S /GoTo /D (page.39) >> +>> endobj +2344 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [227.445 96.394 239.4 107.242] +/Subtype /Link +/A << /S /GoTo /D (page.39) >> +>> endobj +2345 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [136.536 84.439 148.491 95.176] +/Subtype /Link +/A << /S /GoTo /D (page.52) >> +>> endobj +2346 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [474.546 690.167 486.501 701.016] +/Subtype /Link +/A << /S /GoTo /D (page.52) >> +>> endobj +2347 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [392.769 678.212 404.725 688.95] +/Subtype /Link +/A << /S /GoTo /D (page.22) >> +>> endobj +2348 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [408.82 678.212 420.776 688.95] +/Subtype /Link +/A << /S /GoTo /D (page.24) >> +>> endobj +2349 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [424.871 678.212 436.827 688.95] +/Subtype /Link +/A << /S /GoTo /D (page.39) >> +>> endobj +2350 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [446.125 666.257 458.08 677.105] +/Subtype /Link +/A << /S /GoTo /D (page.39) >> +>> endobj +2351 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [416.265 654.302 428.22 665.15] +/Subtype /Link +/A << /S /GoTo /D (page.22) >> +>> endobj +2352 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [437.823 642.347 449.778 653.195] +/Subtype /Link +/A << /S /GoTo /D (page.24) >> +>> endobj +2353 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [407.16 630.392 419.115 641.24] +/Subtype /Link +/A << /S /GoTo /D (page.53) >> +>> endobj +2354 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [474.546 618.436 486.501 629.285] +/Subtype /Link +/A << /S /GoTo /D (page.53) >> +>> endobj +2355 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [392.078 606.481 404.033 617.329] +/Subtype /Link +/A << /S /GoTo /D (page.44) >> +>> endobj +2356 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [436.301 594.526 448.256 605.374] +/Subtype /Link +/A << /S /GoTo /D (page.44) >> +>> endobj +2357 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [416.458 582.571 428.414 593.419] +/Subtype /Link +/A << /S /GoTo /D (page.53) >> +>> endobj +2358 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [474.546 570.616 486.501 581.464] +/Subtype /Link +/A << /S /GoTo /D (page.53) >> +>> endobj +2359 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [382.89 558.661 394.845 569.509] +/Subtype /Link +/A << /S /GoTo /D (page.39) >> +>> endobj +2360 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [446.125 546.705 458.08 557.554] +/Subtype /Link +/A << /S /GoTo /D (page.39) >> +>> endobj +2361 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [382.06 534.75 394.015 545.598] +/Subtype /Link +/A << /S /GoTo /D (page.40) >> +>> endobj +2362 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [446.125 522.795 458.08 533.643] +/Subtype /Link +/A << /S /GoTo /D (page.40) >> +>> endobj +2363 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [388.037 510.84 399.992 521.688] +/Subtype /Link +/A << /S /GoTo /D (page.56) >> +>> endobj +2364 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [421.633 498.885 433.589 509.733] +/Subtype /Link +/A << /S /GoTo /D (page.56) >> +>> endobj +2365 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [356.323 486.93 368.278 497.667] +/Subtype /Link +/A << /S /GoTo /D (page.33) >> +>> endobj +2366 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [459.602 474.974 471.557 485.823] +/Subtype /Link +/A << /S /GoTo /D (page.33) >> +>> endobj +2367 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [377.3 463.019 389.255 473.757] +/Subtype /Link +/A << /S /GoTo /D (page.71) >> +>> endobj +2368 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [438.349 451.064 450.304 461.912] +/Subtype /Link +/A << /S /GoTo /D (page.71) >> +>> endobj +2369 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [364.929 439.109 376.885 449.957] +/Subtype /Link +/A << /S /GoTo /D (page.17) >> +>> endobj +2370 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [436.218 427.154 448.173 437.891] +/Subtype /Link +/A << /S /GoTo /D (page.17) >> +>> endobj +2371 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [398.055 415.199 410.01 426.047] +/Subtype /Link +/A << /S /GoTo /D (page.70) >> +>> endobj +2372 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [434.419 403.243 446.374 414.092] +/Subtype /Link +/A << /S /GoTo /D (page.70) >> +>> endobj +2373 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [376.276 391.288 388.231 402.136] +/Subtype /Link +/A << /S /GoTo /D (page.16) >> +>> endobj +2374 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [415.462 379.333 427.417 390.071] +/Subtype /Link +/A << /S /GoTo /D (page.16) >> +>> endobj +2375 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [364.154 367.378 376.11 378.115] +/Subtype /Link +/A << /S /GoTo /D (page.48) >> +>> endobj +2376 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [380.205 367.378 392.161 378.115] +/Subtype /Link +/A << /S /GoTo /D (page.63) >> +>> endobj +2377 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [450.414 355.423 462.37 366.271] +/Subtype /Link +/A << /S /GoTo /D (page.48) >> +>> endobj +2378 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [425.868 343.468 437.823 354.205] +/Subtype /Link +/A << /S /GoTo /D (page.63) >> +>> endobj +2379 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [404.974 331.512 416.929 342.361] +/Subtype /Link +/A << /S /GoTo /D (page.40) >> +>> endobj +2380 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [446.125 319.557 458.08 330.405] +/Subtype /Link +/A << /S /GoTo /D (page.40) >> +>> endobj +2381 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [414.494 297.639 426.449 308.488] +/Subtype /Link +/A << /S /GoTo /D (page.18) >> +>> endobj +2382 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [349.958 285.684 361.913 296.422] +/Subtype /Link +/A << /S /GoTo /D (page.70) >> +>> endobj +2383 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [434.419 273.729 446.374 284.577] +/Subtype /Link +/A << /S /GoTo /D (page.70) >> +>> endobj +2384 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [372.567 261.774 384.523 272.511] +/Subtype /Link +/A << /S /GoTo /D (page.14) >> +>> endobj +2385 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [419.06 249.819 431.015 260.667] +/Subtype /Link +/A << /S /GoTo /D (page.25) >> +>> endobj +2386 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [413.58 237.864 425.536 248.712] +/Subtype /Link +/A << /S /GoTo /D (page.26) >> +>> endobj +2387 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [412.612 225.908 424.567 236.646] +/Subtype /Link +/A << /S /GoTo /D (page.46) >> +>> endobj +2388 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [393.295 213.953 405.25 224.691] +/Subtype /Link +/A << /S /GoTo /D (page.60) >> +>> endobj +2389 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [392.908 201.998 404.863 212.736] +/Subtype /Link +/A << /S /GoTo /D (page.64) >> +>> endobj +2390 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [399.079 190.043 411.034 200.891] +/Subtype /Link +/A << /S /GoTo /D (page.25) >> +>> endobj +2391 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [420.167 178.088 432.122 188.825] +/Subtype /Link +/A << /S /GoTo /D (page.65) >> +>> endobj +2392 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [409.955 166.133 421.91 176.981] +/Subtype /Link +/A << /S /GoTo /D (page.72) >> +>> endobj +2393 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [406.385 154.177 418.34 165.026] +/Subtype /Link +/A << /S /GoTo /D (page.73) >> +>> endobj +2394 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [410.121 142.222 422.076 153.07] +/Subtype /Link +/A << /S /GoTo /D (page.74) >> +>> endobj +2395 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [410.661 130.267 422.616 141.115] +/Subtype /Link +/A << /S /GoTo /D (page.77) >> +>> endobj +2396 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [376.11 118.312 388.065 129.16] +/Subtype /Link +/A << /S /GoTo /D (page.51) >> +>> endobj +2397 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [428.414 106.357 440.369 117.094] +/Subtype /Link +/A << /S /GoTo /D (page.38) >> +>> endobj +2398 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [415.85 94.402 427.805 105.139] +/Subtype /Link +/A << /S /GoTo /D (page.18) >> +>> endobj +2399 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [401.459 82.446 413.414 93.184] +/Subtype /Link +/A << /S /GoTo /D (page.70) >> +>> endobj +2292 0 obj << +/D [2290 0 R /XYZ 109.858 727.97 null] +>> endobj +2289 0 obj << +/Font << /F29 416 0 R /F8 369 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +2402 0 obj << +/Length 5290 +/Filter /FlateDecode +>> +stream +xڥ][sݸ~УT5OorJAxؓ qpJŗQ_?6gOahf9|pv?1GY?"NY',(bξŸ^^}+gY0UD/1-._[ٿ_|%=.>v߿:X[T?ϚKTܙ~&7ʥR=j8rH$epЕWQg%a}]__^tWxs| io;]S?13ak?ivjfnÜ"9QC pި'#z'=Ax!g Ѕ? +\g0q!.R-"ͬ[\d2" !ŋiKQ jw~ˮH+v'"v#(R"+Jt-W0sUPH~v]Z>zaC$i;֛}ϯWGHlsvx>^T/ӏBz5kSNҕnoLM\r7c?ҁxK]1ϫb @@.R[oUC anfU?v3vqSQ:HkvjKfōc?CPdeXoT0ߌ.ZǏ~ˢ f~f4Ь$2P VH›óko+A|R[3f!n!Pp) NFE[El)j(KDBQD1-!%R!I53"rH7:E'13aQ1.30&A+o V'&VQibhc +E'֫!`C@ 3E8K[\E˜$r9}Ж5_ yR)7`fZʡH%,'y\L?=4xKy;fr$]O[(_8Εi~i5\wc%y<]AkMNTS~2cC a< w7wvqV9qԚ3؝4#6+'<J8_X Qc,O;zwWٸ&;kLE圙Z5b9&3 0!֩r +?Di|B2`f"Y$mc1PE8W4Q*8FnEcqŰ81TT%5E&n*RSCq2N}s/`'$I !n4x)72,TЙE%IYQc.}e=~5lW45.)赦Kp]Zv FA#$1]ayp+_cͫ^0|v;}Aoh]YvTA9֝ {"iMs4&HKjHKnρ(u>=}F$Nվ/n}8j7A!;_x kIDD ,`?tg6܈T[7␴ވ3KCJȰ<_x?>/ۧ@W^7,YvqU?p<?; ~GuQ >V7eSNYdT( 1~10?,ZqQzJm sRO݃L/ +Jr_@ (DD?|.bޝ+ߪ7%M[Oz)%X-p,{lz*irz KY*p ӍYƢJS4FAg +7X%Ԃ@ɿD4~n&"l{M-AH-QDWjxK |q~5@+ Ka%MW[oAJ$VDN + TR'"6lq[IqPx/p]+fWտU%,j 49jn*x+p|A`0滒"CCl׳W_.i^Is%aRzz4ɱQsZd^!b^C~J5^OZlX+ɰ(RrUPw3[IIioVsVaQ]kly6ZI[KK$zcBkf7Jm`&%ͭRemY*ɰh΋M풺}~4J V8ƌq5Vaev_3oIk!d1%ˍ#H|N?"Ǿs~nUWGAwK6nQ(ASΰ"IFGlDᓷxxxz3^=?]$M[o`p+X$p-1, M@\'l L&Ga̭7q` $y%0&'K`ΗMW0׳)Ic8W`[d8oŸs?KHV(X%ɰ2; J/nHk!dm¦vOل &z~9[W?I^Kaz)ir|zd8oB9.< *irz dIJ2Es|ze8gzt/<ҏC]m-ö!@[˶"~Dqtӧ*ze!s5&t/:q(ߘRLH]M$M[o9/HSfȗ$y#("cJ"Y5V3/ICf[ǻtJ>"6k#[b5ے9vcj5 c[vSH-sYᄠendstream +endobj +2401 0 obj << +/Type /Page +/Contents 2402 0 R +/Resources 2400 0 R +/MediaBox [0 0 612 792] +/Parent 2054 0 R +/Annots [ 2404 0 R 2405 0 R 2406 0 R 2407 0 R 2408 0 R 2409 0 R 2410 0 R 2411 0 R 2412 0 R 2413 0 R 2414 0 R 2415 0 R 2416 0 R 2417 0 R 2418 0 R 2419 0 R 2420 0 R 2421 0 R 2422 0 R 2423 0 R 2424 0 R 2425 0 R 2426 0 R 2427 0 R 2428 0 R 2429 0 R 2430 0 R 2431 0 R 2432 0 R 2433 0 R 2434 0 R 2435 0 R 2436 0 R 2437 0 R 2438 0 R 2439 0 R 2440 0 R 2441 0 R 2442 0 R 2443 0 R 2444 0 R 2445 0 R 2446 0 R 2447 0 R 2448 0 R 2449 0 R 2450 0 R 2451 0 R 2452 0 R 2453 0 R 2454 0 R 2455 0 R 2456 0 R 2457 0 R 2458 0 R 2459 0 R 2460 0 R 2461 0 R 2462 0 R 2463 0 R 2464 0 R 2465 0 R 2466 0 R 2467 0 R 2468 0 R 2469 0 R 2470 0 R 2471 0 R 2472 0 R 2473 0 R 2474 0 R 2475 0 R 2476 0 R 2477 0 R 2478 0 R 2479 0 R 2480 0 R 2481 0 R 2482 0 R 2483 0 R 2484 0 R 2485 0 R 2486 0 R 2487 0 R 2488 0 R 2489 0 R 2490 0 R 2491 0 R 2492 0 R 2493 0 R 2494 0 R 2495 0 R 2496 0 R 2497 0 R 2498 0 R 2499 0 R 2500 0 R 2501 0 R 2502 0 R 2503 0 R 2504 0 R 2505 0 R 2506 0 R 2507 0 R 2508 0 R 2509 0 R 2510 0 R 2511 0 R 2512 0 R 2513 0 R 2514 0 R 2515 0 R 2516 0 R 2517 0 R ] +>> endobj +2404 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [215.739 690.167 227.694 701.016] +/Subtype /Link +/A << /S /GoTo /D (page.70) >> +>> endobj +2405 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [186.211 678.212 198.166 689.06] +/Subtype /Link +/A << /S /GoTo /D (page.72) >> +>> endobj +2406 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [176.857 666.257 188.812 676.995] +/Subtype /Link +/A << /S /GoTo /D (page.15) >> +>> endobj +2407 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [192.908 666.257 204.863 676.995] +/Subtype /Link +/A << /S /GoTo /D (page.16) >> +>> endobj +2408 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [155.216 654.302 167.171 665.15] +/Subtype /Link +/A << /S /GoTo /D (page.15) >> +>> endobj +2409 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [158.703 642.347 170.658 653.195] +/Subtype /Link +/A << /S /GoTo /D (page.15) >> +>> endobj +2410 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [157.291 630.392 169.247 641.24] +/Subtype /Link +/A << /S /GoTo /D (page.16) >> +>> endobj +2411 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [160.059 618.436 172.014 629.174] +/Subtype /Link +/A << /S /GoTo /D (page.16) >> +>> endobj +2412 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [152.033 606.481 163.988 617.219] +/Subtype /Link +/A << /S /GoTo /D (page.16) >> +>> endobj +2413 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [177.521 594.526 189.476 605.374] +/Subtype /Link +/A << /S /GoTo /D (page.16) >> +>> endobj +2414 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [177.244 582.571 189.199 593.419] +/Subtype /Link +/A << /S /GoTo /D (page.16) >> +>> endobj +2415 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [144.838 570.616 156.793 581.464] +/Subtype /Link +/A << /S /GoTo /D (page.72) >> +>> endobj +2416 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [201.182 558.661 213.138 569.509] +/Subtype /Link +/A << /S /GoTo /D (page.72) >> +>> endobj +2417 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [171.682 546.705 183.637 557.554] +/Subtype /Link +/A << /S /GoTo /D (page.73) >> +>> endobj +2418 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [201.182 534.75 213.138 545.598] +/Subtype /Link +/A << /S /GoTo /D (page.73) >> +>> endobj +2419 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [148.768 522.795 160.723 533.643] +/Subtype /Link +/A << /S /GoTo /D (page.73) >> +>> endobj +2420 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [201.182 510.84 213.138 521.688] +/Subtype /Link +/A << /S /GoTo /D (page.73) >> +>> endobj +2421 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [179.431 498.885 191.386 509.733] +/Subtype /Link +/A << /S /GoTo /D (page.17) >> +>> endobj +2422 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [195.482 498.885 207.437 509.733] +/Subtype /Link +/A << /S /GoTo /D (page.20) >> +>> endobj +2423 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [217.538 486.93 229.493 497.667] +/Subtype /Link +/A << /S /GoTo /D (page.17) >> +>> endobj +2424 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [216.237 474.974 228.192 485.712] +/Subtype /Link +/A << /S /GoTo /D (page.20) >> +>> endobj +2425 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [131.831 463.019 143.786 473.757] +/Subtype /Link +/A << /S /GoTo /D (page.29) >> +>> endobj +2426 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [231.707 451.064 243.662 461.912] +/Subtype /Link +/A << /S /GoTo /D (page.29) >> +>> endobj +2427 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [154.967 439.109 166.922 449.846] +/Subtype /Link +/A << /S /GoTo /D (page.70) >> +>> endobj +2428 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [183.167 427.154 195.122 438.002] +/Subtype /Link +/A << /S /GoTo /D (page.77) >> +>> endobj +2429 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [199.218 427.154 211.173 438.002] +/Subtype /Link +/A << /S /GoTo /D (page.78) >> +>> endobj +2430 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [219.06 415.199 231.015 426.047] +/Subtype /Link +/A << /S /GoTo /D (page.67) >> +>> endobj +2431 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [183.914 403.243 195.869 414.092] +/Subtype /Link +/A << /S /GoTo /D (page.67) >> +>> endobj +2432 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [184.274 391.288 196.229 402.136] +/Subtype /Link +/A << /S /GoTo /D (page.67) >> +>> endobj +2433 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [200.325 391.288 212.28 402.136] +/Subtype /Link +/A << /S /GoTo /D (page.68) >> +>> endobj +2434 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [192.437 379.333 204.393 390.181] +/Subtype /Link +/A << /S /GoTo /D (page.55) >> +>> endobj +2435 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [194.402 367.378 206.357 378.115] +/Subtype /Link +/A << /S /GoTo /D (page.54) >> +>> endobj +2436 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [179.154 355.423 191.109 366.16] +/Subtype /Link +/A << /S /GoTo /D (page.54) >> +>> endobj +2437 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [215.407 343.468 227.362 354.316] +/Subtype /Link +/A << /S /GoTo /D (page.54) >> +>> endobj +2438 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [215.407 331.512 227.362 342.361] +/Subtype /Link +/A << /S /GoTo /D (page.55) >> +>> endobj +2439 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [181.229 319.557 193.185 330.405] +/Subtype /Link +/A << /S /GoTo /D (page.53) >> +>> endobj +2440 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [213.47 307.602 225.425 318.45] +/Subtype /Link +/A << /S /GoTo /D (page.27) >> +>> endobj +2441 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [170.104 295.647 182.06 306.384] +/Subtype /Link +/A << /S /GoTo /D (page.27) >> +>> endobj +2442 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [174.726 283.692 186.681 294.429] +/Subtype /Link +/A << /S /GoTo /D (page.27) >> +>> endobj +2443 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [230.821 271.737 242.777 282.585] +/Subtype /Link +/A << /S /GoTo /D (page.49) >> +>> endobj +2444 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [187.179 259.781 199.135 270.63] +/Subtype /Link +/A << /S /GoTo /D (page.28) >> +>> endobj +2445 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [187.622 247.826 199.577 258.674] +/Subtype /Link +/A << /S /GoTo /D (page.47) >> +>> endobj +2446 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [158.703 235.871 170.658 246.719] +/Subtype /Link +/A << /S /GoTo /D (page.47) >> +>> endobj +2447 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [198.277 223.916 210.232 234.764] +/Subtype /Link +/A << /S /GoTo /D (page.74) >> +>> endobj +2448 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [214.328 223.916 226.283 234.764] +/Subtype /Link +/A << /S /GoTo /D (page.75) >> +>> endobj +2449 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [158.703 211.961 170.658 222.809] +/Subtype /Link +/A << /S /GoTo /D (page.74) >> +>> endobj +2450 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [172.54 200.006 184.495 210.854] +/Subtype /Link +/A << /S /GoTo /D (page.75) >> +>> endobj +2451 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [196.644 188.05 208.599 198.899] +/Subtype /Link +/A << /S /GoTo /D (page.75) >> +>> endobj +2452 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [163.684 176.095 175.639 186.833] +/Subtype /Link +/A << /S /GoTo /D (page.75) >> +>> endobj +2453 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [172.374 164.14 184.329 174.988] +/Subtype /Link +/A << /S /GoTo /D (page.75) >> +>> endobj +2454 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [181.257 152.185 193.212 163.033] +/Subtype /Link +/A << /S /GoTo /D (page.75) >> +>> endobj +2455 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [211.809 140.23 223.764 151.078] +/Subtype /Link +/A << /S /GoTo /D (page.47) >> +>> endobj +2456 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [226.753 140.23 238.708 151.078] +/Subtype /Link +/A << /S /GoTo /D (page.50) >> +>> endobj +2457 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [198.249 128.275 210.204 139.123] +/Subtype /Link +/A << /S /GoTo /D (page.48) >> +>> endobj +2458 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [163.684 116.319 175.639 127.057] +/Subtype /Link +/A << /S /GoTo /D (page.49) >> +>> endobj +2459 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [179.431 104.364 191.386 115.212] +/Subtype /Link +/A << /S /GoTo /D (page.48) >> +>> endobj +2460 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [198.996 92.409 210.951 103.257] +/Subtype /Link +/A << /S /GoTo /D (page.48) >> +>> endobj +2461 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [208.046 80.454 220.001 91.302] +/Subtype /Link +/A << /S /GoTo /D (page.48) >> +>> endobj +2462 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [415.739 690.167 427.694 701.016] +/Subtype /Link +/A << /S /GoTo /D (page.48) >> +>> endobj +2463 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [446.872 678.212 458.827 689.06] +/Subtype /Link +/A << /S /GoTo /D (page.49) >> +>> endobj +2464 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [410.315 666.257 422.27 677.105] +/Subtype /Link +/A << /S /GoTo /D (page.49) >> +>> endobj +2465 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [410.453 654.302 422.408 665.039] +/Subtype /Link +/A << /S /GoTo /D (page.49) >> +>> endobj +2466 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [409.18 642.347 421.135 653.195] +/Subtype /Link +/A << /S /GoTo /D (page.50) >> +>> endobj +2467 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [431.956 630.392 443.911 641.24] +/Subtype /Link +/A << /S /GoTo /D (page.50) >> +>> endobj +2468 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [431.126 618.436 443.081 629.285] +/Subtype /Link +/A << /S /GoTo /D (page.50) >> +>> endobj +2469 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [423.543 606.481 435.498 617.329] +/Subtype /Link +/A << /S /GoTo /D (page.48) >> +>> endobj +2470 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [384.08 594.526 396.035 605.264] +/Subtype /Link +/A << /S /GoTo /D (page.48) >> +>> endobj +2471 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [430.462 582.571 442.417 593.419] +/Subtype /Link +/A << /S /GoTo /D (page.29) >> +>> endobj +2472 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [386.626 570.616 398.581 581.353] +/Subtype /Link +/A << /S /GoTo /D (page.29) >> +>> endobj +2473 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [371.128 558.661 383.084 569.509] +/Subtype /Link +/A << /S /GoTo /D (page.29) >> +>> endobj +2474 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [377.77 546.705 389.725 557.554] +/Subtype /Link +/A << /S /GoTo /D (page.29) >> +>> endobj +2475 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [370.436 534.75 382.392 545.488] +/Subtype /Link +/A << /S /GoTo /D (page.29) >> +>> endobj +2476 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [426.947 522.795 438.902 533.533] +/Subtype /Link +/A << /S /GoTo /D (page.29) >> +>> endobj +2477 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [441.891 522.795 453.846 533.533] +/Subtype /Link +/A << /S /GoTo /D (page.32) >> +>> endobj +2478 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [398.941 510.84 410.896 521.688] +/Subtype /Link +/A << /S /GoTo /D (page.30) >> +>> endobj +2479 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [437.684 498.885 449.64 509.733] +/Subtype /Link +/A << /S /GoTo /D (page.30) >> +>> endobj +2480 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [400.518 486.93 412.473 497.778] +/Subtype /Link +/A << /S /GoTo /D (page.30) >> +>> endobj +2481 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [405.998 474.974 417.953 485.823] +/Subtype /Link +/A << /S /GoTo /D (page.30) >> +>> endobj +2482 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [389.808 463.019 401.763 473.867] +/Subtype /Link +/A << /S /GoTo /D (page.30) >> +>> endobj +2483 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [429.825 451.064 441.78 461.912] +/Subtype /Link +/A << /S /GoTo /D (page.30) >> +>> endobj +2484 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [423.183 439.109 435.138 449.957] +/Subtype /Link +/A << /S /GoTo /D (page.30) >> +>> endobj +2485 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [414.231 427.154 426.186 438.002] +/Subtype /Link +/A << /S /GoTo /D (page.31) >> +>> endobj +2486 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [405.679 415.199 417.635 426.047] +/Subtype /Link +/A << /S /GoTo /D (page.31) >> +>> endobj +2487 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [404.199 403.243 416.154 414.092] +/Subtype /Link +/A << /S /GoTo /D (page.31) >> +>> endobj +2488 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [383.775 391.288 395.731 402.026] +/Subtype /Link +/A << /S /GoTo /D (page.31) >> +>> endobj +2489 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [383.858 379.333 395.814 390.071] +/Subtype /Link +/A << /S /GoTo /D (page.31) >> +>> endobj +2490 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [413.912 367.378 425.868 378.115] +/Subtype /Link +/A << /S /GoTo /D (page.32) >> +>> endobj +2491 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [408.35 355.423 420.305 366.271] +/Subtype /Link +/A << /S /GoTo /D (page.31) >> +>> endobj +2492 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [397.695 343.468 409.651 354.205] +/Subtype /Link +/A << /S /GoTo /D (page.31) >> +>> endobj +2493 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [417.925 331.512 429.88 342.361] +/Subtype /Link +/A << /S /GoTo /D (page.31) >> +>> endobj +2494 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [439.677 319.557 451.632 330.405] +/Subtype /Link +/A << /S /GoTo /D (page.32) >> +>> endobj +2495 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [455.728 319.557 467.683 330.405] +/Subtype /Link +/A << /S /GoTo /D (page.33) >> +>> endobj +2496 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [409.83 307.602 421.786 318.45] +/Subtype /Link +/A << /S /GoTo /D (page.32) >> +>> endobj +2497 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [389.808 295.647 401.763 306.495] +/Subtype /Link +/A << /S /GoTo /D (page.32) >> +>> endobj +2498 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [399.494 283.692 411.449 294.54] +/Subtype /Link +/A << /S /GoTo /D (page.33) >> +>> endobj +2499 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [376.248 271.737 388.203 282.474] +/Subtype /Link +/A << /S /GoTo /D (page.33) >> +>> endobj +2500 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [433.755 259.781 445.71 270.63] +/Subtype /Link +/A << /S /GoTo /D (page.76) >> +>> endobj +2501 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [449.806 259.781 461.761 270.63] +/Subtype /Link +/A << /S /GoTo /D (page.77) >> +>> endobj +2502 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [395.343 247.826 407.298 258.674] +/Subtype /Link +/A << /S /GoTo /D (page.76) >> +>> endobj +2503 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [393.503 235.871 405.458 246.719] +/Subtype /Link +/A << /S /GoTo /D (page.76) >> +>> endobj +2504 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [394.859 223.916 406.814 234.653] +/Subtype /Link +/A << /S /GoTo /D (page.77) >> +>> endobj +2505 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [423.944 211.961 435.899 222.809] +/Subtype /Link +/A << /S /GoTo /D (page.77) >> +>> endobj +2506 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [399.633 200.006 411.588 210.743] +/Subtype /Link +/A << /S /GoTo /D (page.76) >> +>> endobj +2507 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [463.366 188.05 475.321 198.788] +/Subtype /Link +/A << /S /GoTo /D (page.50) >> +>> endobj +2508 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [416.292 176.095 428.248 186.833] +/Subtype /Link +/A << /S /GoTo /D (page.16) >> +>> endobj +2509 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [431.236 176.095 443.192 186.833] +/Subtype /Link +/A << /S /GoTo /D (page.18) >> +>> endobj +2510 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [431.043 164.14 442.998 174.988] +/Subtype /Link +/A << /S /GoTo /D (page.17) >> +>> endobj +2511 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [408.267 152.185 420.222 162.922] +/Subtype /Link +/A << /S /GoTo /D (page.17) >> +>> endobj +2512 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [383.858 140.23 395.814 150.967] +/Subtype /Link +/A << /S /GoTo /D (page.17) >> +>> endobj +2513 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [399.771 128.275 411.726 139.123] +/Subtype /Link +/A << /S /GoTo /D (page.17) >> +>> endobj +2514 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [398.941 116.319 410.896 127.168] +/Subtype /Link +/A << /S /GoTo /D (page.17) >> +>> endobj +2515 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [416.016 104.364 427.971 115.212] +/Subtype /Link +/A << /S /GoTo /D (page.18) >> +>> endobj +2516 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [416.541 92.409 428.497 103.147] +/Subtype /Link +/A << /S /GoTo /D (page.18) >> +>> endobj +2517 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [384.855 80.454 396.81 91.302] +/Subtype /Link +/A << /S /GoTo /D (page.17) >> +>> endobj +2403 0 obj << +/D [2401 0 R /XYZ 109.858 727.97 null] +>> endobj +2400 0 obj << +/Font << /F29 416 0 R /F8 369 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +2520 0 obj << +/Length 5324 +/Filter /FlateDecode +>> +stream +xڝ]r7}WQت-\(QW7bfd&[Ko&D":RL4HpJbą~Y:_>.o>΢S_O}t.:ٯˊ.۟wcذi؋iڐ~kEK`+v1&$ۄĻpJﰳa>~/+Ⱥ4 +(l$jQ؂ji~OW;Y6r,g]ͳ\B +a!rֆFgK7\y^-`]ih+64X6{iюow {46 D{h), yBِ`m kElȱ+`P4!H`.!^ `5Q`mh}:v/s€Ev4g ^cdԄcƢ_~P|4·\ LSUìp.f"nHɎԤQDmf-22-W}mq\,m\ qz/S_:~aJmhDKB_*6EhkB(! 拉P.b2&`C+b؆P6l4"du Ļ ,m, %Buf%6X@60~]aN?*vX8jԽRO[d@z:^aDjsZ! 3Y+TS …Ev4"^[l6\X.B ckLƍ3[e*3֪̰m*3lC䢹ݵK/Əa>Cט󝛆]G7YYGma%~!ߒ<7!n:l9f.9j.f+IQJwІF#i֬ P6vF_w>Z6F؝(]!C"k…DЯBUǾMW;y/s]u&L(?&_ۧPwU; "´>hbwagmh|+sMǐ3l&,؝pSϚp{pN3hX=lT{dzEyGYlB 6[ h ,Q8&{j9%0.@2#ZE- s2̽ /IotjE М{``% 9ֆFtcK)vܠǎc0|Y 9+c$hf# |wz tp[%cX`wB #]Y9f0S؀BúR;sQ C~qAQ%$LYRP>j1Pa<}W5$n1^VZρ'lbmuh"ϐE*[. +6Ӝ0lh@n0QiQ3̹3dN E(XQ$p<''![z+dV7 h厫eidd…n +ð7x /(q1^J@YΆ` +;h$o}ߜ /yb\J +gb唐d…O!5l3:j`l䒅 +ctҙ0w^ZOBrԻ;ُj=Ɇ(,?l">ߔ0oO2zķaag>֏+'$& H-P JH䤉 +xF(VI6\0OB>dTj,B's/JRHaQaWClo )0^YIHNz +VI6\4J CYyo6׏eMv5TܰW8$p<PRvߊ (ՑzdՑdE<bĘwE 5T!$$'_LWIbIy6abf',tX1^KsjIa +6"IN~hŜT+$ iS2J,v,0 +I1e"9.ΔK0k|طqrIy>-bp~.:5 $ ISZdF# +!_ })S<)l_4IBr"{V(b$dE]v(G̷;[6-1Vayx1ϗ慕Q -S|C'!Gadx7^6Ҩ~;..2갿:| Nz](JHNz|X  :1? +sLgCSj&M{s\+$.!2^ofyku%mZQ?ZFPHw|ROeP\@͋ %ydbdFK%f_y˟j/}MSElɆC@}}mol+>E/خH% #M|W)RɄ E"zg82|c7jɚEdR s"Ua%~rm@kQ|7(Ά 'It}£>(t0Z4]!hwDT2aB͗#VO|3X3婄wRﳐb>mwPy/v=C JHNz4X)*DɆy ėɛuaN{"}wyU!%$'LWFV#/%.(Pd^?;WsuBKIM FܙznHpRRӂF4M'{czn(P|Q2w vd„"Qw锫s]֬$Www)$Ai% .rjcsendstream +endobj +2519 0 obj << +/Type /Page +/Contents 2520 0 R +/Resources 2518 0 R +/MediaBox [0 0 612 792] +/Parent 2054 0 R +/Annots [ 2522 0 R 2523 0 R 2524 0 R 2525 0 R 2526 0 R 2527 0 R 2528 0 R 2529 0 R 2530 0 R 2531 0 R 2532 0 R 2533 0 R 2534 0 R 2535 0 R 2536 0 R 2537 0 R 2538 0 R 2539 0 R 2540 0 R 2541 0 R 2542 0 R 2543 0 R 2544 0 R 2545 0 R 2546 0 R 2547 0 R 2548 0 R 2549 0 R 2550 0 R 2551 0 R 2552 0 R 2553 0 R 2554 0 R 2555 0 R 2556 0 R 2557 0 R 2558 0 R 2559 0 R 2560 0 R 2561 0 R 2562 0 R 2563 0 R 2564 0 R 2565 0 R 2566 0 R 2567 0 R 2568 0 R 2569 0 R 2570 0 R 2571 0 R 2572 0 R 2573 0 R 2574 0 R 2575 0 R 2576 0 R 2577 0 R 2578 0 R 2579 0 R 2580 0 R 2581 0 R 2582 0 R 2583 0 R 2584 0 R 2585 0 R 2586 0 R 2587 0 R 2588 0 R 2589 0 R 2590 0 R 2591 0 R 2592 0 R 2593 0 R 2594 0 R 2595 0 R 2596 0 R 2597 0 R 2598 0 R 2599 0 R 2600 0 R 2601 0 R 2602 0 R 2603 0 R 2604 0 R 2605 0 R 2606 0 R 2607 0 R 2608 0 R 2609 0 R 2610 0 R 2611 0 R 2612 0 R 2613 0 R 2614 0 R 2615 0 R 2616 0 R 2617 0 R 2618 0 R 2619 0 R 2620 0 R 2621 0 R 2622 0 R 2623 0 R 2624 0 R 2625 0 R 2626 0 R 2627 0 R 2628 0 R 2629 0 R 2630 0 R 2631 0 R 2632 0 R 2633 0 R 2634 0 R ] +>> endobj +2522 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [199.356 690.167 211.311 701.016] +/Subtype /Link +/A << /S /GoTo /D (page.17) >> +>> endobj +2523 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [201.625 678.212 213.58 689.06] +/Subtype /Link +/A << /S /GoTo /D (page.33) >> +>> endobj +2524 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [217.676 678.212 229.631 689.06] +/Subtype /Link +/A << /S /GoTo /D (page.34) >> +>> endobj +2525 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [163.684 666.257 175.639 676.995] +/Subtype /Link +/A << /S /GoTo /D (page.34) >> +>> endobj +2526 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [192.659 654.302 204.614 665.15] +/Subtype /Link +/A << /S /GoTo /D (page.33) >> +>> endobj +2527 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [177.244 642.347 189.199 653.195] +/Subtype /Link +/A << /S /GoTo /D (page.33) >> +>> endobj +2528 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [201.072 630.392 213.027 641.24] +/Subtype /Link +/A << /S /GoTo /D (page.34) >> +>> endobj +2529 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [197.197 618.436 209.153 629.285] +/Subtype /Link +/A << /S /GoTo /D (page.34) >> +>> endobj +2530 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [185.519 606.481 197.474 617.329] +/Subtype /Link +/A << /S /GoTo /D (page.34) >> +>> endobj +2531 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [165.095 594.526 177.051 605.264] +/Subtype /Link +/A << /S /GoTo /D (page.34) >> +>> endobj +2532 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [194.209 582.571 206.164 593.308] +/Subtype /Link +/A << /S /GoTo /D (page.60) >> +>> endobj +2533 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [209.153 582.571 221.108 593.308] +/Subtype /Link +/A << /S /GoTo /D (page.63) >> +>> endobj +2534 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [163.684 570.616 175.639 581.353] +/Subtype /Link +/A << /S /GoTo /D (page.61) >> +>> endobj +2535 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [179.431 558.661 191.386 569.509] +/Subtype /Link +/A << /S /GoTo /D (page.61) >> +>> endobj +2536 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [188.065 546.705 200.02 557.554] +/Subtype /Link +/A << /S /GoTo /D (page.61) >> +>> endobj +2537 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [208.046 534.75 220.001 545.598] +/Subtype /Link +/A << /S /GoTo /D (page.61) >> +>> endobj +2538 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [182.198 522.795 194.153 533.643] +/Subtype /Link +/A << /S /GoTo /D (page.61) >> +>> endobj +2539 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [180.261 510.84 192.216 521.688] +/Subtype /Link +/A << /S /GoTo /D (page.61) >> +>> endobj +2540 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [228.192 498.885 240.147 509.733] +/Subtype /Link +/A << /S /GoTo /D (page.62) >> +>> endobj +2541 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [180.814 486.93 192.769 497.778] +/Subtype /Link +/A << /S /GoTo /D (page.62) >> +>> endobj +2542 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [191.635 474.974 203.59 485.823] +/Subtype /Link +/A << /S /GoTo /D (page.62) >> +>> endobj +2543 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [191.773 463.019 203.728 473.757] +/Subtype /Link +/A << /S /GoTo /D (page.62) >> +>> endobj +2544 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [213.276 451.064 225.231 461.912] +/Subtype /Link +/A << /S /GoTo /D (page.62) >> +>> endobj +2545 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [212.446 439.109 224.401 449.957] +/Subtype /Link +/A << /S /GoTo /D (page.63) >> +>> endobj +2546 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [188.065 427.154 200.02 438.002] +/Subtype /Link +/A << /S /GoTo /D (page.61) >> +>> endobj +2547 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [231.015 415.199 242.97 426.047] +/Subtype /Link +/A << /S /GoTo /D (page.35) >> +>> endobj +2548 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [247.066 415.199 259.021 426.047] +/Subtype /Link +/A << /S /GoTo /D (page.36) >> +>> endobj +2549 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [183.997 403.243 195.952 413.981] +/Subtype /Link +/A << /S /GoTo /D (page.35) >> +>> endobj +2550 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [181.119 391.288 193.074 402.136] +/Subtype /Link +/A << /S /GoTo /D (page.35) >> +>> endobj +2551 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [182.89 379.333 194.845 390.071] +/Subtype /Link +/A << /S /GoTo /D (page.35) >> +>> endobj +2552 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [163.684 367.378 175.639 378.115] +/Subtype /Link +/A << /S /GoTo /D (page.36) >> +>> endobj +2553 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [216.016 355.423 227.971 366.271] +/Subtype /Link +/A << /S /GoTo /D (page.36) >> +>> endobj +2554 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [214.023 343.468 225.978 354.316] +/Subtype /Link +/A << /S /GoTo /D (page.36) >> +>> endobj +2555 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [166.175 331.512 178.13 342.25] +/Subtype /Link +/A << /S /GoTo /D (page.35) >> +>> endobj +2556 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [184.993 319.557 196.948 330.295] +/Subtype /Link +/A << /S /GoTo /D (page.35) >> +>> endobj +2557 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [170.215 307.602 182.17 318.34] +/Subtype /Link +/A << /S /GoTo /D (page.36) >> +>> endobj +2558 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [162.134 295.647 174.089 306.384] +/Subtype /Link +/A << /S /GoTo /D (page.36) >> +>> endobj +2559 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [199.688 283.692 211.643 294.54] +/Subtype /Link +/A << /S /GoTo /D (page.36) >> +>> endobj +2560 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [233.865 271.737 245.821 282.585] +/Subtype /Link +/A << /S /GoTo /D (page.36) >> +>> endobj +2561 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [249.916 271.737 261.872 282.585] +/Subtype /Link +/A << /S /GoTo /D (page.37) >> +>> endobj +2562 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [171.128 259.781 183.084 270.63] +/Subtype /Link +/A << /S /GoTo /D (page.37) >> +>> endobj +2563 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [186.999 247.826 198.955 258.674] +/Subtype /Link +/A << /S /GoTo /D (page.37) >> +>> endobj +2564 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [180.814 235.871 192.769 246.719] +/Subtype /Link +/A << /S /GoTo /D (page.37) >> +>> endobj +2565 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [235.941 223.916 247.896 234.764] +/Subtype /Link +/A << /S /GoTo /D (page.51) >> +>> endobj +2566 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [250.885 223.916 262.84 234.764] +/Subtype /Link +/A << /S /GoTo /D (page.55) >> +>> endobj +2567 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [176.746 211.961 188.701 222.698] +/Subtype /Link +/A << /S /GoTo /D (page.51) >> +>> endobj +2568 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [163.684 200.006 175.639 210.743] +/Subtype /Link +/A << /S /GoTo /D (page.53) >> +>> endobj +2569 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [170.16 188.05 182.115 198.899] +/Subtype /Link +/A << /S /GoTo /D (page.51) >> +>> endobj +2570 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [178.628 176.095 190.583 186.833] +/Subtype /Link +/A << /S /GoTo /D (page.51) >> +>> endobj +2571 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [178.6 164.14 190.556 174.988] +/Subtype /Link +/A << /S /GoTo /D (page.52) >> +>> endobj +2572 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [176.663 152.185 188.618 163.033] +/Subtype /Link +/A << /S /GoTo /D (page.52) >> +>> endobj +2573 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [182.779 140.23 194.734 150.967] +/Subtype /Link +/A << /S /GoTo /D (page.54) >> +>> endobj +2574 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [167.531 128.275 179.486 139.012] +/Subtype /Link +/A << /S /GoTo /D (page.54) >> +>> endobj +2575 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [203.784 116.319 215.739 127.168] +/Subtype /Link +/A << /S /GoTo /D (page.54) >> +>> endobj +2576 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [205.167 104.364 217.123 115.212] +/Subtype /Link +/A << /S /GoTo /D (page.55) >> +>> endobj +2577 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [203.784 92.409 215.739 103.257] +/Subtype /Link +/A << /S /GoTo /D (page.55) >> +>> endobj +2578 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [164.957 80.454 176.912 91.302] +/Subtype /Link +/A << /S /GoTo /D (page.52) >> +>> endobj +2579 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [379.458 690.167 391.413 701.016] +/Subtype /Link +/A << /S /GoTo /D (page.52) >> +>> endobj +2580 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [375.141 678.212 387.096 688.95] +/Subtype /Link +/A << /S /GoTo /D (page.52) >> +>> endobj +2581 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [427.085 666.257 439.04 677.105] +/Subtype /Link +/A << /S /GoTo /D (page.53) >> +>> endobj +2582 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [436.384 654.302 448.339 665.15] +/Subtype /Link +/A << /S /GoTo /D (page.53) >> +>> endobj +2583 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [377.908 642.347 389.864 653.195] +/Subtype /Link +/A << /S /GoTo /D (page.53) >> +>> endobj +2584 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [400.324 630.392 412.28 641.24] +/Subtype /Link +/A << /S /GoTo /D (page.53) >> +>> endobj +2585 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [439.76 618.436 451.715 629.174] +/Subtype /Link +/A << /S /GoTo /D (page.65) >> +>> endobj +2586 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [454.704 618.436 466.659 629.174] +/Subtype /Link +/A << /S /GoTo /D (page.68) >> +>> endobj +2587 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [391.607 606.481 403.562 617.329] +/Subtype /Link +/A << /S /GoTo /D (page.66) >> +>> endobj +2588 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [404.96 594.526 416.915 605.374] +/Subtype /Link +/A << /S /GoTo /D (page.67) >> +>> endobj +2589 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [413.954 582.571 425.909 593.419] +/Subtype /Link +/A << /S /GoTo /D (page.67) >> +>> endobj +2590 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [383.775 570.616 395.731 581.353] +/Subtype /Link +/A << /S /GoTo /D (page.66) >> +>> endobj +2591 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [451.162 558.661 463.117 569.509] +/Subtype /Link +/A << /S /GoTo /D (page.67) >> +>> endobj +2592 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [416.016 546.705 427.971 557.554] +/Subtype /Link +/A << /S /GoTo /D (page.67) >> +>> endobj +2593 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [413.193 534.75 425.148 545.598] +/Subtype /Link +/A << /S /GoTo /D (page.67) >> +>> endobj +2594 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [429.105 522.795 441.061 533.643] +/Subtype /Link +/A << /S /GoTo /D (page.68) >> +>> endobj +2595 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [381.7 510.84 393.655 521.688] +/Subtype /Link +/A << /S /GoTo /D (page.66) >> +>> endobj +2596 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [407.105 498.885 419.06 509.733] +/Subtype /Link +/A << /S /GoTo /D (page.66) >> +>> endobj +2597 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [402.815 486.93 414.77 497.778] +/Subtype /Link +/A << /S /GoTo /D (page.66) >> +>> endobj +2598 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [390.735 474.974 402.691 485.712] +/Subtype /Link +/A << /S /GoTo /D (page.66) >> +>> endobj +2599 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [420.499 463.019 432.454 473.757] +/Subtype /Link +/A << /S /GoTo /D (page.66) >> +>> endobj +2600 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [446.319 451.064 458.274 461.912] +/Subtype /Link +/A << /S /GoTo /D (page.77) >> +>> endobj +2601 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [461.263 451.064 473.218 461.912] +/Subtype /Link +/A << /S /GoTo /D (page.79) >> +>> endobj +2602 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [395.343 439.109 407.298 449.957] +/Subtype /Link +/A << /S /GoTo /D (page.77) >> +>> endobj +2603 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [382.364 427.154 394.319 437.891] +/Subtype /Link +/A << /S /GoTo /D (page.78) >> +>> endobj +2604 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [429.659 415.199 441.614 426.047] +/Subtype /Link +/A << /S /GoTo /D (page.78) >> +>> endobj +2605 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [406.136 403.243 418.091 414.092] +/Subtype /Link +/A << /S /GoTo /D (page.78) >> +>> endobj +2606 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [399.494 391.288 411.449 402.136] +/Subtype /Link +/A << /S /GoTo /D (page.78) >> +>> endobj +2607 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [433.699 379.333 445.655 390.181] +/Subtype /Link +/A << /S /GoTo /D (page.79) >> +>> endobj +2608 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [419.489 367.378 431.444 378.226] +/Subtype /Link +/A << /S /GoTo /D (page.79) >> +>> endobj +2609 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [429.783 355.423 441.739 366.271] +/Subtype /Link +/A << /S /GoTo /D (page.79) >> +>> endobj +2610 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [418.783 343.468 430.738 354.316] +/Subtype /Link +/A << /S /GoTo /D (page.77) >> +>> endobj +2611 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [399.633 331.512 411.588 342.25] +/Subtype /Link +/A << /S /GoTo /D (page.78) >> +>> endobj +2612 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [406.136 319.557 418.091 330.405] +/Subtype /Link +/A << /S /GoTo /D (page.78) >> +>> endobj +2613 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [384.827 307.602 396.782 318.45] +/Subtype /Link +/A << /S /GoTo /D (page.18) >> +>> endobj +2614 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [400.878 307.602 412.833 318.45] +/Subtype /Link +/A << /S /GoTo /D (page.19) >> +>> endobj +2615 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [450.248 295.647 462.204 306.495] +/Subtype /Link +/A << /S /GoTo /D (page.19) >> +>> endobj +2616 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [426.2 283.692 438.155 294.54] +/Subtype /Link +/A << /S /GoTo /D (page.37) >> +>> endobj +2617 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [441.144 283.692 453.099 294.54] +/Subtype /Link +/A << /S /GoTo /D (page.41) >> +>> endobj +2618 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [400.518 271.737 412.473 282.585] +/Subtype /Link +/A << /S /GoTo /D (page.37) >> +>> endobj +2619 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [426.753 259.781 438.708 270.519] +/Subtype /Link +/A << /S /GoTo /D (page.38) >> +>> endobj +2620 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [382.364 247.826 394.319 258.564] +/Subtype /Link +/A << /S /GoTo /D (page.40) >> +>> endobj +2621 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [414.3 235.871 426.255 246.719] +/Subtype /Link +/A << /S /GoTo /D (page.38) >> +>> endobj +2622 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [413.47 223.916 425.425 234.764] +/Subtype /Link +/A << /S /GoTo /D (page.38) >> +>> endobj +2623 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [414.881 211.961 426.836 222.809] +/Subtype /Link +/A << /S /GoTo /D (page.38) >> +>> endobj +2624 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [418.728 200.006 430.683 210.854] +/Subtype /Link +/A << /S /GoTo /D (page.38) >> +>> endobj +2625 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [417.898 188.05 429.853 198.899] +/Subtype /Link +/A << /S /GoTo /D (page.38) >> +>> endobj +2626 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [427.998 176.095 439.954 186.943] +/Subtype /Link +/A << /S /GoTo /D (page.38) >> +>> endobj +2627 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [427.168 164.14 439.123 174.988] +/Subtype /Link +/A << /S /GoTo /D (page.39) >> +>> endobj +2628 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [426.061 152.185 438.016 163.033] +/Subtype /Link +/A << /S /GoTo /D (page.39) >> +>> endobj +2629 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [425.231 140.23 437.186 151.078] +/Subtype /Link +/A << /S /GoTo /D (page.39) >> +>> endobj +2630 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [434.972 128.275 446.928 139.123] +/Subtype /Link +/A << /S /GoTo /D (page.41) >> +>> endobj +2631 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [469.094 116.319 481.05 127.168] +/Subtype /Link +/A << /S /GoTo /D (page.39) >> +>> endobj +2632 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [446.319 104.364 458.274 115.212] +/Subtype /Link +/A << /S /GoTo /D (page.39) >> +>> endobj +2633 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [412.695 92.409 424.65 103.147] +/Subtype /Link +/A << /S /GoTo /D (page.39) >> +>> endobj +2634 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [402.815 80.454 414.77 91.302] +/Subtype /Link +/A << /S /GoTo /D (page.39) >> +>> endobj +2521 0 obj << +/D [2519 0 R /XYZ 109.858 727.97 null] +>> endobj +2518 0 obj << +/Font << /F29 416 0 R /F8 369 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +2637 0 obj << +/Length 5453 +/Filter /FlateDecode +>> +stream +xڝ]Ys7~ׯ#-uQgW1;-jm6Go&DL:/J$Wg'`e\f9f>tb8OY?A(9u7A} gW/f9M/|-,*DhR7c݇4g<^ھ|ˋ76y֜DқiB{44*4ș"rfBSL͋:YbKq~;_vWܺXt@p?;WM.ʴcP^N:iCa =9ߣ/;q~|]???cP|ysuI1(nC M=:\mۋϻ0xpvCh6i +7x%iZ;|A1SP@xlomd݁w+~eLP1E3vQ&t豗K=^ra{[uЂ<9"ҍMǚĠ܀"z%y#d leb5S磎#Z0n1 t҄NEސWs3HMu #6D!!`07\g*Ղ3rBW=n=oR*ph箅7k~)a +^y*9`ϳJPa f2/G{(/>ojYAz"Z V0L62ʰG<ަ F/UO0t8G_a kv#3iN5FRHu&Dvh?r2iCmф25 YR'081Խ /\3':dA91ޚAj6sQ=ijC;: 6H'SAߺ)Dvv6ko$LxbIjS(Y Z 5Dke3쯥O腜>.>ɴc+rd%iC/Y >!kYMի KZ'"H1iCSb_OxKd?AS,S/,Er`bIdXkjB`;6  $[/ at0 suB=b5q]- ފ1nCNiāq[_dqjPpBHk_܌ql٘qM]c6Y)@6ŦzṌ'9"vﭗa}K `-eO?nj!o=ױ/6Ekէex܆r!a3.wfWW&t|ѤfvGd @BQzP:T2,=ՖP.^iXBdAkX{c_E%iCm25Xrmw(@r$!l9`wD{qF N'Ø0d?gAr0u"hmW6najy[ MYl@3%m#+5c4M|sOD=V ݡ?A~M;dAO7z#Y ~'Z¢MO7v3>qԬ%mYNn[!5%mA9G:xiR܅MZzcm\]-'T{3 + liE8[!P+w.%/5ۼsYۻtbJZPۺE֘ y>yXm "hAv*/ 5 g- e-`߷AAdAkkj3:iC-xPi,t?쵾Ädi.m Rw˰O~=>LD;GdAkpd܆!-79kq셿^bއQI8i t.AjoD4%m(+M'Y ЪIኟT]bZy"d!&ma &5,6Ur确 +{zj\3@,HtT҂rx8@+z;n_?՘+v}U)a5Cv%R퍐4,e҆rp252 grʼxBڌT^ Gk]-j*SpIJ8֚;#:na}=vCTIeHt7|"PoPf '˜YT^<t8!KKAuYKn;NZ vQ2!!*g9KrTP~\{ +U- ߖms?"v-o 8:|0[&u<x>B˄Ĺ 4yd$Z#'D5<Y2¯}9e_Da斉X5H˄hĹPPDsea"v;&3T'p ɱs퍾aY&L25{ w-U^\xOs8ފBZ)S&Z@D ~ +=gT(,Gr=S{8J 5KU&u??gmֆ W8nڐc&!g}-Qo/0/ Xz3BM&$Gε}bO9n2p7 97[7וe6'0 qs)-YF2ɰ֨1#zpLusyf z]Br\{#HiRtIbmb H{v0@3g3 'ŒuI3Qdqd ^SXYf# koĬ%ZbrLwcAQ,^ጅ?RKu@ d^Br\{{0,dXk䀈/ۨ\eXS'pw ɱis퍁.ɰ֨?ֽhf__H/('v hs݂zc k'$[FWҢ^,Cw Qisu 5K25 + +JInA-_O%$G͵=V'K25 + +=C ڴpuOc +%ZS\:ud貙nԑSG;~~NKxg-߿:,֓U Hs퍈Р2"GW%Z**/[wR!UGpӨSh䨔v;2}7I_E<_a䛐j. Rz;e8kapD\|opXᗏ\a!7@$$G̵7@i{#m g-%Dp9DlY|Lb>IHBkoBZ!"-Dąc?e]l[Tٚd(xCX-8&03bm{ L䘒z`2I5F>!C/GVjj&d#ARC$T|LͤWVbS9IHkw\wGq$La ?Ry@[`LE\O$ Útׯwb=#hg*R AJUd'mW2Ϛ~@U/˜ +!?^GYK Qhꯤp3z'e^ SBr|\{sIűOIF]˳_`/W!)!9:h5&@JS/ +NH x_g_Sx丟Xamɠ3 X1|lm79̵7ΞqHIOD)Yd궽U'{eXЏ8Z#鮿68h8Q#J.yw\[<%$̵]b> endobj +2639 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [183.305 690.167 195.26 701.016] +/Subtype /Link +/A << /S /GoTo /D (page.40) >> +>> endobj +2640 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [206.219 678.212 218.174 689.06] +/Subtype /Link +/A << /S /GoTo /D (page.40) >> +>> endobj +2641 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [218.534 666.257 230.489 677.105] +/Subtype /Link +/A << /S /GoTo /D (page.40) >> +>> endobj +2642 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [212.003 654.302 223.958 665.15] +/Subtype /Link +/A << /S /GoTo /D (page.41) >> +>> endobj +2643 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [211.145 642.347 223.1 653.084] +/Subtype /Link +/A << /S /GoTo /D (page.55) >> +>> endobj +2644 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [195.482 630.392 207.437 641.24] +/Subtype /Link +/A << /S /GoTo /D (page.57) >> +>> endobj +2645 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [183.028 618.436 194.983 629.285] +/Subtype /Link +/A << /S /GoTo /D (page.55) >> +>> endobj +2646 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [197.972 618.436 209.927 629.285] +/Subtype /Link +/A << /S /GoTo /D (page.57) >> +>> endobj +2647 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [180.261 606.481 192.216 617.329] +/Subtype /Link +/A << /S /GoTo /D (page.56) >> +>> endobj +2648 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [189.587 594.526 201.542 605.264] +/Subtype /Link +/A << /S /GoTo /D (page.56) >> +>> endobj +2649 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [180.814 582.571 192.769 593.419] +/Subtype /Link +/A << /S /GoTo /D (page.57) >> +>> endobj +2650 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [197.17 570.616 209.125 581.464] +/Subtype /Link +/A << /S /GoTo /D (page.56) >> +>> endobj +2651 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [177.632 558.661 189.587 569.509] +/Subtype /Link +/A << /S /GoTo /D (page.56) >> +>> endobj +2652 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [184.135 546.705 196.09 557.554] +/Subtype /Link +/A << /S /GoTo /D (page.56) >> +>> endobj +2653 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [189.283 534.75 201.238 545.598] +/Subtype /Link +/A << /S /GoTo /D (page.56) >> +>> endobj +2654 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [164.071 522.795 176.027 533.533] +/Subtype /Link +/A << /S /GoTo /D (page.19) >> +>> endobj +2655 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [194.375 510.84 206.33 521.577] +/Subtype /Link +/A << /S /GoTo /D (page.17) >> +>> endobj +2656 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [222.021 498.885 233.976 509.622] +/Subtype /Link +/A << /S /GoTo /D (page.22) >> +>> endobj +2657 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [168.084 486.93 180.039 497.778] +/Subtype /Link +/A << /S /GoTo /D (page.41) >> +>> endobj +2658 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [188.286 474.974 200.241 485.823] +/Subtype /Link +/A << /S /GoTo /D (page.57) >> +>> endobj +2659 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [204.337 474.974 216.292 485.823] +/Subtype /Link +/A << /S /GoTo /D (page.58) >> +>> endobj +2660 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [169.745 463.019 181.7 473.757] +/Subtype /Link +/A << /S /GoTo /D (page.57) >> +>> endobj +2661 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [163.684 451.064 175.639 461.802] +/Subtype /Link +/A << /S /GoTo /D (page.58) >> +>> endobj +2662 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [189.587 439.109 201.542 449.846] +/Subtype /Link +/A << /S /GoTo /D (page.57) >> +>> endobj +2663 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [166.175 427.154 178.13 437.891] +/Subtype /Link +/A << /S /GoTo /D (page.57) >> +>> endobj +2664 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [197.336 415.199 209.291 426.047] +/Subtype /Link +/A << /S /GoTo /D (page.58) >> +>> endobj +2665 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [184.993 403.243 196.948 413.981] +/Subtype /Link +/A << /S /GoTo /D (page.57) >> +>> endobj +2666 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [201.847 391.288 213.802 402.136] +/Subtype /Link +/A << /S /GoTo /D (page.58) >> +>> endobj +2667 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [218.202 379.333 230.157 390.181] +/Subtype /Link +/A << /S /GoTo /D (page.57) >> +>> endobj +2668 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [230.129 367.378 242.085 378.226] +/Subtype /Link +/A << /S /GoTo /D (page.62) >> +>> endobj +2669 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [163.656 355.423 175.612 366.271] +/Subtype /Link +/A << /S /GoTo /D (page.41) >> +>> endobj +2670 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [215.213 343.468 227.168 354.316] +/Subtype /Link +/A << /S /GoTo /D (page.50) >> +>> endobj +2671 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [231.264 343.468 243.219 354.316] +/Subtype /Link +/A << /S /GoTo /D (page.62) >> +>> endobj +2672 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [214.383 331.512 226.338 342.361] +/Subtype /Link +/A << /S /GoTo /D (page.50) >> +>> endobj +2673 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [230.434 331.512 242.389 342.361] +/Subtype /Link +/A << /S /GoTo /D (page.63) >> +>> endobj +2674 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [198.802 319.557 210.758 330.295] +/Subtype /Link +/A << /S /GoTo /D (page.49) >> +>> endobj +2675 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [214.853 319.557 226.809 330.295] +/Subtype /Link +/A << /S /GoTo /D (page.62) >> +>> endobj +2676 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [198.83 307.602 210.785 318.45] +/Subtype /Link +/A << /S /GoTo /D (page.64) >> +>> endobj +2677 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [220.388 295.647 232.343 306.495] +/Subtype /Link +/A << /S /GoTo /D (page.64) >> +>> endobj +2678 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [184.329 283.692 196.284 294.429] +/Subtype /Link +/A << /S /GoTo /D (page.58) >> +>> endobj +2679 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [173.066 271.737 185.021 282.585] +/Subtype /Link +/A << /S /GoTo /D (page.58) >> +>> endobj +2680 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [204.531 259.781 216.486 270.519] +/Subtype /Link +/A << /S /GoTo /D (page.59) >> +>> endobj +2681 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [163.684 247.826 175.639 258.564] +/Subtype /Link +/A << /S /GoTo /D (page.59) >> +>> endobj +2682 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [175.335 235.871 187.29 246.609] +/Subtype /Link +/A << /S /GoTo /D (page.59) >> +>> endobj +2683 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [190.223 223.916 202.179 234.764] +/Subtype /Link +/A << /S /GoTo /D (page.42) >> +>> endobj +2684 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [220.001 211.961 231.956 222.809] +/Subtype /Link +/A << /S /GoTo /D (page.42) >> +>> endobj +2685 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [197.474 200.006 209.429 210.854] +/Subtype /Link +/A << /S /GoTo /D (page.42) >> +>> endobj +2686 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [247.592 188.05 259.547 198.899] +/Subtype /Link +/A << /S /GoTo /D (page.35) >> +>> endobj +2687 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [197.695 176.095 209.651 186.943] +/Subtype /Link +/A << /S /GoTo /D (page.43) >> +>> endobj +2688 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [213.746 176.095 225.702 186.943] +/Subtype /Link +/A << /S /GoTo /D (page.44) >> +>> endobj +2689 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [188.065 164.14 200.02 174.988] +/Subtype /Link +/A << /S /GoTo /D (page.44) >> +>> endobj +2690 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [200.407 152.185 212.363 162.922] +/Subtype /Link +/A << /S /GoTo /D (page.44) >> +>> endobj +2691 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [200.933 140.23 212.888 150.967] +/Subtype /Link +/A << /S /GoTo /D (page.44) >> +>> endobj +2692 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [186.294 128.275 198.249 139.012] +/Subtype /Link +/A << /S /GoTo /D (page.44) >> +>> endobj +2693 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [193.323 116.319 205.278 127.168] +/Subtype /Link +/A << /S /GoTo /D (page.44) >> +>> endobj +2694 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [196.312 104.364 208.267 115.102] +/Subtype /Link +/A << /S /GoTo /D (page.20) >> +>> endobj +2695 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [199.356 92.409 211.311 103.257] +/Subtype /Link +/A << /S /GoTo /D (page.20) >> +>> endobj +2696 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [200.325 80.454 212.28 91.302] +/Subtype /Link +/A << /S /GoTo /D (page.45) >> +>> endobj +2697 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [424.871 690.167 436.827 700.905] +/Subtype /Link +/A << /S /GoTo /D (page.20) >> +>> endobj +2698 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [440.922 690.167 452.878 700.905] +/Subtype /Link +/A << /S /GoTo /D (page.21) >> +>> endobj +2699 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [382.364 678.212 394.319 688.95] +/Subtype /Link +/A << /S /GoTo /D (page.21) >> +>> endobj +2700 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [370.713 666.257 382.668 676.995] +/Subtype /Link +/A << /S /GoTo /D (page.20) >> +>> endobj +2701 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [421.08 654.302 433.035 665.15] +/Subtype /Link +/A << /S /GoTo /D (page.59) >> +>> endobj +2702 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [406.219 642.347 418.174 653.084] +/Subtype /Link +/A << /S /GoTo /D (page.68) >> +>> endobj +2703 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [414.494 630.392 426.449 641.24] +/Subtype /Link +/A << /S /GoTo /D (page.68) >> +>> endobj +2704 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [429.438 630.392 441.393 641.24] +/Subtype /Link +/A << /S /GoTo /D (page.71) >> +>> endobj +2705 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [398.941 618.436 410.896 629.285] +/Subtype /Link +/A << /S /GoTo /D (page.68) >> +>> endobj +2706 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [388.425 606.481 400.38 617.219] +/Subtype /Link +/A << /S /GoTo /D (page.69) >> +>> endobj +2707 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [386.515 594.526 398.47 605.374] +/Subtype /Link +/A << /S /GoTo /D (page.69) >> +>> endobj +2708 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [389.116 582.571 401.072 593.419] +/Subtype /Link +/A << /S /GoTo /D (page.69) >> +>> endobj +2709 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [408.267 570.616 420.222 581.353] +/Subtype /Link +/A << /S /GoTo /D (page.69) >> +>> endobj +2710 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [386.377 558.661 398.332 569.509] +/Subtype /Link +/A << /S /GoTo /D (page.69) >> +>> endobj +2711 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [372.927 546.705 384.882 557.443] +/Subtype /Link +/A << /S /GoTo /D (page.69) >> +>> endobj +2712 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [404.199 534.75 416.154 545.598] +/Subtype /Link +/A << /S /GoTo /D (page.69) >> +>> endobj +2713 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [390.085 522.795 402.04 533.533] +/Subtype /Link +/A << /S /GoTo /D (page.69) >> +>> endobj +2714 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [370.713 510.84 382.668 521.577] +/Subtype /Link +/A << /S /GoTo /D (page.70) >> +>> endobj +2715 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [417.98 498.885 429.936 509.733] +/Subtype /Link +/A << /S /GoTo /D (page.70) >> +>> endobj +2716 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [369.883 486.93 381.838 497.667] +/Subtype /Link +/A << /S /GoTo /D (page.70) >> +>> endobj +2717 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [421.384 474.974 433.34 485.712] +/Subtype /Link +/A << /S /GoTo /D (page.70) >> +>> endobj +2718 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [408.544 463.019 420.499 473.757] +/Subtype /Link +/A << /S /GoTo /D (page.70) >> +>> endobj +2719 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [383.222 451.064 395.177 461.912] +/Subtype /Link +/A << /S /GoTo /D (page.71) >> +>> endobj +2720 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [418.423 439.109 430.378 449.957] +/Subtype /Link +/A << /S /GoTo /D (page.71) >> +>> endobj +2721 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [398.111 427.154 410.066 438.002] +/Subtype /Link +/A << /S /GoTo /D (page.71) >> +>> endobj +2722 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [377.687 415.199 389.642 425.936] +/Subtype /Link +/A << /S /GoTo /D (page.71) >> +>> endobj +2723 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [397.225 403.243 409.18 413.981] +/Subtype /Link +/A << /S /GoTo /D (page.71) >> +>> endobj +2724 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [405.942 391.288 417.898 402.026] +/Subtype /Link +/A << /S /GoTo /D (page.63) >> +>> endobj +2725 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [384.08 379.333 396.035 390.071] +/Subtype /Link +/A << /S /GoTo /D (page.63) >> +>> endobj +2726 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [422.879 367.378 434.834 378.226] +/Subtype /Link +/A << /S /GoTo /D (page.21) >> +>> endobj +2727 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [382.364 355.423 394.319 366.16] +/Subtype /Link +/A << /S /GoTo /D (page.21) >> +>> endobj +2728 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [429.825 343.468 441.78 354.316] +/Subtype /Link +/A << /S /GoTo /D (page.21) >> +>> endobj +2729 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [399.937 331.512 411.892 342.361] +/Subtype /Link +/A << /S /GoTo /D (page.72) >> +>> endobj +2730 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [415.988 331.512 427.943 342.361] +/Subtype /Link +/A << /S /GoTo /D (page.73) >> +>> endobj +2731 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [423.349 319.557 435.304 330.405] +/Subtype /Link +/A << /S /GoTo /D (page.72) >> +>> endobj +2732 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [417.621 307.602 429.576 318.45] +/Subtype /Link +/A << /S /GoTo /D (page.72) >> +>> endobj +2733 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [429.382 295.647 441.337 306.495] +/Subtype /Link +/A << /S /GoTo /D (page.73) >> +>> endobj +2734 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [383.443 283.692 395.398 294.54] +/Subtype /Link +/A << /S /GoTo /D (page.72) >> +>> endobj +2735 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [410.287 271.737 422.242 282.585] +/Subtype /Link +/A << /S /GoTo /D (page.73) >> +>> endobj +2736 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [387.373 259.781 399.328 270.63] +/Subtype /Link +/A << /S /GoTo /D (page.73) >> +>> endobj +2737 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [412.086 247.826 424.041 258.674] +/Subtype /Link +/A << /S /GoTo /D (page.45) >> +>> endobj +2738 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [428.137 247.826 440.092 258.674] +/Subtype /Link +/A << /S /GoTo /D (page.46) >> +>> endobj +2739 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [398.941 235.871 410.896 246.719] +/Subtype /Link +/A << /S /GoTo /D (page.45) >> +>> endobj +2740 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [388.784 223.916 400.74 234.653] +/Subtype /Link +/A << /S /GoTo /D (page.46) >> +>> endobj +2741 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [421.661 211.961 433.616 222.809] +/Subtype /Link +/A << /S /GoTo /D (page.46) >> +>> endobj +2742 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [396.201 200.006 408.156 210.743] +/Subtype /Link +/A << /S /GoTo /D (page.46) >> +>> endobj +2743 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [396.339 188.05 408.295 198.899] +/Subtype /Link +/A << /S /GoTo /D (page.21) >> +>> endobj +2744 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [411.283 188.05 423.239 198.899] +/Subtype /Link +/A << /S /GoTo /D (page.23) >> +>> endobj +2745 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [382.364 176.095 394.319 186.833] +/Subtype /Link +/A << /S /GoTo /D (page.22) >> +>> endobj +2746 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [414.881 164.14 426.836 174.988] +/Subtype /Link +/A << /S /GoTo /D (page.22) >> +>> endobj +2747 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [399.633 152.185 411.588 163.033] +/Subtype /Link +/A << /S /GoTo /D (page.23) >> +>> endobj +2748 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [431.707 140.23 443.662 150.967] +/Subtype /Link +/A << /S /GoTo /D (page.22) >> +>> endobj +2749 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [412.695 128.275 424.65 139.012] +/Subtype /Link +/A << /S /GoTo /D (page.22) >> +>> endobj +2750 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [437.214 116.319 449.169 127.168] +/Subtype /Link +/A << /S /GoTo /D (page.23) >> +>> endobj +2751 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [412.778 104.364 424.733 115.212] +/Subtype /Link +/A << /S /GoTo /D (page.79) >> +>> endobj +2752 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [447.149 92.409 459.104 103.257] +/Subtype /Link +/A << /S /GoTo /D (page.77) >> +>> endobj +2753 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [417.897 80.454 429.853 91.302] +/Subtype /Link +/A << /S /GoTo /D (page.23) >> +>> endobj +2754 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [433.948 80.454 445.904 91.302] +/Subtype /Link +/A << /S /GoTo /D (page.24) >> +>> endobj +2638 0 obj << +/D [2636 0 R /XYZ 109.858 727.97 null] +>> endobj +2635 0 obj << +/Font << /F29 416 0 R /F8 369 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +2758 0 obj << +/Length 2416 +/Filter /FlateDecode +>> +stream +xڭZr}WQ +Wލ*N$۩%1 +PtlӸƠ<֖Wاqx`fV/ddxޣ&_ϖÊpjuau~f^ zRM}q}%WJ(Y|GJDe?pc-/ok..MfGq- Jx[:F\^d2eVB.Pڌ+iXW]viPU&[{rU_K#HJeѪ#1VLlҺ L(6nO5ϚKa8[|XM_v$%9)9T”hҍQb`͛OgO3mp!X$sQ{o˃.0-! Ӛp}y?w{ 1 ~""if34@ M/X*JHʍvs}{p=(AXFRftB/C3eVvHݣHՊh HG:rY!/w랒|7k3^۷>bS%*9_$e}F-ʤUH-ѦmE Й%ɂ#B/XtdѦ-W u? 5#K%3g廽t V Lz#?KS<~?mNSqPYY$)Y]~zƱ7`ӍِЮcd|d6flLee*oP2,hIg XrwWqA0l`I +(f+`jUhѦ-J&iIaݹ[$P{A0-6k\Wr>n >_"P&=o`%PQ&X hHj̊q{*D]hi(,) I +( 6̂lLpe6h ؏*#d|=nݫ9i tP' k#e>Tg{~4Ѓn&"PĻˊe&M7OsXt;|#ĻKaěV!-8taQB2,l`o~;t=jXtA m5۟;HЂU9M7Z$CXOT$^}~>–\n 9& "IE`⽭ >LehӋʁb0e8`Lj^&d ng>`3":n'AihCt1b(Dd19̋a>ZZt&OMX˄l)풒%SoI%)AB̟y|0dHHR@P{o=lzѲ@4Yx2^*ST-ʔ >L:&^JrKM^a+1]j4酪:2F`/~۟ݕ|#&ǩ^wnZyGεMV/PG$)#p4 p#6hPlS8X\)Ca$)X Q@F\VQ<wZiKC6lQ%HR@M7ZT  쿛Hh䌜HBf2*k;˻?8Nok#ZUfSހ$w {t> 6hI@Z&ߵawI{7KF#8HeM_b>NT$g5p[1C$ڻ_:ýDR `Ӎt[AKR8 Z8'0/PY G2X]18E{慗<Ö]x9$) ̷#X^кr6hI͵L=Hy=Ԇ Un(" IŒ)v\Jaˆ0mAd\o+t@ǘ橒mHLendstream +endobj +2757 0 obj << +/Type /Page +/Contents 2758 0 R +/Resources 2756 0 R +/MediaBox [0 0 612 792] +/Parent 2755 0 R +/Annots [ 2760 0 R 2761 0 R 2762 0 R 2763 0 R 2764 0 R 2765 0 R 2766 0 R 2767 0 R 2768 0 R 2769 0 R 2770 0 R 2771 0 R 2772 0 R 2773 0 R 2774 0 R 2775 0 R 2776 0 R 2777 0 R 2778 0 R 2779 0 R 2780 0 R 2781 0 R 2782 0 R 2783 0 R 2784 0 R 2785 0 R 2786 0 R 2787 0 R 2788 0 R 2789 0 R 2790 0 R 2791 0 R 2792 0 R 2793 0 R 2794 0 R 2795 0 R 2796 0 R 2797 0 R 2798 0 R 2799 0 R 2800 0 R 2801 0 R 2802 0 R ] +>> endobj +2760 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [163.684 690.167 175.639 700.905] +/Subtype /Link +/A << /S /GoTo /D (page.24) >> +>> endobj +2761 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [196.201 678.212 208.156 689.06] +/Subtype /Link +/A << /S /GoTo /D (page.23) >> +>> endobj +2762 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [194.015 666.257 205.97 676.995] +/Subtype /Link +/A << /S /GoTo /D (page.24) >> +>> endobj +2763 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [218.534 654.302 230.489 665.15] +/Subtype /Link +/A << /S /GoTo /D (page.24) >> +>> endobj +2764 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [184.191 642.347 196.146 653.195] +/Subtype /Link +/A << /S /GoTo /D (page.63) >> +>> endobj +2765 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [232.205 630.392 244.16 641.24] +/Subtype /Link +/A << /S /GoTo /D (page.24) >> +>> endobj +2766 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [248.256 630.392 260.211 641.24] +/Subtype /Link +/A << /S /GoTo /D (page.25) >> +>> endobj +2767 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [167.835 618.436 179.79 629.285] +/Subtype /Link +/A << /S /GoTo /D (page.25) >> +>> endobj +2768 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [189.974 606.481 201.93 617.219] +/Subtype /Link +/A << /S /GoTo /D (page.70) >> +>> endobj +2769 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [184.716 594.526 196.672 605.264] +/Subtype /Link +/A << /S /GoTo /D (page.46) >> +>> endobj +2770 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [172.65 582.571 184.606 593.419] +/Subtype /Link +/A << /S /GoTo /D (page.78) >> +>> endobj +2771 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [175.418 570.616 187.373 581.464] +/Subtype /Link +/A << /S /GoTo /D (page.78) >> +>> endobj +2772 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [202.981 558.661 214.936 569.509] +/Subtype /Link +/A << /S /GoTo /D (page.79) >> +>> endobj +2773 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [188.771 546.705 200.726 557.554] +/Subtype /Link +/A << /S /GoTo /D (page.79) >> +>> endobj +2774 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [199.065 534.75 211.02 545.598] +/Subtype /Link +/A << /S /GoTo /D (page.79) >> +>> endobj +2775 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [157.319 512.832 169.274 523.681] +/Subtype /Link +/A << /S /GoTo /D (page.16) >> +>> endobj +2776 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [173.37 512.832 185.325 523.681] +/Subtype /Link +/A << /S /GoTo /D (page.33) >> +>> endobj +2777 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [196.782 500.877 208.737 511.615] +/Subtype /Link +/A << /S /GoTo /D (page.16) >> +>> endobj +2778 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [221.55 488.922 233.506 499.77] +/Subtype /Link +/A << /S /GoTo /D (page.33) >> +>> endobj +2779 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [181.146 476.967 193.102 487.815] +/Subtype /Link +/A << /S /GoTo /D (page.34) >> +>> endobj +2780 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [221.55 465.012 233.506 475.86] +/Subtype /Link +/A << /S /GoTo /D (page.34) >> +>> endobj +2781 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [181.921 453.057 193.876 463.905] +/Subtype /Link +/A << /S /GoTo /D (page.58) >> +>> endobj +2782 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [208.212 441.101 220.167 451.95] +/Subtype /Link +/A << /S /GoTo /D (page.58) >> +>> endobj +2783 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [198.609 429.146 210.564 439.994] +/Subtype /Link +/A << /S /GoTo /D (page.23) >> +>> endobj +2784 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [214.66 429.146 226.615 439.994] +/Subtype /Link +/A << /S /GoTo /D (page.24) >> +>> endobj +2785 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [230.711 429.146 242.666 439.994] +/Subtype /Link +/A << /S /GoTo /D (page.40) >> +>> endobj +2786 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [227.445 417.191 239.4 428.039] +/Subtype /Link +/A << /S /GoTo /D (page.40) >> +>> endobj +2787 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [197.585 405.236 209.54 416.084] +/Subtype /Link +/A << /S /GoTo /D (page.23) >> +>> endobj +2788 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [219.143 393.281 231.098 404.129] +/Subtype /Link +/A << /S /GoTo /D (page.24) >> +>> endobj +2789 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [211.643 381.326 223.598 392.174] +/Subtype /Link +/A << /S /GoTo /D (page.19) >> +>> endobj +2790 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [186.072 369.37 198.028 380.219] +/Subtype /Link +/A << /S /GoTo /D (page.19) >> +>> endobj +2791 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [181.894 357.415 193.849 368.153] +/Subtype /Link +/A << /S /GoTo /D (page.66) >> +>> endobj +2792 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [241.005 345.46 252.961 356.198] +/Subtype /Link +/A << /S /GoTo /D (page.66) >> +>> endobj +2793 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [139.303 323.542 151.258 334.39] +/Subtype /Link +/A << /S /GoTo /D (page.53) >> +>> endobj +2794 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [255.866 311.587 267.822 322.435] +/Subtype /Link +/A << /S /GoTo /D (page.53) >> +>> endobj +2795 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [161.719 299.632 173.674 310.48] +/Subtype /Link +/A << /S /GoTo /D (page.53) >> +>> endobj +2796 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [255.866 287.677 267.822 298.525] +/Subtype /Link +/A << /S /GoTo /D (page.53) >> +>> endobj +2797 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [169.938 275.722 181.894 286.459] +/Subtype /Link +/A << /S /GoTo /D (page.70) >> +>> endobj +2798 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [215.739 263.766 227.694 274.615] +/Subtype /Link +/A << /S /GoTo /D (page.70) >> +>> endobj +2799 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [144.617 251.811 156.572 262.659] +/Subtype /Link +/A << /S /GoTo /D (page.71) >> +>> endobj +2800 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [215.739 239.856 227.694 250.704] +/Subtype /Link +/A << /S /GoTo /D (page.71) >> +>> endobj +2801 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [157.596 217.938 169.551 228.676] +/Subtype /Link +/A << /S /GoTo /D (page.46) >> +>> endobj +2802 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [213.331 205.983 225.286 216.831] +/Subtype /Link +/A << /S /GoTo /D (page.46) >> +>> endobj +2759 0 obj << +/D [2757 0 R /XYZ 109.858 727.97 null] +>> endobj +2756 0 obj << +/Font << /F29 416 0 R /F8 369 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +2803 0 obj << +/Type /Encoding +/Differences [ 0 /.notdef 1/dotaccent/fi/fl/fraction/hungarumlaut/Lslash/lslash/ogonek/ring 10/.notdef 11/breve/minus 13/.notdef 14/Zcaron/zcaron/caron/dotlessi/dotlessj/ff/ffi/ffl/notequal/infinity/lessequal/greaterequal/partialdiff/summation/product/pi/grave/quotesingle/space/exclam/quotedbl/numbersign/dollar/percent/ampersand/quoteright/parenleft/parenright/asterisk/plus/comma/hyphen/period/slash/zero/one/two/three/four/five/six/seven/eight/nine/colon/semicolon/less/equal/greater/question/at/A/B/C/D/E/F/G/H/I/J/K/L/M/N/O/P/Q/R/S/T/U/V/W/X/Y/Z/bracketleft/backslash/bracketright/asciicircum/underscore/quoteleft/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/braceleft/bar/braceright/asciitilde 127/.notdef 128/Euro/integral/quotesinglbase/florin/quotedblbase/ellipsis/dagger/daggerdbl/circumflex/perthousand/Scaron/guilsinglleft/OE/Omega/radical/approxequal 144/.notdef 147/quotedblleft/quotedblright/bullet/endash/emdash/tilde/trademark/scaron/guilsinglright/oe/Delta/lozenge/Ydieresis 160/.notdef 161/exclamdown/cent/sterling/currency/yen/brokenbar/section/dieresis/copyright/ordfeminine/guillemotleft/logicalnot/hyphen/registered/macron/degree/plusminus/twosuperior/threesuperior/acute/mu/paragraph/periodcentered/cedilla/onesuperior/ordmasculine/guillemotright/onequarter/onehalf/threequarters/questiondown/Agrave/Aacute/Acircumflex/Atilde/Adieresis/Aring/AE/Ccedilla/Egrave/Eacute/Ecircumflex/Edieresis/Igrave/Iacute/Icircumflex/Idieresis/Eth/Ntilde/Ograve/Oacute/Ocircumflex/Otilde/Odieresis/multiply/Oslash/Ugrave/Uacute/Ucircumflex/Udieresis/Yacute/Thorn/germandbls/agrave/aacute/acircumflex/atilde/adieresis/aring/ae/ccedilla/egrave/eacute/ecircumflex/edieresis/igrave/iacute/icircumflex/idieresis/eth/ntilde/ograve/oacute/ocircumflex/otilde/odieresis/divide/oslash/ugrave/uacute/ucircumflex/udieresis/yacute/thorn/ydieresis] +>> endobj +1438 0 obj << +/Type /Font +/Subtype /Type1 +/Encoding 2803 0 R +/BaseFont /Helvetica-Oblique +>> endobj +1435 0 obj << +/Length1 797 +/Length2 909 +/Length3 532 +/Length 1480 +/Filter /FlateDecode +>> +stream +xRiTWU8,FpAEd&U@ʦ0ydM^7uWXVj%UBQ(Z;Ogw~õd.ECoء$C š[a+ 5f3e9d +I*iLAX)P$00G +`I12ӿT~4ᐄ1L?m=!KYng;v: K߉!b/ DW4cCCqAsa]9Gjs#^W=U\Zxq~B$̜om?VQ͉~qt񖹛[~ dLK߭g;]|%1kLDe}fVUeJx)0&p$'uN FʖoM,Fe+Yaue1 YϱVu{Ac-.xE}2e'`<7ŴFP@b}=bllkO1_jov\khBW]IoKL7ѥW]fU-l 6Poݪ-|D;|ü޲L.eWudž ڔ1?<1P27rKu^\lXSځp?gw:Cl|~~_WZdLL_vtFzU -;Kw']XҰqn]]3=Po<ִ,{u޵m_2,q+vYi[ךT̒Z^}5fύڜ󫶤^8ZU"R|FR2uQG ~;cx ͺZf~EQ37!E~;;ެ6c7rGՕO=on!C&-IN +7k޶6kܻf>}W%7$E^`3=<1)&ioo|͸Qhjf׏]Q?dLsUM-9zpWI^*mk%Ú^9.-k7nفEoOuGtze^T63:^# <3"LVڏ͢-yorsNW{ѶU7Gz:t?|8 'pb4#bt/"!endstream +endobj +1436 0 obj << +/Type /Font +/Subtype /Type1 +/Encoding 2804 0 R +/FirstChar 102 +/LastChar 103 +/Widths 2805 0 R +/BaseFont /KHTIIV+CMSY8 +/FontDescriptor 1434 0 R +>> endobj +1434 0 obj << +/Ascent 750 +/CapHeight 683 +/Descent -194 +/FontName /KHTIIV+CMSY8 +/ItalicAngle -14 +/StemV 89 +/XHeight 431 +/FontBBox [-30 -955 1185 779] +/Flags 4 +/CharSet (/braceleft/braceright) +/FontFile 1435 0 R +>> endobj +2805 0 obj +[531 531 ] +endobj +2804 0 obj << +/Type /Encoding +/Differences [ 0 /.notdef 102/braceleft/braceright 104/.notdef] +>> endobj +718 0 obj << +/Length1 1459 +/Length2 8934 +/Length3 532 +/Length 9786 +/Filter /FlateDecode +>> +stream +xUX\˶޸;$Kp;A pz}J>>|ԨU5)IUE-̀RNL|qE5+ <%+Q`ezXX\||$;F$nhn tanjPw20Djp݀@ &xVV; he_a y]@R$-hhZ3+9jA&?sq){{%S迍:q'gw+@)-l<sT\`WMhbnn 4w:Zm+0(*8k8_3o +J=g$͝,lAǁ `j: l-7ȗ4j?7߱!mA?N"}w,b,@s%~/Yf0K&ob0&P@~?@~oooUMڿ T]u}&靈,@ОZ Y?dktm@AVd@pAn Hix ?ljix ?o7PLۗ ˳9YDMG_'t͖6o 4_Yt2Mo ,j7׍n_:&B٨T|}H-OuB"c롧a:Y>d!(gʳ)Cç*4aI=Cu5#IP3\*"9"6PS6Bl#`׮<П`?%ϊc,p:N.,Y/:[sgT,la5J(SvfSrFT)D78=rT)T17;%`!z~c eи Qʲ +O;v^#5/C_KkM8쬨z&iX*)F'('$Z<>( =?~h4)P^ UD3N]?pV|鴶7G3VL pq~$>]sUiAKeX35,̎4G9URx!VQdC@Q͏_Tly.18(A{GZ3j.r1Ӿr骔Ožo\,=j:nCO#6W|n?C"ۿOh#C% qHfRʟ 늊P>$})>-FO]h,{{ _|p0Ί%g_ +֫(/d˄M ~`,} UM(x,tOͅn&6{);79lPYΚۨ7Ff1/Z6MLNog;(B 鄼odlޘ+eR.lSb!1cMƩ4e5ajUd/e„6?΍}ھwVڹ;`C!"K񚥚!SЌw 8P-8K|J~3~_$̺?5o Q|bl 1;}*"p)A45b;X^mfw*9ER`+80Rmb2Y%ߋ< Ne@|~T$:mG67_ .sM ҃cKc| Ȗ H b wVY-|t;ƆCI.~u:<,BvB"qS@#Ncļݮ.TF1LY $L9LX8*[boͯ7p z2w8  m1cK<1/JvzST?]F^T9.45u| j?^UДb{Fʊq5T T¹(eLxc0)qx'η^Ѯ?ḚUa `[;D;uuai<'fpN_`< 5*WMɠyzye;f^G _q֐ QҌI +jr $ sSA_W'k\ش:".7̾# +1\b\`ҫ HAZ)",բ)xQ^aҗ΄ʆ6a&ʹ}cWI*m/]p73;N9t=EWѐ2(5҇hڀZ7y=4_ ýp:MJy=%nÔ+Vg #٩T§hReR3@ʹL=;shbHa S!lݹ:y  (9VE컍tC$*f%~ROym1_!oԤX^^ahK'Mx %3jq+^AE748;D裏ҺQsi݂p@#;Q6S\ ['lyg8BVw TѧBQ+xwU<0nҍ]3jKFMu%BIWGi6JXeIYR_2‚Z1H5O#yi,֟p{i ɱh_/IWx y/v9 F7`:+v9}\NV&qI ֱ*ܝe!^V6c`ʒ,oCbN>t#f5ypRUb{1Y~+;+NJY']:V.6wXc󼘪zh pŽA]r=[=x$ȁE[hlɃ΋)uui5KpjlܯWn%%Ŧq5oN~IsIC}wTʠwB: ܽRlm֒j{;kj&(W"Y'%Vj8xVJ;pEUx6c_'Ato^1{&-<17N&_TţhSyʽ^+L3I$T^_n lcȞٽi܍#94+W?ྶ$~'>-oX%Zg+w6WGVaKnKǥwum h{KϨ%^Y$7o>|xſSrB TS!TdZzL&}pe +7::IP@`c o{u-'9χuST>c\H(LFPJ "Cy +%[a< 6XXFz zp3J/5v2עw; tMH^KL:q ]a- @Qn/prں!ګKg2E:qcc;YШض<5O))UJ>](&0A#'$hGsc?ܹ/L;K`/"u7񱞈Y/Zķ|7$gu58 TNwE7ElXk$h:'%(`w:0er pcb%[ö*)au|鱨h Y+ied4VMΡ`TP(c + +T,8`i+ LG%.挵h .lS9㫳ɱLuZaK͙:r/!uS[ɼ]! +,[M`hn%␉U6Mbtp- +Y6}Epx5lt\#}Ǎpm1Ozw1 Q$={CdW/5f3Q|2U>u?'W[tN78t^#m=e؉;m+ 4[eXh(Y%fG%" +![sԇ:u<ek1<ك4:Z~GY=~Gu8AN^C@n@dxxhr$ +Dx[DW'^T~7y7V#!!AXFװE6 > B#PUu"LXx"CS-FP>. Vw YhvG9@KNױzVC/ޠ֠PR}RlohӺ{{< Bs""I1\HA7VꄪD:Ÿ]-^?fS=-P ɠp'12(4KZ]7nTx eP)`7G)Cr 処 S1y_[|JڤiXuS'd9h߅@óZIGK 9/״#1y(@ °r,s)ǧ!egؚmė>G/Oأ~RE򱃟)4`]%Ó +Õ' + ++5E,&NHv-Q]O Iu*[ק_k6}_Z{x&,(Ek=v]1 Gbol +!I&=[ϔ~G|:72l_>=BlfCbDSȹj*$;hsŎL&ӕ ws>B?+n +Guqg>j|C~ `IF-MLjuv%cErVH64TbzcKmMFKMj;Qlha, nv6w\.e 5WnV@0g6Mz@Ui|C ^W`˰W(E +[\e6nXGҦYd'm*Ԋ\skC~TH d L3'!Nq4PYt}<$0$36:e҈&巭.5JCpt(j%\KD!a6o)ŎOA+0F[Fq'T%m+nst8п=]; 7O1|j߬$LEǡOA +!ja MRh7bQϖ7^7blXqLv/ob~ݢڦo0kt1 ԕ(fMqX"^݅GV/|)J™CR}i޷k\2kak/')]x̧4 N|avd%:-aq~ [ +/|/!d`)=JMwGhlzJ-h05zTD>͜]{HvQ=[ڂ5 +PX{qFj?SͿxձ+klUj2{h\(G%=P58 maƅvds-b=%G3K3o>AW4odwP]jG};'b_l /z(7ׅ7ġڋ;|-ޒZixW˥jYX)ƙ|_( QwVg-Z_LR۫IDbPn_B yMÐiv#2uP0t?:67KezR9X/n +=f1V[ہR[Y͢PoAO/D97D 2tujw{US%)x$0Z-5s:Lk̚t6yYFϻ x_0'YE՝wsT)]ܾYv9ZSGS=rOҘ ϩ;@xi?Cϖ4=h0RH·(L +(j_wsW)(9 53{!.FX G͢ѿO]D}~W^{ Ӟ}35U*^7uBﳾ̊`óW6 +Ѯ2cgU?}:0)bQ +Ipun2g>GO_ǧ+/zI*H6=>3%>d +]$^EGٝkKoR(LJR:՘3it82FW>:D,>mL|u$FG#y Shy.qT\BQZ p}vb'j.'/e`xz!$4=cYXT&C=maZW3ew2A#O+M۷1 YI^ZLrE̥,X"LUeR~>)uv3]'[pn̖chG_V^cI^뤰M5d#,Xְta;iMټJۖVƌںj&jBf@jxgr(74_NZ?.O$)u%ƶ۲osow*V̊ T^u;Ȼ9-GGs|fs mIJmnWH!a3 ly N6<5j|lPL;{Y?/a%.?bs{endstream +endobj +719 0 obj << +/Type /Font +/Subtype /Type1 +/Encoding 2806 0 R +/FirstChar 11 +/LastChar 122 +/Widths 2807 0 R +/BaseFont /PLZSYM+CMR8 +/FontDescriptor 717 0 R +>> endobj +717 0 obj << +/Ascent 694 +/CapHeight 683 +/Descent -194 +/FontName /PLZSYM+CMR8 +/ItalicAngle 0 +/StemV 76 +/XHeight 431 +/FontBBox [-36 -250 1070 750] +/Flags 4 +/CharSet (/ff/fi/comma/colon/A/B/C/D/E/F/H/I/L/M/N/O/P/R/S/T/U/V/W/X/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/r/s/t/u/v/w/x/y/z) +/FontFile 718 0 R +>> endobj +2807 0 obj +[620 590 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 295 0 0 0 0 0 0 0 0 0 0 0 0 0 295 0 0 0 0 0 0 796 752 767 811 723 693 0 796 383 0 0 664 973 796 826 723 0 782 590 767 796 796 1091 796 0 0 0 0 0 0 0 0 531 590 472 590 472 325 531 590 295 325 561 295 885 590 531 590 0 414 419 413 590 561 767 561 561 472 ] +endobj +2806 0 obj << +/Type /Encoding +/Differences [ 0 /.notdef 11/ff/fi 13/.notdef 44/comma 45/.notdef 58/colon 59/.notdef 65/A/B/C/D/E/F 71/.notdef 72/H/I 74/.notdef 76/L/M/N/O/P 81/.notdef 82/R/S/T/U/V/W/X 89/.notdef 97/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p 113/.notdef 114/r/s/t/u/v/w/x/y/z 123/.notdef] +>> endobj +715 0 obj << +/Length1 837 +/Length2 1937 +/Length3 532 +/Length 2544 +/Filter /FlateDecode +>> +stream +xRy<"FZE͌d5n̼4!t}Ɖ%$$۽ٗ"drJT;t=v~}>'%UÑ"r8&VB\!|`1\X4훡Z֭2wagJXIX8XEJ : 1Lqv}0-wl[%s`B4!̤aќ\4mLj۰%E0S}-je o֝_;mT*w3޿*b(8|I5*qA8O_n'Z;a:^ȁS# uk3F |GL=nДd&QӬ `mS^0ͮ-cҒ{UWLl#N,)nv;8M߲.%L *^Ǚ ~HDO\ ,z{,|gRQS/Sڣ|jdL#蛻(K5mē,*7H:B:& `oj +Y"Z^%|J lЁEc|w"e䁯Ԓ8 rYgJZЍXj>-jZK!9Dƽeܽ G:*|vOQhKy;Ꙅ+;i]fyE|~[ntrD}ך+ʶnݪYI]WW8$ ;Dyn杌LJ_tJOs,WG/ږԇ mW-{ԙ= +};`[JlM8'[>!r_'J}#_dzUyi<)3dok>L#W.CCМa*S-o',Op˫~J,h)\9wZ Wb*-ަ ?`֋uy#Ծ eǟ BE\ɺPcbazu&GVA$n8/\.[sS˜gU}ֵJlW6TGۻFs(~`p :U*e(Q;ӡhY+$qcֳbqhjcG̗SO-:DXBռFE`'DcMy_2-Cku{v1~ͩ鍑80|e]b6<3w#]:g2@nTf/u$?ԍwgWIHZخ GJp}eÉe.YЩlAcaY+HU"ӹlRG4݅J qsY/|7Q9N0tֿ-aL)sC͆&_, Qۮwr6Y*uo!f5{4,2Jq^Wh{5˲g0(9њ?p }-kΡq-fj} j3bddȯm rw4!|Dv[;E ʖiY0$[aEϙs?I~jas0#+2_BK1d +C@endstream +endobj +716 0 obj << +/Type /Font +/Subtype /Type1 +/Encoding 2808 0 R +/FirstChar 83 +/LastChar 115 +/Widths 2809 0 R +/BaseFont /PTPQCL+CMTI8 +/FontDescriptor 714 0 R +>> endobj +714 0 obj << +/Ascent 694 +/CapHeight 683 +/Descent -194 +/FontName /PTPQCL+CMTI8 +/ItalicAngle -14 +/StemV 73 +/XHeight 431 +/FontBBox [-35 -250 1190 750] +/Flags 4 +/CharSet (/S/a/e/l/o/s) +/FontFile 715 0 R +>> endobj +2809 0 obj +[603 0 0 0 0 0 0 0 0 0 0 0 0 0 549 0 0 0 494 0 0 0 0 0 0 274 0 0 549 0 0 0 439 ] +endobj +2808 0 obj << +/Type /Encoding +/Differences [ 0 /.notdef 83/S 84/.notdef 97/a 98/.notdef 101/e 102/.notdef 108/l 109/.notdef 111/o 112/.notdef 115/s 116/.notdef] +>> endobj +712 0 obj << +/Length1 942 +/Length2 3267 +/Length3 532 +/Length 3916 +/Filter /FlateDecode +>> +stream +xy8}+Dc_+,LD4fa33J!7"Bf_"5[!ٲ&$[e{{?_\?<=#a) C <hYB9[Yydғ1 Jkid|>;$2U~ryXl}̧ٹyRbwowVz\bN8UmƢ|>C$ =~uL^h1šr;̈́n nHOU1+q}<q݃2ӻػ`z$Օk!)SsP!^pj汱Vΐ3s +R MO(]֌^Jgo$]2NK>qb`];aCyip)iKZjE'tcᢻaj[{zs&Wj}czq.fۋ.7MOM $v9o9j5UDgT( ˿ާu!-CUnQB5Uű )p]NZ:oC} ֻ#GaVNe/ju7W#(A#Med755tT9< 3Y)Y>&!,+5 0,Qś+߼V)U<8dc~W4e(Z=QU&VNyk;i=,;k\$߼i ~;WR4BBDm c+ӹgVJh?ɜų XU4g?Fk0?  A|(k"[z,. EpbP :M\V.}cUK*.O@;2p}8q`9]qWԔ5 _)i2>4*ٔ- \[H +^]:0ieRuD \D- 85kKxL#uEy'[|6ax0 +a=2DbK'\n[HQHLLqgy8&v;~MsR9Zl1bh[6I۰K-wtdc^WJ>9*y9lvani ]K5t%S# yj%W MaW}Fq^_RZwpGmVo"tZ'@]4nI4LlwÐ3 +ndULl0dؙҍ$v6QU>/i= Y9$QR}^ִ3Q{|f}A?^ 83_N~{XB荪„`UCNKS*} +t΁񑺠0hvzsC|C:YʝĐ.L1dZyusvqݼ6'9w笠-OGbuM*Y{{s" Q;vTtY5ђi8nϒ;(S.]0ث{FGD"a~ ݧwYء4ݣpNMѨ~2 ƐLwA kU .[_&}? + e$FЯ[lz<\gQo.W??~çumY?f;:D<9ڸ8Q;- 6}AY~>UKҿ3m1=q2232O@hvFZS6]-PZ'}efV;Y 5սiZGD4fhHS~'ȬΉ)䬩c+,W5"ayRkr:aٸp|SGS +>2D|@(tC]֘ƙfm\A0˪ +#=׸2;ͼ6;[% UU/ʩo(:Xv)+ʜ˨~6|R#}ؙΞKܪU/ _z^j{!QC %]p^WNg,AoV=4W ?%{'T p~s5!'ICu{ +? LTB/jN Tσ _ZI\bieR*,-P誼܎D>f s/\pJP"}B +U{5.Ns>yM\D7Vą^DyUi<[ ńTMXw)--C%zyr@P(' RL:zr= \GGjl\Q!!V*Ռj|Ş˕X.H6]j^C͞:Gh(cV뮓HDp3xJc:պ('K mN<꣹ӓ2HSL ,exȅ˻4 qMֆxC=Y,Rȩy|VE/e ްP;}m+d]Îs4֌ +'q.M+ƶ|Ä:d|^̓Q^";]a.9%/,KCvۀJk+%\R%$!z~}YXF#LSZj-7žT:6K\m1e 8;BL n9ORGKX!\/KeiҳW<(S< |ܻ]vK΅{çJ/Z]Ca !9[ )tE +|5L'?դk0+ +%ڶY- +Vn?&SHhcendstream +endobj +713 0 obj << +/Type /Font +/Subtype /Type1 +/Encoding 2810 0 R +/FirstChar 98 +/LastChar 117 +/Widths 2811 0 R +/BaseFont /EKSNOW+CMTI9 +/FontDescriptor 711 0 R +>> endobj +711 0 obj << +/Ascent 694 +/CapHeight 683 +/Descent -194 +/FontName /EKSNOW+CMTI9 +/ItalicAngle -14 +/StemV 70 +/XHeight 431 +/FontBBox [-35 -250 1148 750] +/Flags 4 +/CharSet (/b/c/d/e/h/i/l/o/p/r/s/t/u) +/FontFile 712 0 R +>> endobj +2811 0 obj +[472 472 525 472 0 0 525 315 0 0 262 0 0 525 525 0 433 420 341 551 ] +endobj +2810 0 obj << +/Type /Encoding +/Differences [ 0 /.notdef 98/b/c/d/e 102/.notdef 104/h/i 106/.notdef 108/l 109/.notdef 111/o/p 113/.notdef 114/r/s/t/u 118/.notdef] +>> endobj +674 0 obj << +/Length1 769 +/Length2 586 +/Length3 532 +/Length 1136 +/Filter /FlateDecode +>> +stream +xRkPWqmCW/bF0JMؒ͆&0Q(T:X +uG*P3R:A*ҁR ێm8şNs{^ZE2P\*F &AOP1" +cXsCTT.GAYP 2TB,@`L$QRN˂^@b׃$H&BR,@Q@R2!elMKP.dM)ț EV@B@gAɿajҬ'#`@A$0$dԽp[$)a9p=ED:=!h ʤ,TS&[[0"IV*_M-)K!@jYgR\Ze,;+&u@eqᥤQ@$h K4[ hVxT3I2`! Gt4c E@ +P4,d2߉)4cX!]*afYHs hR|Z !foT}zジ[WKmԑRE4Xnw~xsyG"=Wi;ej]/5~x!Dv]zmVu9}ȸ:{x@}.w] 9Vk]$ܲKfop]::9lKaUv;*IYyH6s> endobj +673 0 obj << +/Ascent 750 +/CapHeight 683 +/Descent -194 +/FontName /TFFBGM+CMSY9 +/ItalicAngle -14 +/StemV 87 +/XHeight 431 +/FontBBox [-30 -958 1146 777] +/Flags 4 +/CharSet (/bullet) +/FontFile 674 0 R +>> endobj +2813 0 obj +[514 ] +endobj +2812 0 obj << +/Type /Encoding +/Differences [ 0 /.notdef 15/bullet 16/.notdef] +>> endobj +671 0 obj << +/Length1 1529 +/Length2 9419 +/Length3 532 +/Length 10309 +/Filter /FlateDecode +>> +stream +xUT֨Kphw -6 [+9k_sgV՜OϪzxɕ՘D@&R W&6f6~*Z aj`cYYl|\|Hq+NI<Q{sgkSc=8@ djm jbnnƌ06u[Z; #`;l?C.`)XV49y-XAZ`?;?=Fq3@dfS5`nffߣv֦v]=͔]Mv.;mR`AEL_!eckWu/$g{l eefeeOt0Y;7 |.aX;{=, W%~ 3? o`rrX,-' +`qa^)g78C<?^+,!p?6C`q?`Cz\O)!p=/WPC +jVC\]?,TZ)M.:?SP߃Mѥ^5GK*N#,\#ͩ43l#9fe"MB !7U7ӴCu'|\R^;X)` ؅]BP &4u7.~ܦEBͭZm`hUaybkBezeHwK %ŭ f?zN Zer |uTP`Hm>eeo8V*z7ȬcO"C[g(!;WO=S, +K2FՊ)f=;qbH.8ؼ1OO^2Z\H3"(EQ"9 Ck22*R<]NI+>>IͤEey޲j٧Br`z&?BCY-`PQGiۏ#˚^J ^,ڌnI] +i-5ױVЯ9a>T8%<hSNE): mQcԼYťy>9/}aV n(ܘM L)$ 4+HeAZΩ`vO}e0ܰ;1b~˱8hu>dGQ]grlF*&a߀]?Q+v{X%Lja@f{ =`v!nݣ'FV/T$JO=!Vǽ +8O[wpZI7{ "6T-:6UDbOHa Đ+sהM҇t^;g8yht/ʈ0oi$F]#!!Y)AASOfze}QWjX:,16Ij=i*Ry¬/M}15U:r dd{Y6u/x5O%z82P+/zw]@n)$ 3 'tc7L[>KLث*o_Ժ-y殺sw=[Pi۲e +{9l<qc";Gz6nau2?} apgdKtsno 1-v`翮oӕ 7Ymy/yTr:=c 3RN|y67ݚ٥||c{X':XGa3Y_q,Zr),(81{WX_rYl*TT$ g0^(:Ym汵x FS˜f /_"ή3yBxIe&sb; k*KaFJ~В/ +w7}.gY={K]p#64.[9K1Ts"w-nCsˇڼ ]Z +ĽvtW*!'P7lt20RpZ pQ%bpKKESLr?(# aC9O]諦a%4h&GB)` ~TKUޟGrr/2LEl7;@|w}֙h ay0z3/ l}iT0vF3 gkþtceB1ibŰHx˵{N1NA(;y=yߝ#:`H/tpW!yZdaUT jTZD {9_']yX$Y_giw0IqG~i'J?LVjE[g3!<11^zZ-MPc]@QjM-^ZEL*3Vqā=yݒzA)hMy (xT?nj 3@ʖ@]01uxbPԲQĽCKr~_Ra I@L^ +mE IcߥJh!m p.o9]&9_g +(Fb 2fay=R9!Ut6sDaj@xb.D,vH_oPqTtgkEsF'=@-%T2rD$I<i>JB|$\u~ k~/x D!l٦w#8~y"_fxY]s.3֎Y :8eb9;wfxY[zfIsz!y;u&cnޞڅRa< SjX7/0a:NFvwSUwxq.o4aE[7^g4w~j犁iW_f]ΡDdjW"TJ--€DcSthz~@춨wqaK7F+(Q38^x𓈂9O9S|[vo CT|qG*Aܡ>Ψ*Su;ʨs&%\;Bu\"!)nGeewݡ)-4m)&V  MS9ӬsL%ݱvw7(9q, +'hN%0~;X_cwYʀW9VŅ./'g}HF7\s~Abc|iˈ}j8szEw0Vm+"Bm1= +-{ܓ"w; ?j9A!3(t v\'-~tFNߑCTFeUAt)4sJÏoU 'm&[?< +U^r>6Yy' ~,bU6e@j7e'*xr{^>= +bXK]=3!taB Y"FOb""M=pKe~&^;qӟ? QIU\Io񷓲~]ڹ]9mDk1`_{u*"ٌXhMW9>H,Lof1,D~e.D(9r=?6 okSAIe+i3\H5ʇI*Y39CV_?-~"`Bal)o`w- kI0 +tY[E:'/?Jƙ'^iN T~bQII ޫk56#ݦcDZOD` |{1\a8do8&@T=BPA>En3Y {tj_'0=[idbS~s!p?;жb :HU}ѤWx7&h<ZQo14DvObj]ڗct.C[ifdJkD̓[2_z b^uJ \osMkVc6eWey!Vmխ9[suS+UGi76ƀ-9ƣ\Ecg?1ߪP$i'%`hLRbԣae~RWMMZtNy1`8^NXIiL/"9 2-iW㥓lpɽ#6iBԐaZ|ZNB'O~w4y-(~!hTT|Yx}6W]%OW1cƳl3O t A]dL29sŽ]!I܀}3]EZٴ)ȏ#hy],3H+߽ <~,l&Drsg8*xnЮ)Ffg+'VE={tA!|ە$tR^i쵀2lZ69\b0քi6zǘ0>؏ś+g݈.{66T\t:?0@I48iJjPPdq!1,V +,F4hwpax&TF]1\vt@:{^FyxtV) QPEן*b1;&w{}wzN ߿cfI +TcDDr9BЎ3☚,(c9PWc%['d3+3NȄ5(}M\'TFGĝeyOpȺ~ +z5 098:_wGF 9 tbM6ժuXGEXs+NWfsZSDKcxuWU!лQ!]?Jmms3q7H +G*2uۺJc T:Xp tzh+%B+ +c4c 5)UW-HQCJYZ|Z< 2N>A@\M|re`tl-B(Y@ +fvta$fg3>?.WVAycH|T4iYHQz +5 +ȣGBDR`.# "7}މ,_#CЎ~=1 {j1:ωBUl_*h#o4YM\ ? Y\ziIO|0D+n}5/]?9JqaKrbN+*I^N=O }KnuEYOnM: 2x*DYjDT @D:{_5Gqq5:J-)嵱8.*$٨ͪi2n${ gClּy݁Z kP#HeO[D݌FAlÏfJlD].UF٣ń$H;$$Ǩ cr|L@P?[T{#Bd#hm,Sζ#rΐg:A49@Ӑ衑0fHIlE5E9}DUb'i0Roүr*?{pCQ60֙\8;*{҆e=noA4ȸ +sr:c}!!ǭגEA^zE(3,\q:X2%:ê~. +{Ad U>quDhi{t˵xY-ඤ>bu̥:0$ek9@vNG[*`[ٶA6;mye^< +Mi/)w5X3fՋU YۺdʁosH/B:z=l;k¯y3J% %]uɿ"ͦ1/|Į*9$ +{b~2a~\|nɘ6Vei9YC~c^E1vao-d$(Xa΂;t6A髊3MUt(S7BX`SGvfnϘ$ő2ܻc#ɳ L4P#bn6BX kM]J2?AəL/@` ,+Opw&l"W14Bߥ ,sJ}FT[r]- ճŶ)7ERh'.h$5MI˿5Ϣnjтi*+5T`XJup0KÐ,*`gVGv(BQ̋0$QCC KVHPLa oRZ[BK?9/蟙 }xY2_USbϝa$ӶcƮm.A8քo+ԩor oף!HBȀxeKlmLǔD7dK eEKE> +*pBU=I M8iʴ/gwt QHuZ KJ),3923X1X ?w˫'|mjg122w;4P]+)|ROOױ7 :Sd/s%HFH md"AϞ /Na[[\D HmF[VJH.?ml|IbAN9)9ZCK(&NkXgOD/țFՠ+ Yfs{g[YWrcO76w\ߠOi/~ԭ18` +yˢSΤXXh_NQYX^fgqWB)*CQ݇wG>y^rwN1Pr +o.q,s<:x "Y-pz^l=Y{(+G&!ZcmhL!쮧2 0(WŒz"*K#Ws5|Yi,^엮/m-xskR,?'t f"8Nm% hgȻGzJͿ|~t.~!kΰ!j*=H~7bQ2mr6s'wBbF"wvc)cFRj4{IxD x4PP(~FEwKj&?"+e$endstream +endobj +672 0 obj << +/Type /Font +/Subtype /Type1 +/Encoding 2814 0 R +/FirstChar 11 +/LastChar 123 +/Widths 2815 0 R +/BaseFont /YVJQBF+CMR9 +/FontDescriptor 670 0 R +>> endobj +670 0 obj << +/Ascent 694 +/CapHeight 683 +/Descent -194 +/FontName /YVJQBF+CMR9 +/ItalicAngle 0 +/StemV 74 +/XHeight 431 +/FontBBox [-39 -250 1036 750] +/Flags 4 +/CharSet (/ff/fi/hyphen/period/two/colon/A/B/C/D/E/F/G/H/I/L/M/N/O/P/R/S/T/U/V/W/X/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/r/s/t/u/v/w/x/y/z/endash) +/FontFile 671 0 R +>> endobj +2815 0 obj +[600 571 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 343 286 0 0 0 514 0 0 0 0 0 0 0 286 0 0 0 0 0 0 771 728 742 785 699 671 807 771 371 0 0 642 942 771 799 699 0 757 571 742 771 771 1056 771 0 0 0 0 0 0 0 0 514 571 457 571 457 314 514 571 286 314 542 286 857 571 514 571 0 402 405 400 571 542 742 542 542 457 514 ] +endobj +2814 0 obj << +/Type /Encoding +/Differences [ 0 /.notdef 11/ff/fi 13/.notdef 45/hyphen/period 47/.notdef 50/two 51/.notdef 58/colon 59/.notdef 65/A/B/C/D/E/F/G/H/I 74/.notdef 76/L/M/N/O/P 81/.notdef 82/R/S/T/U/V/W/X 89/.notdef 97/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p 113/.notdef 114/r/s/t/u/v/w/x/y/z/endash 124/.notdef] +>> endobj +647 0 obj << +/Length1 788 +/Length2 1257 +/Length3 532 +/Length 1831 +/Filter /FlateDecode +>> +stream +x{yyv{z8`M45pr>qg2 9$F1 $Fʊ C0f֦8cq8*U8 !BPDHԀ!`р@VOD/$ +cd +A0U&wi^tĻ"!I" 0B//-$Dqi0aD!} >h.($ + iFcͣQh,Dp(C(d-xsQ;yy1`׶=!T$@wZ=&lX1LBHwA'1* +,s 8G&x&@E<$ 3&@8N^%Ø)^X2 {q8Xl +̉.,`%WFF#.`oG8"'³w1%lFX&K0&% iw^jv;ͩmhC6jƻ>9T0OyS/y|' Nߊڴz[ad}GͶ¢F3:1j<ƘRͩطxxbY,TrdttvwP H5{oʷ*~t0Yh6zL3ώeϝ-EU*y185] +OÜ+S+5zi80Ϝ.$;i6wJiݶa=Z׸C z89VK|J+(sϐ_wlv(Wn.Q0Lx֭ٗO}sgُU&\lw5puȆH1+4gc:KD*ixڇL&`jyUjGeSvzmYY+]:rIn3MbۖB-}|j}C\Q몔awgxNm5I|30[}ԏ )"dž4%*~sRE+WZ \IG6m,/7^O]`l nn2Ou5Pտ_bX> endobj +646 0 obj << +/Ascent 694 +/CapHeight 686 +/Descent -194 +/FontName /QARLDV+CMBXTI10 +/ItalicAngle -14 +/StemV 107 +/XHeight 444 +/FontBBox [-29 -250 1274 754] +/Flags 4 +/CharSet (/colon/Q) +/FontFile 647 0 R +>> endobj +2817 0 obj +[356 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 855 ] +endobj +2816 0 obj << +/Type /Encoding +/Differences [ 0 /.notdef 58/colon 59/.notdef 81/Q 82/.notdef] +>> endobj +627 0 obj << +/Length1 773 +/Length2 1036 +/Length3 532 +/Length 1602 +/Filter /FlateDecode +>> +stream +xR{8Y.jJQyEn3ø ]$d\~3soo|3*%TMEBwh+)T[h{zVϞ=9}V\1! \aŤ39%A37Q( 0R%X6aapض4s#dQ$* U9${B!8BPJi  +Qt0ۿC|PL1@@%(N䎇s[}"!)L96ʤ( !4ko: R^ [+1 HQ,/!)^`j Qt0@0T%VL[:s/FUP*D pq`'T|>/uZ|~Aq_ W@ZS +f &EUРp!Fq `BHAIl(.*Uak:N(- +&$UXZѨ(E\\UXؔ2lF߉8pq芔$ qBRTm$DNIȋuˮכ+~drt'd-?8Hc5L}Q`-a?xXk{0C)z&X6r43vYEgYOkdqLC_mͻ;6|ڑibTZPVnu|"&g\vb;[5|w眼*uPӉ3s G >n:nƒF6v\iuќh9:כ\WsXnroQޭi,$zeR&NGszᢂ#.~u~{.|כw^H"~@pĈ"qyeϗMOAHHyv EaOd{'-3[<_lyXXsZHtahwpJ}Ƣo3Arkwnz{,d ukcif]9{Et"TnIoy]HΎ7~%#k/+ 6D;nF_NdkK lm25NA[v+lu*P0yIj Mu&Ƭw/l8PR*q$u ?^mayfѲgy R"dԞ=:iC]\شGXZZ6sfShyɉcV.R?!c$:`)Ҍ7LBrn}$':`x[pac:t>}w -Sм'ۿNjbj?y\xzV- 3 -5-LuzΤ؄TMCkd5e_}g"LO˧vSȌiח5|̳r˂t,8kOL,,4<K*oKڂIU+*9uƬdwAsv$Oju߯m(l;yvOfR3}MIgĐza6~ RAH2'7ggendstream +endobj +628 0 obj << +/Type /Font +/Subtype /Type1 +/Encoding 2818 0 R +/FirstChar 62 +/LastChar 62 +/Widths 2819 0 R +/BaseFont /WOUJEA+CMMI8 +/FontDescriptor 626 0 R +>> endobj +626 0 obj << +/Ascent 694 +/CapHeight 683 +/Descent -194 +/FontName /WOUJEA+CMMI8 +/ItalicAngle -14 +/StemV 78 +/XHeight 431 +/FontBBox [-24 -250 1110 750] +/Flags 4 +/CharSet (/greater) +/FontFile 627 0 R +>> endobj +2819 0 obj +[826 ] +endobj +2818 0 obj << +/Type /Encoding +/Differences [ 0 /.notdef 62/greater 63/.notdef] +>> endobj +556 0 obj << +/Type /Font +/Subtype /Type1 +/Encoding 2803 0 R +/BaseFont /Helvetica +>> endobj +519 0 obj << +/Length1 776 +/Length2 1036 +/Length3 532 +/Length 1599 +/Filter /FlateDecode +>> +stream +xRkXUFG@Zg VevaYvpAV7X^P֙01;C"JF4I1#HZlD5`>>Ӝ?||^tPˡXX$V0F-FGQc%hj + +FH|*SH}Rat!RRY&$ɀQ@cSt$1P$<badL!b1 a +A!>Ԕmܘ2A&3l +g)pG|h6y7l WI2JgJo@?!Bhh2p"؜0U:T + P'B ax4b@#3PRp'\~C>|ժq>#(VkI}Ok.$0Tbȭ'aST +Hat"9>"f#Kf 228j\XOBCiU+BSFL+qEn@|C]0bfKI'`!4C X6U) +/=U>Z15]N _%zė>^zɽJidڞ (4nLv-qȦ# +޻b3ڻ}MG*__Xv'/ٝ7/!I"s_/nfk]J۷5MN͗jF}t,*0O"-i/.%N4¢||/qpmM۩@EjEEw<ʋcedмm#`% `𻝕1ƧU}"N&?ߜ{.(ǽ;`K>Z/^V2F÷!홵w5`&X;.A* fixUcۘnvfhCRUX…:9力JUdQJg8mynS'(; upyCWj}x@ +[`ZxuigZGH +k;>slJYQ`镏-W*ʬ9/d6^+f +˚+zY JEL|H]:w[MWISoݺʞs~[(:oe=Z}m5DR%BNVW_w%z%׍h% ||BgS.>ŦqZ}{ +eMYb_<['m>yDAŽ"g:3e!?G/S<t-NxW> endobj +518 0 obj << +/Ascent 694 +/CapHeight 683 +/Descent -194 +/FontName /YIFVKS+CMMI10 +/ItalicAngle -14 +/StemV 72 +/XHeight 431 +/FontBBox [-32 -250 1048 750] +/Flags 4 +/CharSet (/greater) +/FontFile 519 0 R +>> endobj +2821 0 obj +[778 ] +endobj +2820 0 obj << +/Type /Encoding +/Differences [ 0 /.notdef 62/greater 63/.notdef] +>> endobj +515 0 obj << +/Length1 1399 +/Length2 9741 +/Length3 532 +/Length 10598 +/Filter /FlateDecode +>> +stream +xUXҮkF!Ӹ!8]߿L\{ku{?F5jIUM퍁v. ,,r,FffEF.vbF.OV|‰ jdinW@dibd3rڂrTM,.av8@'7)# ` 4C`'i;3{Ȧ^r:9LI4AՀ /66FJOu#[Kaotٛ;T?䀦*bdci"lgn032n,a4Ut18сvԿ|0I*gQE`aP,=:̠.A?W1q;{SK;s+'4D x,L1 h _¿tLfh Ժ:odbokkG09MH&/f_,6r@ ZqDC\]!P17hb0)!P?T]rj@S!<5?T/5 ?!Ȑ_` A&B df/ٰ A6BP]T/5/p A6B ? +FDÛ4 p#,Ac#-1ffnVTW''??YKo6c h`ob!OE{ir1=ЃjyLHwB~]%{•wUvg?bJ* ~?|&ig\0v׳>c%[r>l{%ݚdY3Gwu!*)ۂb<2WQc/Ռ4&W(lpj;H\SR 0ga,zoGGT㟞̊FPM'jY؃\brFFIp~,3?]\׏a"&_~ajQ8\΄K{CDgT +ʓaU[ΒFm=;/n + ơQMrp&Յ +!Yʽ* 툾ܸtxY4@?㙻--wSư{1 +5-.vrB;rfe*armּ-"^blteE) qP=הWBGf1CxJ@ZkFrCy*\WAڶK bu/mN1ywe;\46WVd><(&3X7]PkVz{oϪ+(sxm3in'po`|mÝt♩F}"(#N6*1l& WW/<+<ɏ%'޾G{7)m +P&).aBi>2'xLwQY|Ԉ'>XyǸ>SLKԳ,ew&;̤Y?vxԐ;B@^|5'ˬ7 (FdRC9r(*I2}f`ԂCJmrF#r cbÛ1,V + ́(͍AK"KdH *{wC +! + A}Kae¶08}2|KBmDã+i1.>\ g'˿blo:a =&K"]P_M;L /$UF'C^ӗO_? ]ƧtY3֟ià ƽ70j*ITh(aV~*gkg4-ڡDNC'V-ɷO%= ! C` K֔0p +[aV[gBG4 +1:rr0q#f5ؚJxlHϯCy7p]9Lhh +TP[RkY>8NddLK$+SÐ1jFz#j +V( a*OT狡{!\0UX zUwgpxDml7fP;t$B3$I?^Mtx~9 /&̆`1ŐP~F x?!+ I 3K +LoO#8H? jbAOT@A,N|FbIH P4@[]֊;(*6BeF8̐2+1f0Flzpqִ "mD%# / ^z`f4Pu}ṍ` [#uHR1E)Sؐ7+P׈Mjx[G;hy hrCKd<9|95Ufr'9JM@Rwubgcrڗ(kf*)mno{S Qn^ev2 ~C*߀.K|<%[̂+Mg1THˣ{&Uޅ[:\A:*ngn,GYn>)\PqvI{^%h /u&\D&s?t%BV]d~yt߁4c&QY&FCwㄜ$D~R󆐦͒[%zyqȶ9v %'F]Dnk[ew/UO\2ߋՏa9w +x` :"ⵡo]J'Ia[{g &yYJC~ 8Q'0pg0GC5 r%8Ч("nU+DܘVx@$mAh7))΁jrwzrؓ ^Yj{A>rcc3DUOZ H5B7K>JCY~!mąI~$7k uO57Q>ƒ8ypрbV=uWs5>x0o*mjL0%pûE)MxZe6)\ 8#B@vٔŨf@iO|@ I2Mc@$e; iqߘoՃN.w~Yzj"w^< F*'TP_iW E@ec:Y +%LlEIbziK1Zծ 3d =V-$7cn8Uw*t .٠^8Kb +WҵM.P*/O͡Y9O3pP{TWwd}G8㻩̔ςyRRMTdآH2["j! ݓ& NI~ 7pvN2`6#u#LY9]}?`I.[^N|5fAsz)|i` )s2ٷQ`D{*'zY `e Y)ۆ9t0Ƞ~r%8c.ֳXQaWyç1Fw;4LҹE$Uyt &$cg ?&o5|/)+oʀ ]RW9ѐ{vrրRSd /!6rs.X([ɦ9{O2a> /I.л%M(~9\B>ꛕ⫆S}j a鱺AS9k^5e`=&Js/-RIr bQT +uk!ʕ]#?+#ICo7/cVČBZ(|ԮL7Ɂ<&!Gb(JJ_qHݷ˻iG.K3]9פ2-1ƃ.A +0ݾ<ҫVfU-:km6N.3m[,,GOc*<%IBr?Fقl+twMBP 0dMc{=Khx_1AAs&x@ X;2w;<*5 S5uc!9SVS1TE%)#Ωp)#틞5*c4˨p ҹPwfuN[ƠlkF }zڶ;Cl"\Vgʫv؈'`kF@s\r:jFGp5"ZEV3)g[+|N9,pBEzģ %Rӛ,GGB^dD1D.>$lOC"2[JnKbxj\ژ&C ͧI3i:jQklIv2.r!TSמXr| nKhj39aVSc+Z4H0tC#t[XBJ[HG09^n(xk fz*adpQ 2wr;ddzв|OO%+0|<zlZӁ#A(4`?qMEWݔo@sRZJ轄)7i>͙jWz퀂TI2 ;\')kmlb|jiA^i g2ZiieNz:#2f*wZDldfu i8ݫ]IxLSH"'G̯_zNFNԟ#gx6%dIʔ+m8x +: Zx ;~Yv/zV4&yւ(K,mZG1YYN=]7VP@e=1e`/Q+vy dcߜؿ?po"Xsߚ/aj;r)yE LRi2Rc2Us[)do5~SA R|:!m?f+G\s2Gȗ{;nj0=gu. +p;2-ZhGO lmAY |Osc嫆}]~[3E02mzZcU$rǒOr-jip!9\I?*|E +!W;ud"K<C и\ I-E ,>spKo{Es%WPG~Cbs~,2:7]tKTG3H 3%}5[H,D{ŕ@':'U!.#^ujP!_#r~Wё1:=ѧ`o@-="p`"i{>{R,?:&)qXp1,`i١7nL#niچHvi/sjftAsƘē|IO2U4(|'$@ʸJIW\8&U51KPR絻K錯>C iorAFV%qL¹kr- m]/Q]6N=}._y%.-gs+ >[T1lPH6S5IYO$ΈKIIy=8|Ƙ\]͍&ſ{l;Xry^hUf=Ͱ?DKK/.W=a%=&b`ub +0sM .\ + j% ZGH3?0Sj8LBImA)^o~xW6yab27Da(jOR57Rt6u*[`ߋWa&~?)MNl*){ł"ZkW WͨflwېcʊڣnEX}Gs&c@+F[wQ~e6:V%Rha:ߑjh +4>G)_`(|q0I#K8Eո]?kb4AbN -9`™@|K^Pr"Ӑ +,!9am==ͨ9N;: ׈mnİS%0ʴsy_ir},CXfάOK >e &6itѡJ ۴1#98Zɴat:ɨ,pآ7~>IyL0ۦ1vS-YO],wu6 t6qfZIKI#eh( vUɳ)n,EA$7 K)sGx@@7Yʂٌ7ORs\4 } -׭qڽkD>E(N%Lvd][5n˘edfE5SK/G8p*OB=޸G.鬖3Q\p|,p4=Ϟ_7 LlFN.FN+endstream +endobj +516 0 obj << +/Type /Font +/Subtype /Type1 +/Encoding 2822 0 R +/FirstChar 11 +/LastChar 121 +/Widths 2823 0 R +/BaseFont /GCTRBE+CMTI10 +/FontDescriptor 514 0 R +>> endobj +514 0 obj << +/Ascent 694 +/CapHeight 683 +/Descent -194 +/FontName /GCTRBE+CMTI10 +/ItalicAngle -14 +/StemV 68 +/XHeight 431 +/FontBBox [-163 -250 1146 969] +/Flags 4 +/CharSet (/ff/quoteright/comma/period/zero/two/colon/question/B/C/F/I/L/N/P/R/S/T/W/X/a/b/c/d/e/f/g/h/i/k/l/m/n/o/p/r/s/t/u/v/w/y) +/FontFile 515 0 R +>> endobj +2823 0 obj +[613 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 307 0 0 0 0 307 0 307 0 511 0 511 0 0 0 0 0 0 0 307 0 0 0 0 511 0 0 704 716 0 0 653 0 0 386 0 0 627 0 743 0 678 0 729 562 716 0 0 999 743 0 0 0 0 0 0 0 0 511 460 460 511 460 307 460 511 307 0 460 256 818 562 511 511 0 422 409 332 537 460 664 0 486 ] +endobj +2822 0 obj << +/Type /Encoding +/Differences [ 0 /.notdef 11/ff 12/.notdef 39/quoteright 40/.notdef 44/comma 45/.notdef 46/period 47/.notdef 48/zero 49/.notdef 50/two 51/.notdef 58/colon 59/.notdef 63/question 64/.notdef 66/B/C 68/.notdef 70/F 71/.notdef 73/I 74/.notdef 76/L 77/.notdef 78/N 79/.notdef 80/P 81/.notdef 82/R/S/T 85/.notdef 87/W/X 89/.notdef 97/a/b/c/d/e/f/g/h/i 106/.notdef 107/k/l/m/n/o/p 113/.notdef 114/r/s/t/u/v/w 120/.notdef 121/y 122/.notdef] +>> endobj +415 0 obj << +/Length1 1653 +/Length2 11610 +/Length3 532 +/Length 12498 +/Filter /FlateDecode +>> +stream +xvuP].nk0HA!{pw A.kwuj~OסT`4dvVN6!NUd,39xQhiA@N t@fi) )((B ۻ;ZYXB Z:,`NVv dyoKPz(/`Yd߼&6VE+S`vc0}Ԝް$@= +hrAVNNo+'#V`egjl79oBo70Ux*-K NVonmy!@+;'+ `fdotfh7 g'+;2`8,f6 '77쿪<){ߧV'9 +'[LS[l +;E }. ǿ W0lf sve0-$ῧ2 "L?]}Whge[cަ@ל:5q6mlQny,vopqh$c2SŹ6o5ۮFerrpO/x!&%5 NշNhۿtf {%rz!Z qrw_`>ؙj oErpK!M[-}m@( `S/i)j1inN؁ :\Jpor`SU[KP7 }W4ԛ'ky+aZoHϳ9 8]>15u'6nG;F?j\?\[{t1xPyGn.{vI3ci]"2Iu<#z1)9TbA裖Vf>ķ>"@1mYDn .TސQ>&_̸:(=1*(Xo`˥E]ޅ,P\QO[fuB.$2q#eV-B0p1]  0.>gzol}vo֥5a[ח̼Q[H3Y ׄڏѰ BaHؘj:XMxʥ5( 7_ׇ k7R@kP!_^N@'_@|2ΌŁndq2TXLe {7q7 ReѸ.}#5'rC?4}:.MX-g0u@G&އ*>26j0_NjM/ٙ]m|!B5>kk (p.4D7!tLs2b(|`yW*p"߭%;kAuF*!$WidYԸW-Umq-D5;O!im0"ܺtEvh3͐T!.*QcgپW c“Le3:Ui}+~vRVn`n-}6 +Xוd@ۥ9[O G7&f,cD-%NX 'vmT48 %sh1R۶..&Y<ž4c-Wh&Dµ|O֖?ؘ۲sK)Ά@D HiwM9"%R9ۓ׮WC>N r b/\=SIkF۳C uQSU'brv19[ +hZ%sʚ^7 `vf_iI}#{% +-6#(D OrMGCb])3:^Z29Tm+0zOC73O"npg8:,(w[q2Q9S19R`WC5ZJDupJg>BҳWL y ydֈto]tvy̨Z'2AX,Q2#&f/'rUbtNZ8$и'D0|ElI3zֿ"zt!EA+T'%kuK7ŁkjdaM4Vn'c@C2oؤ6d}- ڍz:f_{zsޠ$G[j Vp;֧f!-'AUӒkn[2d#-! nc9*Dg$Ht{iËj,!Ѹ^pZ}f3w+#BRm!ao}2$.vHsGs/7Ʃ5%0.GFH6 yHѓ7j_>e*c dK{O 1(PHݽT8t; +!(CYT_:sbE_v0XHO\w~-s#W6yT}nw]U}.ď$Fjd e_M¹+mh]z[F{w-s;R^zt|?I/(vr\j6e=1.6}%-+5 WbO9^NĽ$mĘ8+*K$s;A#":Uh#ڰiOqacFwn0]wE=Fw!ۥ ܶ~Ȏ}ollv{ q m62ȭjZNXt^|^b8;޸|(WQ#ʿ{LB}zrĪ]RF1ÕAˏЪ* +m80ϗ)%#5|4).0/wgxt|L2b2=A\M* 6KW+3v!*RY/&>d2jda z;LfZV&`3b1[A ?kJȣ͖|i%_Olv}}Ƀ"T#,Jv:*2t0%Z0%G'&+j0L݁>/(?SKDlj~>OG#;ZtUDa_Uꀓ;^moja؉̪H +&^4~ol#w,4$Ɏ+@V=& J:"X%>EE0|[ڧ΃#=XoI|ZȐŜ)9Y;3Pђ}{͍C T"vbR3aHZpTHWޙ7^B{&}z x] H>xNʃTOC MatóE<.OWXwvQ?{pT]$K'Xd~UwGWLYF 7>4ӊeVt5Q7 BtۿH҇yd1/tSƀS'R;<4AM83.3Is`8bxv7u,{ +rqZDs˳o=d'8lAǖgae^]Y}1 9${M.?]Zmہi0SkOoBԥ{񻦆\wGXwQ-'0G 󏞁E#9-) |0ehU!F(dQ3Ln\P7pY<"di`kyqP&p,]|Nhȁ#7E^"^8]"w--r׍YΆcN?u&' dd _*_w )"x{ype@&ͭ@O^&oWq@irlP#.lz~d RU mgGhCV7 +ǫ0W|bk~ΨsbI/09”Ɵ"&`R j?ʼjҦP~ >'LgX3cmOZ;QGȗR^\LuI1-Ghvp翽*6 +rF(zQB/&BNC>m™LjL}~j:5Ao:8gi`Vz!\9jqsw'h].cvQF}N!l&xڨ`!mDȼd連D>J=Cga]&qw7Bwme5$P+Gp_ȆK+,(8J8o(cʶ?w#Dmt[jq{+rJ/n.]3̂.Pe XgXZqAȭAȧpNzw]nm6y+ÏcV1ֺ퍽UR܅˵E{iX3.Nu']Էܨ,\I(qupZk3L 6DJ62=(ZhX*Gk"ԝJJRkd}ɤyL׷X%^0ON+f=6M=RMKfHBU̟N4#6\Lq|$Q\n[|PS&fs?{Wl nJY]G] ˁ,[etۉ,%J8١sd00L%|Ŷ6N-GnxA]*Y$=o',zw8 +R~8z +a@BMsu o]T R_ YC rP-6Vɏ$n&|oGG؁ۭi^&Am{]n,I9)"XJ.qr|SYK +$-Oä(2$}Yx4˷Mz蟺䟂;/Tjv) xI[/ H-GaU ١b٭ ,ړ~-uZ<:Y9|LWc5,g=elBo"o13{$*a3Zx'x'9 + ߄y$7b[-E0O98G{.RPPH 梺4$}&AfƢ +b?)QVʥ۸ ge2(Uje>6OG&Nr[6oc2ٜO9dQsk%'^ڔP$n"N3K/>ř `yW Ӣ=KIJQUsK2w1+L0j!)&#oOhYa*z$"%8"q3'y;$r%5-h!ԲbQI~Df0df ^1gMpr6;RC|A!aۧ1Wl)oPݬu{ oE[3oQ #q#%WÇDCp?tOK8q3}C54Ec럔4uta?cVio6a $pRn~Ī59A&&uazidJoMdtBF̬xJ^2؅!*Q1\3J&z=7$vb%]Zu-ZX'T&Э9n(HCXY7T V}`s6KfIc6YD=*;/昭Us4/G"r7n?_eV+@z/j\J1Me1/6cMyyt$~$:B[PPyuȾ.SLtNiVOAR}㢄< *[Lk +}"fI<7./3ZNү.H$eU5r!oS ϊHuVĔ60Cd4c&@h4dG&%0NO N؆Ym8k@JeRڴLנȄ^~[WqIKpeFExBc.KDb_x8.amU6U"H{·*K0{"7hKk G\'kBw܍Ztzp(+iHJ6{>-~VHiOa\ ZA y*%JaMu~[M +S7Ѽ^78Oo9jXFZψ}xU0 |2wZuXB7J-]Յ& yaZ`woA["VcRoE( +Zj΅ݡF¤P0gBb_fKh7^)a^2s}_s1_ >V7<`"dZ$fXtꍕDujLJBp߯3OFV[g-̪dш?T5]Z>{G‘GYꅸ%ς0@^H02W_D⿾`֖@"yJSЕv|vg(I->ZmS𱢃 +ÜQ:J-1sz Iv~W#44 o\>_`fiK#]h"hP [ЋQkM"sɑJ +7dWKxE,[B|H0hVʸs?$Zń|r"(t#5q-c%@FftGa;fUsgôCR^t>9bkl0pâLinL;v '߈f6|a="iT'Tdl>UFChKWWy@i4/%j|"T0jBB{&|'tKMr1Фi؃~C9::ԩB%FD{p9 ˣtB;R)"Zxy qd`H6I"xؑLp#[zEE'*i}t?c>P[ņl!0+a01F6~̊pQ 7O{qw7T}[2mK3Ol=Xo̭R>BW'käKD}9l ~iO%s!mŧ(4ۉ!H4A gg{ofaQ(~.hGԃ`TR(:9Bp Hv>"ҫ(hJPU҄NޅXf3QXY144#zxp{ VY$VgLԘ~D5FQFS Y,޳b›1f{qlĩWzǙ3>/eSVH# ƣM{VҲgψb$n[aSbpEwGѕ0Hp +"DyLha/F^ 8@8|FіJj/[6Wݒ8^{f @9w4la!ZN +~$wxL!;'dR L#o۾ᇐb̧|̳t:)gP+[\$C(4gX$d|Hf u#sV-%$D^v 3u#U0?JNpxW|ٹn0溧lD$Œ#iTnc܊#^twWsQ643pboSk9g|*{8Eɍr8U10$,G`/36Tnv}V6Bԡ |K4R<vKvZä,&8\Ȕ%U.X|km.,>MG7^ ~X)v0 ?i#j1>T)Wt jÐwB +J}?)4}' )&k:mޚ(-[IOP- rڟULǴT"2=Lf. / ۆ|=7FlaymJA}q?ep|\b:64.OqG W zm* %^>_IlSM#7Ÿ=}{}/|Yn+Swr -myC#\z*߯}DSb +IM1avG'6G/m08r-ŨXW%0UcXOj;+ƶ'kCQc{yj ϕWxO//š0ڟ;&EcxgޫuI5QB6dVb.t {W~=EOI]%XȘ ᏅMqeܳCr0P4#p%tw%3Ï(}_7WzT.uU`xD< [/3~Q!."gH#LiXu8D7iKIJ1!2c~jN]a4:ejIɗ$#F8//t$$0"g'`~Ao H6׹z +tg6S@{}rfkcWwЪ_s͹X8hI@l\bU itRV׶Kw JU|ͷnrҁ-rTTՏ5{?9? QRendstream +endobj +416 0 obj << +/Type /Font +/Subtype /Type1 +/Encoding 2803 0 R +/FirstChar 2 +/LastChar 150 +/Widths 2824 0 R +/BaseFont /ALHNTJ+NimbusSanL-ReguCond +/FontDescriptor 414 0 R +>> endobj +414 0 obj << +/Ascent 713 +/CapHeight 713 +/Descent -213 +/FontName /ALHNTJ+NimbusSanL-ReguCond +/ItalicAngle 0 +/StemV 73 +/XHeight 523 +/FontBBox [-136 -282 820 951] +/Flags 4 +/CharSet (/fi/period/zero/one/two/three/four/five/six/seven/eight/nine/A/B/C/D/E/F/G/H/I/K/L/M/N/O/P/Q/R/S/T/U/V/W/X/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/endash) +/FontFile 415 0 R +>> endobj +2824 0 obj +[410 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 228 0 456 456 456 456 456 456 456 456 456 456 0 0 0 0 0 0 0 547 547 592 592 547 501 638 592 228 0 547 456 683 592 638 547 638 592 547 501 592 547 774 547 0 0 0 0 0 0 0 0 456 456 410 456 456 228 456 456 182 182 410 182 683 456 456 456 456 273 410 228 456 410 592 410 410 410 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 456 ] +endobj +384 0 obj << +/Length1 1809 +/Length2 12776 +/Length3 532 +/Length 13807 +/Filter /FlateDecode +>> +stream +xUXͶp$qwNڸ]ww \%kss%o5%)P `ebaEM\M\|V^^6$qrp!Q@֖V1:qD k3hf tbTPA@s&$VV+hi#as7nr\Riv^s#L.fghbOj7Nn@@r]u_ed\MD,]$=֮fV ;@^ 0hIiמQU?i/fY{X +(&`hn` `@&^H&N+ z]C%X8P3[+od lhggOd:-\DY+O lk?Ap ';7?ɟ' +'Vq'r40ؙX ?^? w vVpt3a`].@\; `?ss3 FS!p?+Sq'(ӓCI!dxR"..(!pu?WCz!Lf˘_ zV!/ `'ۿ,e V`v V!/k_p n!X/kxA6_MTӇ~l \pvvʈ_8n'j3ߚ;!.9ڤKVAZ&(6-t#$BڕN9m6h?Wfa|x%vUrN ˻X:Kk߉!e''dyˑBeqCuR~=P.nm,;*vRU H $6W]nXɿ bb\"]QΈڷy9w[ʛku_%<=w;Hw7+&LVG5$`L6_Dw} +j8UM%VC u7MiZq1*8Y՞&E~U A\a]m}Y+Yf)+P@qZXm(u[5S~j}{|X &D{tT }Ƣ>q,6bNRJ&:Z+DVuqw a7:Ͱ`kLa8R"Mwb$x&ѾnUdc +(v2 bE<[B,=TU4pt3H!?W\f.(b'%˂ufz? M,MBy$Rһf=|pv7j <@ZAפWdYsh66E4 rM:!yjt4K'),brN6x*r)dSmR.3XF^ |9e^P2$IaFR^&eĎxXh】S_\UdUJClR'8Ɠ9zwBَM.TSpvP' YFt zh$U 6O]peW,iݒeu238& zJwRv'r,E}/Z\9J Xd[WI1)@ML7C9{;K%tAYOǢ"+NuCIREv儽;7g?>ɸv`#l$k̖ϫiap = T4gْOgy(>_ +MTP8yz?niKH>q5r-Z@Qa qCVؘB4aUG0Rz#~D St@tT@X;_p#svcĪ$|n&坉@#Pke)ϜeR!:|H+OˁgVb&H dajy#g(BunZ!dE" -Z/ATt[٤2dJ>~Lh\%lFí<+>i#~o*Eb%m:>PyLG]=ц}-/VfVcmU9}y\Ar{K>F"S/]Θou6=W14Uac!.NsF%MsկT`0^!Z5N̯Y}wstp"JkCF{"SSG2F7x3@Hh*PH\,j" *X' y\1B6vB:JTS(=w-DP>QM{r+g65{`]/lÊp{7FI,zRfB gXߋz +hB(%K)VvlS1T /Z_7->qU U%3tZʝŕ|ȶcUEO<%eu9% 4`і[?O_REa(.(ۊLZh732l_~&Zp3̝B%ZZMa4҇J|}HCL<'+i6/̺(X ߖ 'Wё" +>#}ǔ=D&>e ǘwm ~h֣E +ŽknG 6 چ08U72g?d剒kb`σ-JJF>qPKgfCs711Yғ M :#GN <,,N^416o%>ҚRcHmEʜ4kT孵~/f/T4f +u'wC&&ȝi[LS-ELMY5j"G |K"7}0{0/܆#jC wvkcegV[[rfn|xxP9aGܬdNThSƏO^m.[Ws4QׅA0))I"b_lgewiFHGsi+98S֧Ikڵo?a)y0A-^Ynې].Q|tteouN.#y(9y R~~wZ| .GOG9̓a†NEua!?^'I)&0&J%Md +4N~oyh}(5[~}^Bg|zt[wV!+})7 14;BD]Ҩ[[yBX0fְ,C[.6H?>J!'q+H}kq|cQ%?{Qz9\}V[^{dR ƈlq'd}iI̱oqmx98..6wQ}OqO{Bɞ_JSpj➐ 4K4l[y%p'WizC$6:ٗmg_oYcxM:QS_mn/PmDwF2=Wfq"QIp=w +iaH }ӢP]&5]duăك,6m0v04l6 +ט?MYo!WQh"ɬM\I@/d$ q.,ksBlPM[+c&ޘeP!u"Kڤ]AsڋȲIs~3Xײھ iY@ÅfKw3< 9v "=e wsŧ=O*T,WJ(ɲ}WwHɯ Ah& "P{u@ +C!6cޞ$g")i~4~bZ%?R\QjV}EW]L n94L?ybeq6-laX$&-W}>㓠0τ?GWJHv;@K i#3f_?`ek#1vT͈ 3خDB3#$*d7R! αN:rF4%ӗ{bʊmzF 3GVuOo '' l#IQ|רYhV+㊍̿B 5>&;BsfVxgn@ f%ɫ']dtܭQQ0s VxzzM*Vڣƈ0(2U4r0_T-! +EIp3Y +Vޤŗ~̗npr$AU |?R}{M.wGc4,wfNh r-* U-u(ϼk~^AR=5] S/:ҨⓙV%kR셯Lnj&лGo#ڥA8~xn#Qԝ/:JOedۥfđJc aQI{~cg{x&_~׾]qqgvjM{vՠ=Mi6# [cĄd!vU09wF=f"3+ꓰH#Egq$n׮$kX})j> y/w c81jJ<Ѵ&V@Й֋mM.b,"ԈLtrN? QFv5m,|xw5U WB*JJ1{dT\V(W"%!,.]bVՙGz80t4+mQ\O;?<= TXۖp['ٖXM9LSS&;soKj~ " ˨^FY +`D>LtNS0~&E˛ z-xn„%V~;e;Rlcp>1v/t:kut!^ȞqC<=cvUoYXc"=&0ٸ1$X]uWJvN+r7eUfZ$/};<(O*TÎD/|*=O6h'˓M+Y;,lY`DŽq=>\ ě@PyKuƆ+fZ7~넰$r򽰰/':&fTqNQYYweO +"l˿Rk]D8̻2/a"Df3 kH)zaCd4H톖}`<v9fd  CǓz[.ˌ#v0OAS2Є1RKwฌȴq`t2iŢt3t*'6%u>ܼZCbp I{KN D\?<$똮]MtBJhRsz` +Mbʡ/ytҸ/г^::` -*v]_Ӣ7a,2Ȃ06/6O%E"eAvq}ŕ+qxe_4 C6#(U)טR Ydw +FD8GVgV{嘧0ɋѹSw<ߩiHsU1&VyxH$?K_@/hO*w̌Wj +>m5-Lu$EeaFZ2 ak{\MXJȔ'6cM攼:f(glFڕ ^L&q띞e!7Dߞэ2qr_~8;:CyxWֹGj#Gy'E,FɃL>bٽ՘!8,lѼ(|`$R&cT>F +FB@uQh_^azP짻 Mu*N/Yz!a^䮭 tb#sśOVH++K>%kv( Gcq{&M 㷸S|D̢!zS3A"۰ۣ2`˜Gn߽sǃR3OaTWh+k= '?Ǣ+lŒ]4ӿ0o +2Ux .{Gn@W x**c_¿|H}y*dʉ$Iܥ!)EA&IGZ ɛ\d7pTMl~6 G XuzԎe s +'""{|`^Ƒj-ЋRp]غn4Koz! ݗas&τ#q""VOעoI%<{^sb혿vKNj8"whef! ,(t,n9mc wA{*WOB6}s~G +)-SmLͻx C7߈t5^1{sZsVBKTy]!xk7i8UNKG"y;9sͷf1иo{~%iZ"sqnT%oRn?ֈb~y?RDs,L_L5ikgf'$~A5[o| +H/^-% \Oj~\S[|^U$?ﵺ}\"vW|y9CeG65WZ͘|W1 tYe2…E)̔kD'c~ZfMTp/뺎+fqn 7~c'^Gcfw~'>Ba ߏ`ӆwS\U#)711O=nܣF5Ի޶ og(4OѰkT}/IZG}TS "Eʚ[m *pwJ1VƤp؇x5** w߃PԤڝh E6Ax>pxSZv +nCPe8r=3 +RQ*u {?y#zDu/gYZ MBg ʏZK*XD%md!1#.yRpbCԋ4˔_ZXl#rQ D5t*lZ*81BkV¹HSf;C"s6jEѷpޠ-y=!-:=0n󙱐̪ݪӶVZ[SM˲W}"edT B\ +9uA1~gM?W6|T=l=nCQm;oa.^XlqH<We QMu_›$u֐}bt- k8MވFFjy +F^M5<Ag=3g[@JBuCEx=a~`y^9"3s~-U ׶1`?6[cHP fq肽WuO`E0ݷcYN YO Kʁ+ȓD+HMwvK*~'fݭ%Z>U=U 'AtuOfpfXVc7ٿRcbj( m*3(z]q6?KyPTXf]][% ^*㼋 fwe-bn#wk9nJa ^cAR*;W7x;> +mIT$( +;=N0CQ>!8;ؙ+lK3,w* +d5#WrJРaK,i.8{̗L:r +~ƥXu +oA˟y5\BXZ]=Z\%RMߴ-~전;' @<#ڑk(j@.Мt.b>$" +d*EWؠ6Q 3jw]Dh>0J #gsbISgθ)@'ڏ߻>걏xpU1m)[&(՟q1L:RjG 47U3 ̜ ~SV8M N,Ҭ<ԋ~F wF;o>q䏷w?}浂sF}Vc=[g>7y+V- bqZ1IVj-1V{FHvz 5Jfg/pZ,5 J@Cdls z[h/,}L 3Ys9wVdͼjZ9'T8} =337a_*FUu0pT ?b39"dP0qjT1{Oc SIRávKJ~򡩵i~s͋< y\֢>`5L7!cn0n" ja5~cvU犀R.C'2~5LYa֣ep M)Y8P|W.V@`K0t[™f*0xny닐JfWb}F.aa .mRt4 3lbSJo{++j =/SM̶t!N\/pvUdh=po[X: %YmKOZ>…J"X{IBO9ڳ>iHVMM*RcE#3ܼ]J^su@]Q9%'*9FMV i6`weO̷!fg|BQ|X޴dw}ė@_TeO=oinse89w|NUJiZ "(ΏPUOHQX{j>)6glA:*5(-ũF {Ϛl 'd@QE$bC|=J<{>9a% vzٻ "8EG+>,شBV7q61hӊB&hiR˲$ Pq_ek BW뾮:C:˟&=iTLrMiOܗq~(~`}TՈȢ ~PRrgc=ȉas̔B~4dT A*?aJrfNKs~;$lPʻ[-A'(C">¾?8TqQY5w18B2Жہ*&{'J$$>RH$D j8B%?Tt İ,Y2UrH:EoR]fB~9<܎E}Q!6aԀXphs)ehs݋ p:҈%#NzpTV-饣Am=#Ex$޸b$G)T8YB9ٺZ#Ee+S{qW}헝HQ7\x%@r9d7`o+?ct՟$v eH V/N"<럳;S;C;h Z0J'7RU-^G x_B+rX6 $oEq=9S<7]&L)f3[t*;[4E]EqS:x !?>PJ]߭ 7/_ñniW-gv찫9znN= ]b#pd3bHȔ)c2 X]OeKG-Y;9hkWU +aڣ_  %~gIIVh8|s*eN!x_Y#."v\m3%< ZLa) +_%, s"ǐpFR#\4!w]{n;ڵ!a˅CgmoEʮXRrÆI01N% ee,8/~O=htOZw_ˌ *ā)Ŭ뿾rٵ҃ҐVjR \-ONv@kH=ba>*ǥL}ѐh^3B&0?mj`ٙdrp6 RRfʼv8mà O&^B a[T}B(G|xsBz?ɣ ía!д酦T0CE>lM7UAmn`oqIl>cjG5JF.[)Ғ$1 Ѿ/C͗9r3 ;JEm;v!wXVAB{t׊1Fb*\}WVk^]WOK,٘9Ֆ;24b2a)6aSסmO+F0-l –d f  ƤKJQ[Cz UnݟH4`x-"U9^^g);H.3߫Z 1 # 6b^v5n9r,[k^݆!`w +czY&ah +} . B\eu_tA@ a[4UV]zVt|ĺM:{Lv5gb)X@~*\=Q$~DCC Q鞭I@6ɇm]fz pEŲ$bM^'g#8+ݱXb⮁V@~>ktf) +G?ʽtEN@$@7'Βg8uՃ +4h`n3aVtmSAf?LQ;2GR8;%VB$s9"*PltyEy!܅ +,et&Y.A*jb&c.,MxB +)1 VRTy +DH])>hH;ZEn}`kα 3Մc] ?/"Uf{xUR9OlY2eiW O>-"q!vs[nQAe +k$joit69UxRiy=&kOyS-k +_ 9ޗڅ$)&%O8A,nwJӓB3ӔHe~J+ o i~hGk XI94iy$v9W"eQs6_TF ~'"_ 7K{TS-`״itW99&Y-W;o{!EI__pmzKXNnXDKx-LT-oƷz^a$ uRsC'&3VCHu7ƋNǪJl4%fyCxYРRnC.)I-.{?r&:+q~/3q 16Fކ0MI P;=ѦLf2!^eTpn5 /Wd/ d&kfBgm3!I)Z^IXͫλe}XG{?&"_t3q{7?fAKɤ'%\[Em%.pw^߽ZT d-AT*@tފ߄x(19nZ3NdZRQ *+Xz_*ZO]L/_L.#˪aÛ1ϗkоҵ\Y[Ǣ8C Kw(ۼh;HF4upf+ܡ RxEWQs8bl>{谬7G5c`^a7'q?'M@& [w1endstream +endobj +385 0 obj << +/Type /Font +/Subtype /Type1 +/Encoding 2825 0 R +/FirstChar 11 +/LastChar 121 +/Widths 2826 0 R +/BaseFont /QWGRCX+CMBX10 +/FontDescriptor 383 0 R +>> endobj +383 0 obj << +/Ascent 694 +/CapHeight 686 +/Descent -194 +/FontName /QWGRCX+CMBX10 +/ItalicAngle 0 +/StemV 114 +/XHeight 444 +/FontBBox [-301 -250 1164 946] +/Flags 4 +/CharSet (/ff/fl/dollar/parenleft/parenright/asterisk/plus/comma/hyphen/period/slash/zero/one/two/three/four/five/six/seven/eight/nine/colon/A/B/C/D/E/F/G/H/I/J/K/L/M/N/O/P/R/S/T/U/V/X/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/r/s/t/u/v/w/x/y) +/FontFile 384 0 R +>> endobj +2826 0 obj +[671 0 639 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 575 0 0 0 447 447 575 894 319 383 319 575 575 575 575 575 575 575 575 575 575 575 319 0 0 0 0 0 0 869 818 831 882 756 724 904 900 436 594 901 692 1092 900 864 786 0 862 639 800 885 869 0 869 0 0 0 0 0 0 0 0 559 639 511 639 527 351 575 639 319 351 607 319 958 639 575 639 0 474 454 447 639 607 831 607 607 ] +endobj +2825 0 obj << +/Type /Encoding +/Differences [ 0 /.notdef 11/ff 12/.notdef 13/fl 14/.notdef 36/dollar 37/.notdef 40/parenleft/parenright/asterisk/plus/comma/hyphen/period/slash/zero/one/two/three/four/five/six/seven/eight/nine/colon 59/.notdef 65/A/B/C/D/E/F/G/H/I/J/K/L/M/N/O/P 81/.notdef 82/R/S/T/U/V 87/.notdef 88/X 89/.notdef 97/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p 113/.notdef 114/r/s/t/u/v/w/x/y 122/.notdef] +>> endobj +379 0 obj << +/Length1 1647 +/Length2 10220 +/Length3 532 +/Length 11099 +/Filter /FlateDecode +>> +stream +xueP-.[ Hwwwwwn4! n-@+ +uZ!@( \BBB:+d6`baa M7- HqprvO:n@ @M=iU%  ]PMwk( +A`n&+%OjnO\Rn@+3rBEݢ`ɉǤ@tɡ0֫\?IH&M#g|"EPVoL w| … +U1v73v^9c,tMg<4Lr$ŮYaf3TR!CL{7d}Is.[RxYݭ_m| g?.؈J:O)_ KwX=,Y"D0z I&i- +JgU]5?'ɠBʯ` tʈaLO@6&}k%a항8%}`K~KSi]1K{ޤL:˵-&̉meyY:i>]v+;Fx})96oXR fՂ +Fao6΂o2bNy!(܊ܚC}9 41Zۦ׉7>fETy_įBa}VR"K +DaD,97q,9#w{NXN"=Ҋ mʊgu7[AqEZ{t2 co:}>vL~I[ DޮdG?Tr=mXtk +\JEԻB4 .zyOUJ:ҡךRf], $iѻ9'< &+fƠ/B3]nϺ%]`5~xޘ1 G(BgTf݌z®',*^S^C;FɻBW7|Ǝ,x~Ŭ9#E vV0}3 Pƕe8CJ4FVrdrɔQ5E\>H =01awn3q .* )O粏cUOhtw/3{sS5&|fUcQep: ~_уG`=8Eዙy<'NѯylH5U .x^|lѭ=ݰȱh˗79?}LV iU*) e{ƀ*hLS +kLi뽥e[jzm3oahqu>BpZ +="C4$D ]VwDMṡ9,xƚ dzؔ&lآOe\@Lth!3_Feu2m5ԇ!9\u/ uL'e";"&g*'[Y @tO K;ACٙ{۰_ˢNA)ןkl([E8WolL;[IuϳҜABp5L"ɨ"&۟,:VCt3ULTjt`{&TˢYzJ1qЂwsYise\/;>yx|@4JQD6rN zZq(:]\$0* z~{mbi%6;Ʌ^Ys* +AZyuwTNLB&L|pFC 6+2|A1=\jqi3GXU]&Qgc_XxKeHޤEoĦ`4ŕ^QbRym'/o<$(/\?] vR+gI|.rV@Po(c7Qm85xG8h,$(nά_Y[VM],Aur +;eJg K,Q~^HK$Fq.KC5fAiQsifLb~0R^ IAuYNJsSn QqYʧ/:ZS^rNP{*]ݠ;3C Z#g a8f5]#V会.r,א%ˍ_ꉅi5Tʋe;\oT!P1pt/;Ucu"{pWVi;g$ꁸI)[*]#ySѺflDK)vf ^G +&IgGv*4||u8Qe;)Xm-XMGk}5n6=ؽZw ™%֍sXSC)(_FV&o6˨V]Hݠk}0r{Q#rCުra< +@2 N} pxY IzK)A^fHq>4 $>W]sŭ""ω%sqnbvZ8?QY + +Ö^$Oӆ66u=ũROi m.U_%dR˯$^~ًͮKA +&'ߙU]C.qKH5oCho_>ǧW2dN9 k6_}w8Ci4-w Xr\y +gz'\h }!jfjYPT҆6Z<!0J84j̫|)}|7ҥ_.X0xV.^cqWſd!vs:!ezf,\u&w%ܓQZ}L%.ls>k`S;,:|Un9GhrP7bAKu^/O;{~x^v%q}U)`S7W R< 1yTQG%"U +V{Nޟ,sp/8g )sR(ҡ_lg2x^!Ҵ-WH>LyWCAoa$ߝ﹇"^/5gT=+gId5d1udy7uMkhG3z'<5[ ۰h x#Bp0&*I^ަ+4EqbxݫTyH?m> oͪuCq͔PN߾Ew16)-قjч)L> 5M*bsBV Rµ`lBV}Y5 j3aԭ/AX7LJRb3|BrT&)˭{n? Zs&FAea;&S}?&5'?_EO(-+'Byk\X[~54sP޴\^tm^=DL;zc#2sP7f:lߤʌp~׆$6(UHz0)e\ID}HT~H[j.֩fJG=T}ts顭"eiPϭ"mn2G.QTG8^Jw5hگsJŒFgMnZXsiT)C0*WKx+hvxRF+Ϯ "/ )hK m*pzԦSpCsMJ3p ,Iq&T*cZ]SRO7(kwQ,{kNtv^c6}Km9Hs]̔ mnkΈurB w]:^ ʃ<ڀ>$c&a1P|b +1NL{5 aNeNHv@y,ۙ`tBɕ"+xR T>Z.EQ-M &_>|J=ƔFOܒy\'pS ت;"iWyrX}2mt5| +z]BX6/w(ܥe̬^bi#/ h#'N/`Yx=j@,|9lWX=0qB8Z ,L2&+NP‰Z= &u. I o}դmYb۽7% @xo1#Ħ. z2DyzJ^,rAFx>eK dGx5Ok<>fs]ӏ6ةųmWw>˧Soߓ0ߓ"'d ZY6&?\Ml6BV^VSmRgh_hk`}h?7 z,$a*of-w>糂c0ZnKj*[2ok#:~}Z .z-osg@x\cUFRw =gr +dQ3j#TU0jY XjUYuKqMBȡ?Z@$<,\EFf9EQکrQ?6gMkAfCӹGZWޡd9NV`}qj +a=L bV |ĊB|Wa683B0(/j~^ؘhl7%#GD(o"n?O2H^_Tm<}csqBq<{%\[_S~⿷&S.J0n[uSeѸ*Y{m9>%ih2.9 ,|ʀliH㘌N!nXQmH<|xmf[BVj݆'wۛQURt;O|Ʋ>ܣ$?x i +j 4OǷ!rDzcB7M/pNd1r[zܝe*z;E%;S RK. Ggu1lL#Mgm?IS-`G3z^x3ZXa{ pV7U>jdQ00s`_SJiݲ_㯋Je<ǷR}k?Z!.?WJp.Q_"P_ +/}u ~hIՎ"f`9SV ~DZgBzfm͆GAx|H TPQE1ʝeAekΌ :E,~͓֊ݟ};Wj \a;'[ґ-3V^~9qq Iza{!"lUI'I|F 4' ԄwrZ +㤊QR?dMm\[̬hlGHp H>E~.4nϰVc\E3Zܫ4ذa_~.iKw:9;L)D6ɽ/WLХ6L[}-Z+9{H69̦m Eґ;#S7.xiw矴Pm&^Q@GyR]W𮹠" (v_C.IAhѪxuj[jt=X@gvwIJw=a枩*1t—;nl +ԪkK+_=兟W1flM{3o׵fTlc z}P+TƕhB6NJZdz~$TuM **NEx) o:r6XkGFHTRcS܊]^sx"Ղ+ #/S~]_-  xl#tY4 &@GBt~z(Vۛˎ{K?hP.?Z:E)ЪyNݏeh5(EH;Wt|Nw+_RfVd Α +%]{h'Jct&1#C&}km[m&4LSqQ"sds +=e~!p,r9r'*/09PC`2F̆^EkQoQ]]' +\%[֭ (smETkYLY:4d~2=:Y ^OP= rKؠ`pYhy=͜7,oa#9LԘyQyzSKBH`pcHF|-B(/}k{29KsE2.GAؠU8ߖ-(ͷ{#dK*M,jQR-$X0(S?$Txb:DOm TH#q})vxDEjWK!75|4/>ACL3nQc"I6ŕ Z@ؽ"s;ExB>_JyfH\\%2| +u%C_9zx!ᢥnw9N;;Kѽ^14{՛PMSx{V!f^|MlDpLDĕr)R5ZR ~!ñ<p{G4 +Zt"kT5:'rI(Kg]\E<el+Z5W[jqerK=*ktdu'̃!ȋ&`ΰE*_\Ĝ+~(y9}I"+i2s79&1 ߜF=MC~D\dD.VM!|_}z6uZo7Ŵrج5j}n^Ir&|Lz[zudvG aŬZ[I ^y̦DʦsG79gscz5^"b?~`"C.Fhz{Ft + "K@[ݴ1ak{AȰR\bDSZyܫx*EmoNrA<)BH1`{5_:j&ijX" EjmO= #Zz3+Dͺf•5𪇹Ķײ$* GB+.YF>u礹 s5$V =;2R'Ț%vZD X=զQx(CAh5BIġ4ODbf A87R#|~K1K*w&Ϊ y1K`a(֖P5#32i|YY#ۣ&2OV U"$4Ǜ~og.fs+-B`.yWC6 +Icd!T j 5-4,IК|%_i%lMT1%ϼ~l|V,mM3C>|aȪmpߎwFt^J?$ Ѝ忖s V.?.(R e&sPQtW#u7dXv_A,m5-mM w4gK\buG8 ZaGs8uM{1fnR¿8$pMu;u U_!,SC|^ tH,³:Q(z-ukZi/\+>zzPZ9PVL Vtu·鄍gG)B3BՂ`*_U{T9d%eY:t{Q.u@M +ط]b)J$DJ 4f~=W)ۀyOj*1a4+V:<%eD$g+Fp%wϮb2Ϛqs\g9 `G0IkW}%43XڞsI}plo;!9ǫȚpQOjҲZ *l.%zz[ݱcXжiԼ1,I! W$%F/2gK?pϻBO^wZb[uĊ ]$ojtd̓iQqΛYak(r`moqဇ6"LOG.߳>JaWX|iC53C9&?˥~U:NJ +)E$$Xؘw'/~_͢L|[k#EWwG?DQ=Ѧr>R蛘LDQRh3*2jُ/ztޢ.|-ƀ||bƅ_?oM6c6{.xC->7l^ (Y#iTpdgԦcObHdZY2!\=x[WP9l M/gu.v@UX?R0 +16xBJW~%p6 ՠ!O-F|m \<:T#S0]BR=D} #5g, dw +Prdk1 v ++ػ nu%n%rVr9t0[$E%Т;O/v6f>Y=Y$p˽pOʐhh~R,V#|q3!˶ga VVFϴάj8m>.{gC*7Hk^ KQl'}{90_1lޑ`gf7\̘@F+(bw_ hj?Hb endstream +endobj +380 0 obj << +/Type /Font +/Subtype /Type1 +/Encoding 2803 0 R +/FirstChar 2 +/LastChar 122 +/Widths 2827 0 R +/BaseFont /EALJZW+NimbusSanL-BoldCond +/FontDescriptor 378 0 R +>> endobj +378 0 obj << +/Ascent 722 +/CapHeight 722 +/Descent -217 +/FontName /EALJZW+NimbusSanL-BoldCond +/ItalicAngle 0 +/StemV 114 +/XHeight 532 +/FontBBox [-139 -307 822 975] +/Flags 4 +/CharSet (/fi/period/A/B/C/D/E/F/G/H/I/K/L/M/N/O/P/Q/R/S/T/U/V/W/X/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z) +/FontFile 379 0 R +>> endobj +2827 0 obj +[501 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 228 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 592 592 592 592 547 501 638 592 228 0 592 501 683 592 638 547 638 592 547 501 592 547 774 547 0 0 0 0 0 0 0 0 456 501 456 501 456 273 501 501 228 228 456 228 729 501 501 501 501 319 456 273 501 456 638 456 456 410 ] +endobj +371 0 obj << +/Length1 867 +/Length2 1181 +/Length3 532 +/Length 1804 +/Filter /FlateDecode +>> +stream +xUkXg]A"}o 8"$4Pd--!H20Lh +/\DE]D- +% +(++@]s>;gs~g=gbv`&%A:B@&ҙ7CȄlM1ܰ|^\$"!{a0 tE,+.NA@Q)1KEX @#xi +0#ME&'$Ƚ2̷_H7<$A $FF 8 \T9h2R֋("3mYAJ" ! 8",BƷ`c~ dJ 1EPdJ8*v2L&H +fۥ0&@Be@8%PDV, Pt̠K1\ѤN+h 0`t7>FjvʟزE+B>m&ށ'YeSZ&׶ޖCi:T:, #juF=ύkn:M]|%ibAԬO]aOUʆZAC3'42m|e' 3.eB&މ@J?N#ȟblܖt&|8y苶6^)WbsO,2ΤIǸֆGuyI{ 4Z&5YWU7v+)Pz3n9guW^NP]7lZՒo%v/*Ys+R%++f#ߗ_jݶNWk"tÃZ}m6?Zq%W_ +1.LwWc!75dln [z#*/y!=ϕcU=m/rN7F)ʫxEJ?O[?+Rmut('*<Ĝ`S h]?IT3Bu߇zMxHd ڔ@_^BEB-coRh‚GN7rnm-o0D֟no<[1qTSxHwS hBWe&E1\ t4*;o?GE> |^qL(SFy}}y-9٢FUE@w}ÒBɎĜG3g]nTl[]_wF}'t&zMX^ +nBنs}uT?[Ct3˹bhƟJRg;|3 ٟfvz]Sp'v8ƆvS)_4c:9WvKUa2"ߤW=o,.;XgxU{_K*9ZUwMG/#˂OTF猦h]@hb5,qs%Cr=wjGy8rzbS\3Z SDp@x4gendstream +endobj +372 0 obj << +/Type /Font +/Subtype /Type1 +/Encoding 2828 0 R +/FirstChar 13 +/LastChar 110 +/Widths 2829 0 R +/BaseFont /AOYKYK+CMSY10 +/FontDescriptor 370 0 R +>> endobj +370 0 obj << +/Ascent 750 +/CapHeight 683 +/Descent -194 +/FontName /AOYKYK+CMSY10 +/ItalicAngle -14 +/StemV 85 +/XHeight 431 +/FontBBox [-29 -960 1116 775] +/Flags 4 +/CharSet (/circlecopyrt/bullet/braceleft/braceright/backslash) +/FontFile 371 0 R +>> endobj +2829 0 obj +[1000 0 500 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 500 500 0 0 0 0 0 0 500 ] +endobj +2828 0 obj << +/Type /Encoding +/Differences [ 0 /.notdef 13/circlecopyrt 14/.notdef 15/bullet 16/.notdef 102/braceleft/braceright 104/.notdef 110/backslash 111/.notdef] +>> endobj +368 0 obj << +/Length1 2191 +/Length2 16545 +/Length3 532 +/Length 17780 +/Filter /FlateDecode +>> +stream +xڬeT]Mp'w 9;];}o'}߿߀8s:UV]2"y%Zc(։PHFAL`+ldED(jbbebe%#ع;X;R +QN(`c`ad`K(cdnbP `daNG(`mM7 MM\L` - M,laQ5;llC.&@)BiR%&j&@?ֲ6LOa kI9;8MloɿdL-m宅 !ÿCn&NF愦֎&_ `@/ . !D3טf'_qp#bO:g-[#!+;,{JHhaklFh8B7)9bF& ZAf ZA 3dblh+!?}bf'FHo 6p 7&(Ӳ08ZeI);vv`cc't7w37*Z;Z8wan`kf;gz;;OXu(h+ M@U[E8ٳ5/q3Gـ&:s1qJ:Y $:" bKML$2"."."!(!(!!!3_O?l`lcjmA8'xNzџgy ؿd+T NV!P꯫he)_@+ V?_r V!/Zu{B_ VwW#P?"(pe^? '9;SJvNEwӿuM-o87#wejcHHT)5YSl]l;\Rv|I:EHϖT>rp}䏳11cc骶5ge^gd:P֑6V(5 +'MHeR{3TB#Ȋ `BSgVxzp˝s(kնebCe%X]A^e4qU P:p :CUv :s}Z)tXbv$VHvV1=eMBaSS>[A&Ga*uY7 dG,_w-'߯:R$b#`"5ڙxiyC:R>zc o_Eݾr_.-j +ـ|Z,2 i3tY Q8Q34E2Yʉ5qևU<<)Ixc2dM62v' +8vk7JaWw~9֘~`7VJQ?. pG#:M 捻HN:gZJ ,! 230|:G[Y>5˜ZjӴEb ~7.,}!Gg-Y0wZAk@>3=[kw ɬafks #Ov!%9F7Mia84)ZGwEwơD=sH8%aO~:QkP8;!pC~Rr 47#`ü{%J\!~](ȹC99#â\Ҕ;ZpXa2mU,6v] +.QԖd;fRxFW~d7Nh{h&tm-C 1?]seEbTERغd[B'1қ''h4!0:9]pXcBע\D,+> FZIݘʤA0eڽ DqZ ʂ沮=RMuNOQe"I: P`=qX{M#"ǃCKe;*SVg#LJZvZIMZxb{<]R(tds2k:>f#ypԑ] #Õ  ;|+g;$#"/Vwǚ.^D%(#OXT[6'u(=!. ю4ˢ槚А5Z(20} fĻ/z)GQ^ݼD{ d8>#mZAe3mɏ +r7׳HDs/J3␞q?W>v:WN +WO%$yՇڛ= $؏i MNώ1*:sD~~Ucz\-x ֲ5DNޭs]cf~g/ ϒ: +b_fFYP1\)~9S6u(q2.}iEWkrT-j2YK X+b W5_l8V ?md]icB)tm WxlC郎eNdxyWsFJ-o;2Uۢj2n^g{< aRas 3%TP!D ZνC~z OZړ,GaO^r{߱6tHF6Sҥ7ipKUtBg 4sk8'ma780QF"39~^-0Jsd.LWAkπ|*4"/63@>M+WgRK}~_R`bbxfT2})̇bq߮,V hw`GHA}7( V:w C YT,tCdVl'KtM&uhS'1@t-߀*3z@y#Qȃ? }5kW zeߝ3YR i]jKmIWqW֑a,"{'}p.$: b꘠X/WhM ~ד/ex.z#U;NݲX!#+GixX[TҒ +A< ֨Lhqt,^)́ؐLNOso_A8`v^ =V=pYƤghFqY5˗tYXhrũmt4\ E*_Yl]Ld2ۿ eJza.6E$U~g|SV-4uFaUvH鵒M| +z?cTwDS!p )roXxveJO-}JXmUh<&,$TĸaAyޘ4/(r_0Ur5U# +#+>kyCV"ꄘSB~5!3z}@0ee|"8j8 &Kt⣉JCWdÚ٧,Nʳ52/Cl$</L mWm1J֒lr}P0ŪYnQ<ٲ760lBF KKc[춄VeHy_S+Tnj%I^ֶt10ƻBWjy-k9ZuX BJfY=bzdBI҇qh_*'U=ɿT&J v_QvmQvq"H؄yz;bKd@"UN1ɜgp j! +qە_ +Mӏ-vLDs.ق׽3MxBYW>x头oz F*R/ RV@6R$1o &ZU7R'<e!0:RRn.ޟ>@v5]76]",.J !@# M:1x`ӗ ϘՅYo!Azg|`Vieq㻵yh-3y}aI(QOkZX OޓDG!QJUp NAԋ6\22 mI +`Jȫ 2Q=mPk6Cl斶Blᵝ +"DS\,cڛj_::4Ж`rŏ_=x͎ZT\23\Iq<ЙdG6JJW.s XMȖjb\>,P-@' * ,Y2m&])Pۼ_1Y?Ex}OR|'ۜuSlfQM5>ѻeAz:y˯µh޲ISϨ +Yٳw`Yʔz<~9RhVo̒BG˲*$|6 +8jU.Q6І5TZf:ٓ?E=!XceE;*Qkk<լUK 3bZ&vyju&zd0 c^2n'0Ȫ(z0r_RoCQ6*.~Ëob<.h +wd[鯼Zpz]#A博bey[5ؠC[ r/}f ȏVCʣ'mCiq&$ϙu=}$=fʛ.6lG nr?UJ~^Uϧ;[ID%B$OpKdpkE/?dǮy-b\B{ƮR |I;/`^+ Xr(4^_KL}ҳ,:\X"-ź]G _Tڽ\R>-05Ңp"౵Ӏ_vNlp_&Q!o# N@@^\ F70qP"2#\ʅ%͚6c0EaGAE:0E$ٟNд>uBCdZʐ`ihV\O5'#(ԛ#FUAo$3X-N y #3}SEAэ+{7K69} qkQbPU٣CvG/חk]G (cnSۛLtߘb4b@W9hZxW|$*1ͅ`lJ}ݧ'WXYukrܽg] + hb]aUnr<"}w^Y}גbK4XzF_UJSƖ=dj:;nR,di|88b]TϑV<_j_"uM5U}4Nkf\%yxWh +e|7WZ6YFjPl@JZl +qm11 ;%z̕)gS!60 n0̰*ozثorkte!_ůuD$G4 +g'Cg5 '؅\3 .rp2.2MFV_{& +1 cb,4DCa=5 NhO׷84jkW=ruc֮hݧV-S*tg<U[*5,Шb\s(uߴO26AVF 5nkUbf:}0R6ES}\%qYϫ_Ү;"Kx @ܝiJֆ*`WZ7BPSEp.F$Oѝ=]*4H}c#!u?.)m]*/ sO$C˖Ja%wH#-vX[q]nF+3[ֲ6+s4M$Y +(U\ɻ9#ʨ;jN/uK[M]GC$<Nht%ѫ"sgt$t҇:pF~&L+-nM—7M_$IGP$iɻWGrfGJln^V|^d^l\@7K[:kƇx(c53^@PP֊Ǐ GV^~+'b_a1͏ {tdM/[{~I~Tgl*KSɥPIW7sa]rz 1'F/6bo y،6_Àbs-?f2I܄NNM|P*s(3{/SKcdg5~~jj5WPi'tk}0.=A&BJY 1BXIQeǁ1`2Fe۽GiI/7ҚA23}+ -R W\H9O58C]l}2~o?Uܚ|T$>A@٭(,m)th#EDyޛpFh VhD%KQq%"Gk\Qk'P#/K{'IHs9]ѾYopJ5WdByKptq"5az]0+l&g)_~P9G/.x}}I!R,.X8tʧ[o`ٟ~~DѝoM?8@m Myՙ2ww8cw(RP|ejj tzCB L_DƻN;ͅYh@/P7vgn൞X}Ѫf2<9[P{X ܧF_2^7E'`*T_Jo.-+x)Td{QtRC+!> զ!z ]N}ёl >(p`6:hYłvˏyU{E灕UzE!5]]MZc%wNfk !ۓP%Y|77' MSȒ GdVi'DLЀ%@23_2"W*ɻn # +g!qW%G!',3l%GNG +:iB-bb74ۂ:XaK*YH'KyW%Ww)oԐX4m Fc *H)G0$h-7Te搜ǵ0=\u?z r_ЂV[m}`nA72Q@q.s;+cL,TʌK$|c+*qHGv_([^u'=C)L-rX:2!:QH" `W +BJ]eqw܆M6DԗԬ;E29o=[i¿ѫ:$+h>[P#^^$ F彄(2\y4sicM)(\F#r)U92R|w7zhﲈ6Y"eDvx{rTNk<,̗kTX.՝RL*3ԏFg(t:(۸>&%BCi"q|*<>v]gyBSA־u|KR7&K0҉QY4NxlƬw/fF݈! `+&X]|wFmѓ7:+OUgщ/DUNЉﭲene_)ÙZ3 ҹ`Zc姴~QAsaJEE-.wϙ\jPi0d}oj>CYRkb$ND̘XM` ']sBw&^8^5ecrqYz\ȔKy8yFm\ +D:GH:GL "(9dz  +kn5$αFfdGRm"8J<,F[˰x#vrљ_zk(6j# +qɭ`xf>a}HL/UܳGkӷ%MJG~~˅T5*_)g~4M޸D+#_i3|þiqk%vל\?λ!6jꐬ +d@ [=UUEDLчiF9Ng *[A<:{@Azhj%] $qZT[% +jXU;ibMDϗD4Y2o;`Z*omd:&&,3 x1[&H]o+zOWD$WͰ]5 HT *# +glu&"Q0 3sh7&&irjOy_IOIf +gjj3Y|An/aDzr0pOOx%/J8qi 4o+SRx;hLs0rn oftY. }>boٟhm_J]zeq; h%5Drj~4|gK1܃9Pm0bF?%I{i/ y#Y-,^js0fa}8kdtb:QPzEwuldn"J[2EX@qu[|]`mҵ$`%nbhV =Dž8*)xКQeO:&I9 Rt,BQsR>*ܭ}&dUs;'vs't1;wq-8:<E['uL t 덇ydW"{71\(SpBCئ}g+gJ?[Նc?m>e BTRp6+L_;]u9DosjeC?_B,2/#ǀW&DžNz{%zo +,uَ }n"~#:[vpI^x^f?*:Cq>&l H&| N?>IgW['݃B1 |2aMK!Heb|XPo +%WpY-,/o-9!-VTb}GH3V[ ܳV}f~b f>׈ƻ:J{"0$p횾^I2XM6mNLpO}'r~'VzN^? b$ +=}%ݍ +wl ^y_akv+ d;[4i{m/^Dr +:71i0eWi|\"{ҵT ;^ +hnbPRV7\ q,ĸdޙ/fVNMAn-9i?فSguw5X{x8v7nO`vsj(tگ0'ysԔN ƪO"x|Ԝo&vs& }6@\O[Xz&ȹEY?%{ `u/LAzfAjeh|[uS3k4L^=ή~Yk&S:WA D +Ůq+#L͈z+xБ[9_+4dK~q#X)-?P:;Q=4DJ5C{r7%{v rce,Ff!K5!HBj'~7 +ނ©G[y!jDA$!dUCP@9,w a=aS(\XfԡfBr=CxtBs5դeZ6% +ħ L^}/]*8+npNco/orXlQZu'Le󫈦b}+懼`ħ.ZӼ[ >qOqN'8uO_۔p) .wl<+]lBe4N鋅"08 M}Q>茦<8OٖeECi  HC6RdWKL"H45.h)>& Lˠ/G"#l!N.~KR4vl 7E޷&aGHԒ@#}eE WbQ=Ui鶩̼4:Q^C#QDJ+?BLJ뗪ΗpFF~9ͧ\Eq7l+_SunEK-c?<rU~HMxqk+>y+d'f1;Q:1|ŗ{VQ&M,{F)ߍAB3?垥YR _~NYbKck@k !q0$ R8 K[+KrI'tq`ɬ ʿ7*0t?zDㆡJ؅.U3p-6-uKfXbU[L Ia֌=M/PvsoX 88R{;Tj.mP:d5}b86=%"(x=~HsɗAXYY.KOe9ߎ-gn.A›DwpyPLTm3)\Y[na֦*vȽA佴ްbx$]?&f\ gTO,GZy6nTЮ3S* R*mb1Ő:0󙂀KpSZmNX@C`r< :`7EMREƣ<sGLTQu|Y7c[ -kAC HSס +M]k7".sz$ERʸ˜;d784mwRRifS*{=lH^!U m;*CJl@*Kԏ”SXc1x9@47MV"ViFψ^D*,?҇[oGD$N* +"i]8ٿCSMe3=m4VRϯ?6hAŐJ|m7 ʑg(]]NA0v|u w 3Gny|t:Ee`~p2lٯpm\\5>{o>A9g;Bq"8@7v* ?UGR!~1bʊ1_dRBQ_JO݌V7W+ 9=1L9MٴCˑ^"+'HebS ضLL*`=V#5::=SmCCyW*/ՙ%-}hU".6u NqKr`獧 oG:~ ܼ33j{ ~jhU%-!pڇ42S]HfvqޖN Ml +caߊ~a[99=ޥdX}c+iExhuġ !čdۛ݇J63t ޤe1sʼn$Y%M 2Y."{Zxޖ)y(x:lB< +nDp'0>wJoʉ +1HS"ܙrYn_H|$0?=.원$xڎ˟.ۇ! j4N khN9 L볼_ +5pޅoClCQ&Z%!Fi;"fWddp*SMAx]j_t,7%mGyЀ-i!4~C4dk8h0zxo|+EDǓS1vcT1-Cq%ʱIu5+k + Ա>=g4F :X;@ +aTj.n϶Yi/߃Eܿlt0KLcq|uYEŤgLe3vX.*J"4y!? 9. /q/d8rB0r&H-pG&qtntxF%&٧qK2(תc#/_$Yr}6 =Ხ.piHٲfi(vN[c-Շ*g9苗R 񤠶~]RTm%K}÷ HIh|KݚxQ@N-h f,L.Ē@} %t̻Tr9:?mF/|2xV?m.}3j#dQ\5뻔Sd,Ӷ$_Q)YwJ]b#y,f.saCٌ{l_ܽo'?*?=3q҆'_[ޟjx/⦪xs*_]zj2))Y?m{vQù55?QRhx(i๲Xl{4_l'3WO IKݩ{Za|Bѭ>v\}[Ȍe(iի*oQ@&/5mٺbOߟt`"rcラW*}kMmDԯ&oWg8/ ~ +5 +kgJu{-$.TeQV[ ]8 ˇm8RWέ~{U|f[ogh8j<ۍi杗cX(|'IKs/O_ӏkh̸觥gV*-0(:aR+avUbM(j_9.r(HCӻV8脾srUCKt[Avis']0{Wcn׼}Uaү'Λ9c_fX;G;'ovw1-O+y0ɣG&ӣ}CW7{4W-I:#sAKlq9&嶯r;~,(i䭏O|qCZDdYhuܮ%RUyK&t7/L^(Hn_.cY?Rb+^lݽwwK5v]Zc%ͳlNo^\~S(a_o}}kEe:WIL[Rsuv\">PF $&&es6endstream +endobj +369 0 obj << +/Type /Font +/Subtype /Type1 +/Encoding 2830 0 R +/FirstChar 11 +/LastChar 124 +/Widths 2831 0 R +/BaseFont /AKXAIC+CMR10 +/FontDescriptor 367 0 R +>> endobj +367 0 obj << +/Ascent 694 +/CapHeight 683 +/Descent -194 +/FontName /AKXAIC+CMR10 +/ItalicAngle 0 +/StemV 69 +/XHeight 431 +/FontBBox [-251 -250 1009 969] +/Flags 4 +/CharSet (/ff/fi/fl/ffi/quotedblright/numbersign/dollar/ampersand/quoteright/parenleft/parenright/asterisk/plus/comma/hyphen/period/slash/zero/one/two/three/four/five/six/seven/eight/nine/colon/semicolon/equal/question/at/A/B/C/D/E/F/G/H/I/J/K/L/M/N/O/P/Q/R/S/T/U/V/W/X/Y/quotedblleft/circumflex/quoteleft/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/endash/emdash) +/FontFile 368 0 R +>> endobj +2831 0 obj +[583 556 556 833 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 500 833 500 0 778 278 389 389 500 778 278 333 278 500 500 500 500 500 500 500 500 500 500 500 278 278 0 778 0 472 778 750 708 722 764 681 653 785 750 361 514 778 625 917 750 778 681 778 736 556 722 750 750 1028 750 750 0 0 500 0 500 0 278 500 556 444 556 444 306 500 556 278 306 528 278 833 556 500 556 528 392 394 389 556 528 722 528 528 444 500 1000 ] +endobj +2830 0 obj << +/Type /Encoding +/Differences [ 0 /.notdef 11/ff/fi/fl/ffi 15/.notdef 34/quotedblright/numbersign/dollar 37/.notdef 38/ampersand/quoteright/parenleft/parenright/asterisk/plus/comma/hyphen/period/slash/zero/one/two/three/four/five/six/seven/eight/nine/colon/semicolon 60/.notdef 61/equal 62/.notdef 63/question/at/A/B/C/D/E/F/G/H/I/J/K/L/M/N/O/P/Q/R/S/T/U/V/W/X/Y 90/.notdef 92/quotedblleft 93/.notdef 94/circumflex 95/.notdef 96/quoteleft/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/endash/emdash 125/.notdef] +>> endobj +365 0 obj << +/Length1 1121 +/Length2 4740 +/Length3 532 +/Length 5479 +/Filter /FlateDecode +>> +stream +xg<\(!ZCQ 0G{(D/$z5H5/~Zo~9XuPeK +BX@C `"w97[@HI +KH +r +gO$p)pJ䜠Hh@PvP'EX(O@xk+ +EC`f,08!! ;l%w(c +˜0pGOjCD`jA1N&&e$ PP$"N5Mj ss + +:BC0Wej CY6GW_q(&0}HSၲc޿5m tGW_ ͘ ah dZJp+5 Q1DB< 1!Q P4Ec f /`@:NQdl@ΘcBXI /(O@T<~FF7a!HM"H 0* b12 A@!d + ?cb:)1 ?()߈dA𿏋</, 1. +ypTE}AA"EܐH( 3P(jEya%lZO`.m]۶x,ǢOj.:;.qi++^ {ߜَ6Hj6EF{_&k#_KQoZ`1qC G*NaGdi./E<Ȓ ه"n%^|}B5.f +prDE?a.xx~Z?$\J)ճ'Z SZ)v4jO7e =hn6`~Y+vҙTrt(5ktR5Lr >Ec.$<<+*v9VFu WыG_j$K _! Dí̕޷ٕލ iྺktN~pyȜ\D.-֋:YASAI|OJ| eO4?4m~gwRn0~al4͠!73u|Uq zr&b7Hib'UҕQsJI(4+jWݥ8L^Yh8Mq3PcXXzVbĉUڍi^[IUĭ{p&v@bIW򜈹!,o^b {pk-(/@m{ϛEe3E\561|?*<G84;9-+|4+P ![ S]R5l;ܯɬ`|L"mU'O"CuvA6Y@&T Jsۙ~";~]CbmD=:rbɞ˨1Y&kpDɬ_-:0<9 l޺Hp^ԃn:X'W a ++@ϕR).C#Pħ CXtyQ +šiNh Z ݮMsq{t,>]VA+ƾ.߳:M*>3P;4 AX(u.e̶ :qg}YH6mp +v}4X@6טo#ȝ |au{KflucFmYB7@^_mn $ԆoJ$ܺKufKq0֠`6]UT>\Xo7|g^ƞҩ؏%q!) +;wA..~1ɜ`g\)VlSa[T9 ;t~fٝ +7e14o`)%~*t9("Gw]x~ulUFߤ̩Rɩ=+]Q\6>ıpR- ٬qA;LF }?O.Pc|DY˸/Y5<ĽjI~Jb^P/176<̾9LIO?^ 7+U&D}"Kkl ] {J}1lvWOnaQouݼX>ǩ!"U &Ebɳٮcn>ZoyHLoBg͘†S lA`8Kk~ F^6yeM.?E6mPv2G(*7Ći?%pXQxI3WQ?h Dd+nkԇ yiޛ|yII gci|q!ikζn\ 9R盱LNJI}@&5Azk\SFvznc l]vx_ %Sѝaꃐ+?WuLyc[S, wʐJcYJP-n] Ž:n-:q継m#* 3\}wX+]:Z%xrm2ڣ-UTG}[U#n.غaL}GJyF 2K^/>S~xlX]v Fc1C οڅs+,tۈQQk͗]x|necETKe߃|: v`W ; `Qk_svFzJ߻FWΠ +Lx +|rWⲌ+4]CAo)35wdŖ4LQsiHr)kyHu驱?GƿSWu(QὑS,7W?F (XTX!ae qU_ts +~v'; +$3ߝ _N Wg1;q + )Z F@~F{_x!vy0#tW3J'm*ZmAoMuШw%{ ,X9VVk+9RwXO {Ƈ>;Y}v/kV30xQ0bqr+*vδޖ2rs#s~R]>93RBi+ZP,HUz~-I+®1@A7<s ;?)Q6_ܜn/WL!KǬE:0!ҞIc`vj.pTѽ<16cTi^CƗ}1kCW^S" ~nUX3 ` +M}>ww15f4_,c?/K&7;T,@ }7q`+o9k& 9,a[tr)q`xO _I-^8ߩLN(̣*bLvqZ[%`\肃KPpQIN}GE7q%W#eiWA A 3tFEOz= ^󪤀/o΁5eiy$6`1RJ\Cn LDQnv؝# n$T)EG:y^Jj*~KNp1|4ͳ<(;r2ր GIx5:ťM3Ds2%1wE}:b_'P?r O7z*w,K'VڬƕGvm:7HoI-5}%)>Wg|JJx/{Eօ0wT7O-Ǹx6@^\WEj8evDQKdܧ{zG1E0Lloj7~Px&4ϼ=*KNM<iԼ)☐5:|j jht.0(ŬÄdemx܉V Vzp<)WUA#Ǒ=z0}b]fR̓Ġ*xMUM@x6E#$ +A:yendstream +endobj +366 0 obj << +/Type /Font +/Subtype /Type1 +/Encoding 2832 0 R +/FirstChar 45 +/LastChar 120 +/Widths 2833 0 R +/BaseFont /NCGFYV+CMR12 +/FontDescriptor 364 0 R +>> endobj +364 0 obj << +/Ascent 694 +/CapHeight 683 +/Descent -194 +/FontName /NCGFYV+CMR12 +/ItalicAngle 0 +/StemV 65 +/XHeight 431 +/FontBBox [-34 -251 988 750] +/Flags 4 +/CharSet (/hyphen/period/zero/two/A/D/O/P/T/a/b/c/d/e/f/g/i/k/l/n/o/r/s/v/x) +/FontFile 365 0 R +>> endobj +2833 0 obj +[326 272 0 490 0 490 0 0 0 0 0 0 0 0 0 0 0 0 0 0 734 0 0 748 0 0 0 0 0 0 0 0 0 0 762 666 0 0 0 707 0 0 0 0 0 0 0 0 0 0 0 0 490 544 435 544 435 299 490 0 272 0 517 272 0 544 490 0 0 381 386 0 0 517 0 517 ] +endobj +2832 0 obj << +/Type /Encoding +/Differences [ 0 /.notdef 45/hyphen/period 47/.notdef 48/zero 49/.notdef 50/two 51/.notdef 65/A 66/.notdef 68/D 69/.notdef 79/O/P 81/.notdef 84/T 85/.notdef 97/a/b/c/d/e/f/g 104/.notdef 105/i 106/.notdef 107/k/l 109/.notdef 110/n/o 112/.notdef 114/r/s 116/.notdef 118/v 119/.notdef 120/x 121/.notdef] +>> endobj +363 0 obj << +/Type /Font +/Subtype /Type1 +/Encoding 2803 0 R +/BaseFont /Helvetica-Bold +>> endobj +373 0 obj << +/Type /Pages +/Count 6 +/Parent 2834 0 R +/Kids [357 0 R 375 0 R 418 0 R 459 0 R 485 0 R 492 0 R] +>> endobj +509 0 obj << +/Type /Pages +/Count 6 +/Parent 2834 0 R +/Kids [502 0 R 511 0 R 530 0 R 549 0 R 580 0 R 596 0 R] +>> endobj +610 0 obj << +/Type /Pages +/Count 6 +/Parent 2834 0 R +/Kids [606 0 R 621 0 R 632 0 R 642 0 R 651 0 R 657 0 R] +>> endobj +723 0 obj << +/Type /Pages +/Count 6 +/Parent 2834 0 R +/Kids [693 0 R 737 0 R 746 0 R 764 0 R 773 0 R 791 0 R] +>> endobj +823 0 obj << +/Type /Pages +/Count 6 +/Parent 2834 0 R +/Kids [815 0 R 841 0 R 854 0 R 873 0 R 889 0 R 901 0 R] +>> endobj +948 0 obj << +/Type /Pages +/Count 6 +/Parent 2834 0 R +/Kids [934 0 R 972 0 R 994 0 R 1006 0 R 1025 0 R 1041 0 R] +>> endobj +1068 0 obj << +/Type /Pages +/Count 6 +/Parent 2835 0 R +/Kids [1055 0 R 1070 0 R 1085 0 R 1101 0 R 1115 0 R 1135 0 R] +>> endobj +1167 0 obj << +/Type /Pages +/Count 6 +/Parent 2835 0 R +/Kids [1150 0 R 1169 0 R 1187 0 R 1214 0 R 1232 0 R 1242 0 R] +>> endobj +1263 0 obj << +/Type /Pages +/Count 6 +/Parent 2835 0 R +/Kids [1255 0 R 1273 0 R 1303 0 R 1336 0 R 1350 0 R 1359 0 R] +>> endobj +1382 0 obj << +/Type /Pages +/Count 6 +/Parent 2835 0 R +/Kids [1369 0 R 1386 0 R 1412 0 R 1430 0 R 1447 0 R 1477 0 R] +>> endobj +1496 0 obj << +/Type /Pages +/Count 6 +/Parent 2835 0 R +/Kids [1487 0 R 1507 0 R 1527 0 R 1555 0 R 1571 0 R 1585 0 R] +>> endobj +1610 0 obj << +/Type /Pages +/Count 6 +/Parent 2835 0 R +/Kids [1599 0 R 1630 0 R 1656 0 R 1670 0 R 1687 0 R 1698 0 R] +>> endobj +1731 0 obj << +/Type /Pages +/Count 6 +/Parent 2836 0 R +/Kids [1717 0 R 1733 0 R 1745 0 R 1757 0 R 1774 0 R 1789 0 R] +>> endobj +1833 0 obj << +/Type /Pages +/Count 6 +/Parent 2836 0 R +/Kids [1824 0 R 1843 0 R 1861 0 R 1874 0 R 1889 0 R 1911 0 R] +>> endobj +1918 0 obj << +/Type /Pages +/Count 6 +/Parent 2836 0 R +/Kids [1915 0 R 1920 0 R 1924 0 R 1928 0 R 1932 0 R 1936 0 R] +>> endobj +2054 0 obj << +/Type /Pages +/Count 6 +/Parent 2836 0 R +/Kids [1940 0 R 2056 0 R 2171 0 R 2290 0 R 2401 0 R 2519 0 R] +>> endobj +2755 0 obj << +/Type /Pages +/Count 2 +/Parent 2836 0 R +/Kids [2636 0 R 2757 0 R] +>> endobj +2834 0 obj << +/Type /Pages +/Count 36 +/Parent 2837 0 R +/Kids [373 0 R 509 0 R 610 0 R 723 0 R 823 0 R 948 0 R] +>> endobj +2835 0 obj << +/Type /Pages +/Count 36 +/Parent 2837 0 R +/Kids [1068 0 R 1167 0 R 1263 0 R 1382 0 R 1496 0 R 1610 0 R] +>> endobj +2836 0 obj << +/Type /Pages +/Count 26 +/Parent 2837 0 R +/Kids [1731 0 R 1833 0 R 1918 0 R 2054 0 R 2755 0 R] +>> endobj +2837 0 obj << +/Type /Pages +/Count 98 +/Kids [2834 0 R 2835 0 R 2836 0 R] +>> endobj +2838 0 obj << +/Type /Outlines +/First 7 0 R +/Last 354 0 R +/Count 5 +>> endobj +354 0 obj << +/Title 355 0 R +/A 353 0 R +/Parent 2838 0 R +/Prev 351 0 R +>> endobj +351 0 obj << +/Title 352 0 R +/A 349 0 R +/Parent 2838 0 R +/Prev 79 0 R +/Next 354 0 R +>> endobj +347 0 obj << +/Title 348 0 R +/A 345 0 R +/Parent 327 0 R +/Prev 343 0 R +>> endobj +343 0 obj << +/Title 344 0 R +/A 341 0 R +/Parent 327 0 R +/Prev 339 0 R +/Next 347 0 R +>> endobj +339 0 obj << +/Title 340 0 R +/A 337 0 R +/Parent 327 0 R +/Prev 335 0 R +/Next 343 0 R +>> endobj +335 0 obj << +/Title 336 0 R +/A 333 0 R +/Parent 327 0 R +/Prev 331 0 R +/Next 339 0 R +>> endobj +331 0 obj << +/Title 332 0 R +/A 329 0 R +/Parent 327 0 R +/Next 335 0 R +>> endobj +327 0 obj << +/Title 328 0 R +/A 325 0 R +/Parent 79 0 R +/Prev 319 0 R +/First 331 0 R +/Last 347 0 R +/Count -5 +>> endobj +323 0 obj << +/Title 324 0 R +/A 321 0 R +/Parent 319 0 R +>> endobj +319 0 obj << +/Title 320 0 R +/A 317 0 R +/Parent 79 0 R +/Prev 311 0 R +/Next 327 0 R +/First 323 0 R +/Last 323 0 R +/Count -1 +>> endobj +315 0 obj << +/Title 316 0 R +/A 313 0 R +/Parent 311 0 R +>> endobj +311 0 obj << +/Title 312 0 R +/A 309 0 R +/Parent 79 0 R +/Prev 291 0 R +/Next 319 0 R +/First 315 0 R +/Last 315 0 R +/Count -1 +>> endobj +307 0 obj << +/Title 308 0 R +/A 305 0 R +/Parent 291 0 R +/Prev 303 0 R +>> endobj +303 0 obj << +/Title 304 0 R +/A 301 0 R +/Parent 291 0 R +/Prev 299 0 R +/Next 307 0 R +>> endobj +299 0 obj << +/Title 300 0 R +/A 297 0 R +/Parent 291 0 R +/Prev 295 0 R +/Next 303 0 R +>> endobj +295 0 obj << +/Title 296 0 R +/A 293 0 R +/Parent 291 0 R +/Next 299 0 R +>> endobj +291 0 obj << +/Title 292 0 R +/A 289 0 R +/Parent 79 0 R +/Prev 279 0 R +/Next 311 0 R +/First 295 0 R +/Last 307 0 R +/Count -4 +>> endobj +287 0 obj << +/Title 288 0 R +/A 285 0 R +/Parent 279 0 R +/Prev 283 0 R +>> endobj +283 0 obj << +/Title 284 0 R +/A 281 0 R +/Parent 279 0 R +/Next 287 0 R +>> endobj +279 0 obj << +/Title 280 0 R +/A 277 0 R +/Parent 79 0 R +/Prev 263 0 R +/Next 291 0 R +/First 283 0 R +/Last 287 0 R +/Count -2 +>> endobj +275 0 obj << +/Title 276 0 R +/A 273 0 R +/Parent 263 0 R +/Prev 271 0 R +>> endobj +271 0 obj << +/Title 272 0 R +/A 269 0 R +/Parent 263 0 R +/Prev 267 0 R +/Next 275 0 R +>> endobj +267 0 obj << +/Title 268 0 R +/A 265 0 R +/Parent 263 0 R +/Next 271 0 R +>> endobj +263 0 obj << +/Title 264 0 R +/A 261 0 R +/Parent 79 0 R +/Prev 219 0 R +/Next 279 0 R +/First 267 0 R +/Last 275 0 R +/Count -3 +>> endobj +259 0 obj << +/Title 260 0 R +/A 257 0 R +/Parent 219 0 R +/Prev 255 0 R +>> endobj +255 0 obj << +/Title 256 0 R +/A 253 0 R +/Parent 219 0 R +/Prev 251 0 R +/Next 259 0 R +>> endobj +251 0 obj << +/Title 252 0 R +/A 249 0 R +/Parent 219 0 R +/Prev 247 0 R +/Next 255 0 R +>> endobj +247 0 obj << +/Title 248 0 R +/A 245 0 R +/Parent 219 0 R +/Prev 243 0 R +/Next 251 0 R +>> endobj +243 0 obj << +/Title 244 0 R +/A 241 0 R +/Parent 219 0 R +/Prev 239 0 R +/Next 247 0 R +>> endobj +239 0 obj << +/Title 240 0 R +/A 237 0 R +/Parent 219 0 R +/Prev 235 0 R +/Next 243 0 R +>> endobj +235 0 obj << +/Title 236 0 R +/A 233 0 R +/Parent 219 0 R +/Prev 231 0 R +/Next 239 0 R +>> endobj +231 0 obj << +/Title 232 0 R +/A 229 0 R +/Parent 219 0 R +/Prev 227 0 R +/Next 235 0 R +>> endobj +227 0 obj << +/Title 228 0 R +/A 225 0 R +/Parent 219 0 R +/Prev 223 0 R +/Next 231 0 R +>> endobj +223 0 obj << +/Title 224 0 R +/A 221 0 R +/Parent 219 0 R +/Next 227 0 R +>> endobj +219 0 obj << +/Title 220 0 R +/A 217 0 R +/Parent 79 0 R +/Prev 139 0 R +/Next 263 0 R +/First 223 0 R +/Last 259 0 R +/Count -10 +>> endobj +215 0 obj << +/Title 216 0 R +/A 213 0 R +/Parent 139 0 R +/Prev 211 0 R +>> endobj +211 0 obj << +/Title 212 0 R +/A 209 0 R +/Parent 139 0 R +/Prev 207 0 R +/Next 215 0 R +>> endobj +207 0 obj << +/Title 208 0 R +/A 205 0 R +/Parent 139 0 R +/Prev 203 0 R +/Next 211 0 R +>> endobj +203 0 obj << +/Title 204 0 R +/A 201 0 R +/Parent 139 0 R +/Prev 199 0 R +/Next 207 0 R +>> endobj +199 0 obj << +/Title 200 0 R +/A 197 0 R +/Parent 139 0 R +/Prev 195 0 R +/Next 203 0 R +>> endobj +195 0 obj << +/Title 196 0 R +/A 193 0 R +/Parent 139 0 R +/Prev 191 0 R +/Next 199 0 R +>> endobj +191 0 obj << +/Title 192 0 R +/A 189 0 R +/Parent 139 0 R +/Prev 187 0 R +/Next 195 0 R +>> endobj +187 0 obj << +/Title 188 0 R +/A 185 0 R +/Parent 139 0 R +/Prev 183 0 R +/Next 191 0 R +>> endobj +183 0 obj << +/Title 184 0 R +/A 181 0 R +/Parent 139 0 R +/Prev 179 0 R +/Next 187 0 R +>> endobj +179 0 obj << +/Title 180 0 R +/A 177 0 R +/Parent 139 0 R +/Prev 175 0 R +/Next 183 0 R +>> endobj +175 0 obj << +/Title 176 0 R +/A 173 0 R +/Parent 139 0 R +/Prev 171 0 R +/Next 179 0 R +>> endobj +171 0 obj << +/Title 172 0 R +/A 169 0 R +/Parent 139 0 R +/Prev 167 0 R +/Next 175 0 R +>> endobj +167 0 obj << +/Title 168 0 R +/A 165 0 R +/Parent 139 0 R +/Prev 163 0 R +/Next 171 0 R +>> endobj +163 0 obj << +/Title 164 0 R +/A 161 0 R +/Parent 139 0 R +/Prev 159 0 R +/Next 167 0 R +>> endobj +159 0 obj << +/Title 160 0 R +/A 157 0 R +/Parent 139 0 R +/Prev 155 0 R +/Next 163 0 R +>> endobj +155 0 obj << +/Title 156 0 R +/A 153 0 R +/Parent 139 0 R +/Prev 151 0 R +/Next 159 0 R +>> endobj +151 0 obj << +/Title 152 0 R +/A 149 0 R +/Parent 139 0 R +/Prev 147 0 R +/Next 155 0 R +>> endobj +147 0 obj << +/Title 148 0 R +/A 145 0 R +/Parent 139 0 R +/Prev 143 0 R +/Next 151 0 R +>> endobj +143 0 obj << +/Title 144 0 R +/A 141 0 R +/Parent 139 0 R +/Next 147 0 R +>> endobj +139 0 obj << +/Title 140 0 R +/A 137 0 R +/Parent 79 0 R +/Prev 83 0 R +/Next 219 0 R +/First 143 0 R +/Last 215 0 R +/Count -19 +>> endobj +135 0 obj << +/Title 136 0 R +/A 133 0 R +/Parent 83 0 R +/Prev 131 0 R +>> endobj +131 0 obj << +/Title 132 0 R +/A 129 0 R +/Parent 83 0 R +/Prev 127 0 R +/Next 135 0 R +>> endobj +127 0 obj << +/Title 128 0 R +/A 125 0 R +/Parent 83 0 R +/Prev 123 0 R +/Next 131 0 R +>> endobj +123 0 obj << +/Title 124 0 R +/A 121 0 R +/Parent 83 0 R +/Prev 119 0 R +/Next 127 0 R +>> endobj +119 0 obj << +/Title 120 0 R +/A 117 0 R +/Parent 83 0 R +/Prev 115 0 R +/Next 123 0 R +>> endobj +115 0 obj << +/Title 116 0 R +/A 113 0 R +/Parent 83 0 R +/Prev 111 0 R +/Next 119 0 R +>> endobj +111 0 obj << +/Title 112 0 R +/A 109 0 R +/Parent 83 0 R +/Prev 107 0 R +/Next 115 0 R +>> endobj +107 0 obj << +/Title 108 0 R +/A 105 0 R +/Parent 83 0 R +/Prev 103 0 R +/Next 111 0 R +>> endobj +103 0 obj << +/Title 104 0 R +/A 101 0 R +/Parent 83 0 R +/Prev 99 0 R +/Next 107 0 R +>> endobj +99 0 obj << +/Title 100 0 R +/A 97 0 R +/Parent 83 0 R +/Prev 95 0 R +/Next 103 0 R +>> endobj +95 0 obj << +/Title 96 0 R +/A 93 0 R +/Parent 83 0 R +/Prev 91 0 R +/Next 99 0 R +>> endobj +91 0 obj << +/Title 92 0 R +/A 89 0 R +/Parent 83 0 R +/Prev 87 0 R +/Next 95 0 R +>> endobj +87 0 obj << +/Title 88 0 R +/A 85 0 R +/Parent 83 0 R +/Next 91 0 R +>> endobj +83 0 obj << +/Title 84 0 R +/A 81 0 R +/Parent 79 0 R +/Next 139 0 R +/First 87 0 R +/Last 135 0 R +/Count -13 +>> endobj +79 0 obj << +/Title 80 0 R +/A 77 0 R +/Parent 2838 0 R +/Prev 27 0 R +/Next 351 0 R +/First 83 0 R +/Last 327 0 R +/Count -9 +>> endobj +75 0 obj << +/Title 76 0 R +/A 73 0 R +/Parent 27 0 R +/Prev 71 0 R +>> endobj +71 0 obj << +/Title 72 0 R +/A 69 0 R +/Parent 27 0 R +/Prev 59 0 R +/Next 75 0 R +>> endobj +67 0 obj << +/Title 68 0 R +/A 65 0 R +/Parent 59 0 R +/Prev 63 0 R +>> endobj +63 0 obj << +/Title 64 0 R +/A 61 0 R +/Parent 59 0 R +/Next 67 0 R +>> endobj +59 0 obj << +/Title 60 0 R +/A 57 0 R +/Parent 27 0 R +/Prev 39 0 R +/Next 71 0 R +/First 63 0 R +/Last 67 0 R +/Count -2 +>> endobj +55 0 obj << +/Title 56 0 R +/A 53 0 R +/Parent 39 0 R +/Prev 51 0 R +>> endobj +51 0 obj << +/Title 52 0 R +/A 49 0 R +/Parent 39 0 R +/Prev 47 0 R +/Next 55 0 R +>> endobj +47 0 obj << +/Title 48 0 R +/A 45 0 R +/Parent 39 0 R +/Prev 43 0 R +/Next 51 0 R +>> endobj +43 0 obj << +/Title 44 0 R +/A 41 0 R +/Parent 39 0 R +/Next 47 0 R +>> endobj +39 0 obj << +/Title 40 0 R +/A 37 0 R +/Parent 27 0 R +/Prev 35 0 R +/Next 59 0 R +/First 43 0 R +/Last 55 0 R +/Count -4 +>> endobj +35 0 obj << +/Title 36 0 R +/A 33 0 R +/Parent 27 0 R +/Prev 31 0 R +/Next 39 0 R +>> endobj +31 0 obj << +/Title 32 0 R +/A 29 0 R +/Parent 27 0 R +/Next 35 0 R +>> endobj +27 0 obj << +/Title 28 0 R +/A 25 0 R +/Parent 2838 0 R +/Prev 7 0 R +/Next 79 0 R +/First 31 0 R +/Last 75 0 R +/Count -6 +>> endobj +23 0 obj << +/Title 24 0 R +/A 21 0 R +/Parent 7 0 R +/Prev 19 0 R +>> endobj +19 0 obj << +/Title 20 0 R +/A 17 0 R +/Parent 7 0 R +/Prev 15 0 R +/Next 23 0 R +>> endobj +15 0 obj << +/Title 16 0 R +/A 13 0 R +/Parent 7 0 R +/Prev 11 0 R +/Next 19 0 R +>> endobj +11 0 obj << +/Title 12 0 R +/A 9 0 R +/Parent 7 0 R +/Next 15 0 R +>> endobj +7 0 obj << +/Title 8 0 R +/A 5 0 R +/Parent 2838 0 R +/Next 27 0 R +/First 11 0 R +/Last 23 0 R +/Count -4 +>> endobj +2839 0 obj << +/Names [(Doc-Start) 361 0 R (Item.1) 517 0 R (Item.10) 536 0 R (Item.11) 537 0 R (Item.12) 538 0 R (Item.13) 539 0 R (Item.2) 521 0 R (Item.3) 522 0 R (Item.4) 523 0 R (Item.5) 524 0 R (Item.6) 525 0 R (Item.7) 533 0 R (Item.8) 534 0 R (Item.9) 535 0 R (addthemenotification) 730 0 R (aluminumtheme) 609 0 R (appendix.A) 350 0 R (changes) 1901 0 R (chapter*.1) 381 0 R (chapter.1) 6 0 R (chapter.2) 26 0 R (chapter.3) 78 0 R (contacts) 500 0 R (converter) 624 0 R (convrules) 625 0 R (convusing) 629 0 R (currenttheme) 735 0 R (defaulttheme) 565 0 R (faq) 645 0 R (features) 488 0 R (geteffectivecolor) 731 0 R (gettingstarted) 540 0 R (installation) 513 0 R (introduction) 487 0 R (knownissues) 635 0 R (license) 490 0 R (officexptheme) 573 0 R (page.1) 360 0 R (page.10) 623 0 R (page.11) 634 0 R (page.12) 644 0 R (page.13) 653 0 R (page.14) 659 0 R (page.15) 695 0 R (page.16) 739 0 R (page.17) 748 0 R (page.18) 766 0 R (page.19) 775 0 R (page.2) 377 0 R (page.20) 793 0 R (page.21) 817 0 R (page.22) 843 0 R (page.23) 856 0 R (page.24) 875 0 R (page.25) 891 0 R (page.26) 903 0 R (page.27) 936 0 R (page.28) 974 0 R (page.29) 996 0 R (page.3) 420 0 R (page.30) 1008 0 R (page.31) 1027 0 R (page.32) 1043 0 R (page.33) 1057 0 R (page.34) 1072 0 R (page.35) 1087 0 R (page.36) 1103 0 R (page.37) 1117 0 R (page.38) 1137 0 R (page.39) 1152 0 R (page.4) 461 0 R (page.40) 1171 0 R (page.41) 1189 0 R (page.42) 1216 0 R (page.43) 1234 0 R (page.44) 1244 0 R (page.45) 1257 0 R (page.46) 1275 0 R (page.47) 1305 0 R (page.48) 1338 0 R (page.49) 1352 0 R (page.5) 532 0 R (page.50) 1361 0 R (page.51) 1371 0 R (page.52) 1388 0 R (page.53) 1414 0 R (page.54) 1432 0 R (page.55) 1449 0 R (page.56) 1479 0 R (page.57) 1489 0 R (page.58) 1509 0 R (page.59) 1529 0 R (page.6) 551 0 R (page.60) 1557 0 R (page.61) 1573 0 R (page.62) 1587 0 R (page.63) 1601 0 R (page.64) 1632 0 R (page.65) 1658 0 R (page.66) 1672 0 R (page.67) 1689 0 R (page.68) 1700 0 R (page.69) 1719 0 R (page.7) 582 0 R (page.70) 1735 0 R (page.71) 1747 0 R (page.72) 1759 0 R (page.73) 1776 0 R (page.74) 1791 0 R (page.75) 1826 0 R (page.76) 1845 0 R (page.77) 1863 0 R (page.78) 1876 0 R (page.79) 1891 0 R (page.8) 598 0 R (page.80) 1913 0 R (page.81) 1917 0 R (page.82) 1922 0 R (page.83) 1926 0 R (page.84) 1930 0 R (page.85) 1934 0 R (page.86) 1938 0 R (page.87) 1942 0 R (page.88) 2058 0 R (page.89) 2173 0 R (page.9) 608 0 R (page.90) 2292 0 R (page.91) 2403 0 R (page.92) 2521 0 R (page.93) 2638 0 R (page.94) 2759 0 R (reference) 655 0 R (registration) 496 0 R (removethemenotification) 732 0 R (section*.13) 58 0 R (section*.16) 70 0 R (section*.17) 74 0 R (section*.18) 82 0 R (section*.2) 10 0 R (section*.3) 14 0 R (section*.4) 18 0 R (section*.40) 138 0 R (section*.5) 22 0 R (section*.6) 30 0 R (section*.61) 218 0 R (section*.7) 34 0 R (section*.72) 262 0 R (section*.76) 278 0 R (section*.79) 290 0 R (section*.8) 38 0 R (section*.84) 310 0 R (section*.86) 318 0 R (section*.89) 326 0 R (stripestheme) 574 0 R (subsection*.10) 46 0 R (subsection*.11) 50 0 R (subsection*.12) 54 0 R (subsection*.14) 62 0 R (subsection*.15) 66 0 R (subsection*.19) 86 0 R (subsection*.20) 90 0 R (subsection*.21) 94 0 R (subsection*.22) 98 0 R (subsection*.23) 102 0 R (subsection*.24) 106 0 R (subsection*.25) 110 0 R (subsection*.26) 114 0 R (subsection*.27) 118 0 R (subsection*.28) 122 0 R (subsection*.29) 126 0 R (subsection*.35) 130 0 R (subsection*.38) 134 0 R (subsection*.41) 142 0 R (subsection*.42) 146 0 R (subsection*.43) 150 0 R (subsection*.44) 154 0 R (subsection*.45) 158 0 R (subsection*.46) 162 0 R (subsection*.47) 166 0 R (subsection*.48) 170 0 R (subsection*.49) 174 0 R (subsection*.50) 178 0 R (subsection*.51) 182 0 R (subsection*.52) 186 0 R (subsection*.53) 190 0 R (subsection*.54) 194 0 R (subsection*.55) 198 0 R (subsection*.56) 202 0 R (subsection*.57) 206 0 R (subsection*.58) 210 0 R (subsection*.59) 214 0 R (subsection*.62) 222 0 R (subsection*.63) 226 0 R (subsection*.64) 230 0 R (subsection*.65) 234 0 R (subsection*.66) 238 0 R (subsection*.67) 242 0 R (subsection*.68) 246 0 R (subsection*.69) 250 0 R (subsection*.70) 254 0 R (subsection*.71) 258 0 R (subsection*.73) 266 0 R (subsection*.74) 270 0 R (subsection*.75) 274 0 R (subsection*.77) 282 0 R (subsection*.78) 286 0 R (subsection*.80) 294 0 R (subsection*.81) 298 0 R (subsection*.82) 302 0 R (subsection*.83) 306 0 R (subsection*.85) 314 0 R (subsection*.87) 322 0 R (subsection*.9) 42 0 R (subsection*.90) 330 0 R (subsection*.91) 334 0 R (subsection*.92) 338 0 R (subsection*.93) 342 0 R (subsection*.94) 346 0 R (subsubsection*.30) 893 0 R (subsubsection*.31) 895 0 R (subsubsection*.32) 896 0 R (subsubsection*.33) 898 0 R (subsubsection*.34) 899 0 R (subsubsection*.36) 904 0 R (subsubsection*.37) 905 0 R (subsubsection*.39) 906 0 R (subsubsection*.60) 1278 0 R (subsubsection*.88) 1785 0 R (tbx) 669 0 R (tbxcurrenttheme) 575 0 R (tbxdkpanels) 680 0 R (tbxextitems) 681 0 R (tbxlists) 682 0 R (tbxmdi) 683 0 R (tbxsettheme) 576 0 R (tbxstatusbars) 684 0 R (tbxswitcher) 685 0 R (tbxthemes) 686 0 R (tbxtoolpals) 687 0 R (tfontsettings) 688 0 R (tfontsettings.bold) 710 0 R (tfontsettings.color) 721 0 R (tfontsettings.italic) 722 0 R (tfontsettings.name) 740 0 R (tfontsettings.size) 741 0 R (tfontsettings.strikeout) 742 0 R (tfontsettings.underline) 743 0 R (themes) 557 0 R (ttbxalignmentpanel) 919 0 R (ttbxalignmntpnl.margins) 946 0 R (ttbxbutton) 920 0 R (ttbxcheckbox) 921 0 R (ttbxcoloritem) 1290 0 R (ttbxcoloritem.color) 1308 0 R (ttbxcolorpalett.color) 1802 0 R (ttbxcolorpalett.colorset) 1803 0 R (ttbxcolorpalett.colortostring) 1828 0 R (ttbxcolorpalett.create) 1829 0 R (ttbxcolorpalett.findcell) 1831 0 R (ttbxcolorpalette) 1797 0 R (ttbxcolorset) 1819 0 R (ttbxcomboboxitem) 1291 0 R (ttbxcomboboxitm.autocomplete) 1339 0 R (ttbxcomboboxitm.create) 1353 0 R (ttbxcomboboxitm.itemindex) 1340 0 R (ttbxcomboboxitm.maxlistwidth) 1341 0 R (ttbxcomboboxitm.maxvisibleitems) 1343 0 R (ttbxcomboboxitm.minlistwidth) 1344 0 R (ttbxcomboboxitm.onadjustimagndx) 1334 0 R (ttbxcomboboxitm.onclearitem) 1355 0 R (ttbxcomboboxitm.ondrawitem) 1356 0 R (ttbxcomboboxitm.onitemclick) 1357 0 R (ttbxcomboboxitm.onmeasureheight) 1362 0 R (ttbxcomboboxitm.onmeasurewidth) 1363 0 R (ttbxcomboboxitm.showlistimages) 1333 0 R (ttbxcomboboxitm.strings) 1347 0 R (ttbxcontrlmrgns.bottom) 999 0 R (ttbxcontrlmrgns.left) 1000 0 R (ttbxcontrlmrgns.right) 1001 0 R (ttbxcontrlmrgns.top) 1002 0 R (ttbxcontrolmargins) 922 0 R (ttbxcstmpgscrll.autorange) 1091 0 R (ttbxcstmpgscrll.autoscroll) 1093 0 R (ttbxcstmpgscrll.buttonsize) 1094 0 R (ttbxcstmpgscrll.create) 1105 0 R (ttbxcstmpgscrll.disableautorang) 1106 0 R (ttbxcstmpgscrll.enableautorange) 1108 0 R (ttbxcstmpgscrll.margin) 1096 0 R (ttbxcstmpgscrll.orientation) 1097 0 R (ttbxcstmpgscrll.position) 1098 0 R (ttbxcstmpgscrll.range) 1099 0 R (ttbxcstmpgscrll.scrolltocenter) 1110 0 R (ttbxcstmspndttm.asinteger) 1376 0 R (ttbxcstmspndttm.create) 1423 0 R (ttbxcstmspndttm.decimal) 1379 0 R (ttbxcstmspndttm.increment) 1380 0 R (ttbxcstmspndttm.maxvalue) 1381 0 R (ttbxcstmspndttm.minvalue) 1391 0 R (ttbxcstmspndttm.onconvert) 1433 0 R (ttbxcstmspndttm.onstep) 1439 0 R (ttbxcstmspndttm.ontexttovalue) 1440 0 R (ttbxcstmspndttm.onvaluechange) 1442 0 R (ttbxcstmspndttm.onvaluetotext) 1443 0 R (ttbxcstmspndttm.postfix) 1394 0 R (ttbxcstmspndttm.prefix) 1398 0 R (ttbxcstmspndttm.snap) 1401 0 R (ttbxcstmspndttm.spaceafterprefx) 1409 0 R (ttbxcstmspndttm.spacebeforpstfx) 1410 0 R (ttbxcstmspndttm.value) 1383 0 R (ttbxcstmspndttm.valuetype) 1384 0 R (ttbxcustmchckbx.allowgrayed) 1049 0 R (ttbxcustmchckbx.checked) 1050 0 R (ttbxcustmchckbx.onchange) 1058 0 R (ttbxcustmchckbx.state) 1053 0 R (ttbxcustmrdbttn.checked) 1118 0 R (ttbxcustmrdbttn.groupindex) 1120 0 R (ttbxcustmrdbttn.onchange) 1122 0 R (ttbxcustmsttsbr.fixalign) 1676 0 R (ttbxcustmsttsbr.getpanelat) 1690 0 R (ttbxcustmsttsbr.getpanelrect) 1691 0 R (ttbxcustmsttsbr.images) 1677 0 R (ttbxcustmsttsbr.onadjstcntntrct) 1692 0 R (ttbxcustmsttsbr.onadjustfont) 1693 0 R (ttbxcustmsttsbr.onpanelclick) 1694 0 R (ttbxcustmsttsbr.onpaneldblclick) 1695 0 R (ttbxcustmsttsbr.panels) 1679 0 R (ttbxcustmsttsbr.simplepanel) 1682 0 R (ttbxcustmsttsbr.simpletext) 1683 0 R (ttbxcustmsttsbr.sizegrip) 1684 0 R (ttbxcustmsttsbr.usesystemfont) 1685 0 R (ttbxcustmtlpltt.colcount) 1868 0 R (ttbxcustmtlpltt.create) 1878 0 R (ttbxcustmtlpltt.oncalcimagesize) 1881 0 R (ttbxcustmtlpltt.oncellclick) 1882 0 R (ttbxcustmtlpltt.onchange) 1885 0 R (ttbxcustmtlpltt.ondrawcellimage) 1872 0 R (ttbxcustmtlpltt.ongetcellhint) 1894 0 R (ttbxcustmtlpltt.ongetcellvisibl) 1895 0 R (ttbxcustmtlpltt.paletteoptions) 1869 0 R (ttbxcustmtlpltt.rowcount) 1871 0 R (ttbxcustmtlpltt.selectedcell) 1877 0 R (ttbxcustombuttn.alignment) 1011 0 R (ttbxcustombuttn.allowallunchckd) 1012 0 R (ttbxcustombuttn.bordersize) 1013 0 R (ttbxcustombuttn.buttonstyle) 1014 0 R (ttbxcustombuttn.checked) 1015 0 R (ttbxcustombuttn.dropdowncombo) 1017 0 R (ttbxcustombuttn.dropdownmenu) 1020 0 R (ttbxcustombuttn.glyphspacing) 1022 0 R (ttbxcustombuttn.groupindex) 1023 0 R (ttbxcustombuttn.imageindex) 1028 0 R (ttbxcustombuttn.images) 1029 0 R (ttbxcustombuttn.layout) 1031 0 R (ttbxcustombuttn.ondropdown) 1044 0 R (ttbxcustombuttn.repeatdelay) 1032 0 R (ttbxcustombuttn.repeating) 1034 0 R (ttbxcustombuttn.repeatinterval) 1038 0 R (ttbxcustombutton) 923 0 R (ttbxcustomcheckbox) 924 0 R (ttbxcustomclrst.colcount) 1853 0 R (ttbxcustomclrst.getcolor) 1855 0 R (ttbxcustomclrst.getname) 1858 0 R (ttbxcustomclrst.ongetcolorinfo) 1859 0 R (ttbxcustomclrst.rowcount) 1854 0 R (ttbxcustomcolorset) 1820 0 R (ttbxcustomdropdownitem) 1292 0 R (ttbxcustomitem) 689 0 R (ttbxcustomitem.alwaysselctfrst) 749 0 R (ttbxcustomitem.fontsettings) 750 0 R (ttbxcustomitem.layout) 753 0 R (ttbxcustomitem.minheight) 754 0 R (ttbxcustomitem.minwidth) 755 0 R (ttbxcustomitem.onadjustfont) 760 0 R (ttbxcustomitem.ondrawimage) 769 0 R (ttbxcustomitem.stretch) 756 0 R (ttbxcustomitem.toolboxpopup) 757 0 R (ttbxcustomlabel) 925 0 R (ttbxcustomlabel.create) 1074 0 R (ttbxcustomlabel.focuscontrol) 1064 0 R (ttbxcustomlabel.underline) 1065 0 R (ttbxcustomlabel.underlinecolor) 1067 0 R (ttbxcustomlink) 926 0 R (ttbxcustomlink.imageindex) 1080 0 R (ttbxcustomlink.images) 1082 0 R (ttbxcustomlist) 1565 0 R (ttbxcustomlist.create) 1582 0 R (ttbxcustomlist.itemindex) 1576 0 R (ttbxcustomlist.makevisible) 1583 0 R (ttbxcustomlist.maxvisibleitems) 1577 0 R (ttbxcustomlist.maxwidth) 1578 0 R (ttbxcustomlist.minwidth) 1580 0 R (ttbxcustomlist.onadjustimagndx) 1569 0 R (ttbxcustomlist.onchange) 1589 0 R (ttbxcustomlist.onclearitem) 1590 0 R (ttbxcustomlist.ondrawitem) 1592 0 R (ttbxcustomlist.onmeasureheight) 1594 0 R (ttbxcustomlist.onmeasurewidth) 1595 0 R (ttbxcustomlist.showimages) 1348 0 R (ttbxcustompagescroller) 927 0 R (ttbxcustomradiobutton) 928 0 R (ttbxcustomspinedititem) 1293 0 R (ttbxcustomstatusbar) 1665 0 R (ttbxcustomtoolpalette) 1821 0 R (ttbxdock) 690 0 R (ttbxdock.useparntbckgrnd) 777 0 R (ttbxdockablepanel) 929 0 R (ttbxdockablepnl.bordersize) 1124 0 R (ttbxdockablepnl.captionrotation) 1125 0 R (ttbxdockablepnl.create) 1175 0 R (ttbxdockablepnl.dockedheight) 1138 0 R (ttbxdockablepnl.dockedwidth) 1139 0 R (ttbxdockablepnl.effectivecolor) 1140 0 R (ttbxdockablepnl.floatingheight) 1141 0 R (ttbxdockablepnl.floatingwidth) 1142 0 R (ttbxdockablepnl.maxclientheight) 1143 0 R (ttbxdockablepnl.maxclientwidth) 1147 0 R (ttbxdockablepnl.minclientheight) 1148 0 R (ttbxdockablepnl.minclientwidth) 1158 0 R (ttbxdockablepnl.ondockedresizng) 1190 0 R (ttbxdockablepnl.showcptnwhndckd) 1161 0 R (ttbxdockablepnl.smoothdockedrsz) 1162 0 R (ttbxdockablepnl.snapdistance) 1163 0 R (ttbxdockablepnl.splitheight) 1164 0 R (ttbxdockablepnl.splitwidth) 1166 0 R (ttbxdockablepnl.supporteddocks) 1173 0 R (ttbxdockablepnl.updatechildclrs) 1182 0 R (ttbxdropdownitem) 1294 0 R (ttbxedititem) 1295 0 R (ttbxedititem.alignment) 1428 0 R (ttbxedititem.fontsettings) 1480 0 R (ttbxedititem.onchange) 1490 0 R (ttbxedititem.passwordchar) 1482 0 R (ttbxedititem.readonly) 1483 0 R (ttbxedititem.showimage) 1332 0 R (ttbxedititem.startediting) 1484 0 R (ttbxitem) 691 0 R (ttbxitemlayout) 1784 0 R (ttbxitemtransparency) 733 0 R (ttbxlabel) 930 0 R (ttbxlabelitem) 1296 0 R (ttbxlabelitem.caption) 1491 0 R (ttbxlabelitem.create) 1510 0 R (ttbxlabelitem.fontsettings) 1492 0 R (ttbxlabelitem.margin) 1494 0 R (ttbxlabelitem.onadjustfont) 1513 0 R (ttbxlabelitem.orientation) 1495 0 R (ttbxlabelitem.updatecaption) 1511 0 R (ttbxlink) 963 0 R (ttbxmdihandler) 1636 0 R (ttbxmdiwindowitem) 1638 0 R (ttbxmrulist) 1297 0 R (ttbxmrulist.keyshift) 1515 0 R (ttbxmrulistitem) 1298 0 R (ttbxmrulistitem.create) 1535 0 R (ttbxmrulistitem.mrulist) 1533 0 R (ttbxmultidock) 964 0 R (ttbxmultidock.resizevisblpnls) 1222 0 R (ttbxpagescroller) 965 0 R (ttbxpanelobject) 966 0 R (ttbxpanelobject.makevisible) 1247 0 R (ttbxpanelobject.onmouseenter) 1249 0 R (ttbxpanelobject.onmouseleave) 1251 0 R (ttbxpanelobject.smartfocus) 1245 0 R (ttbxpanelobject.spaceasclick) 1246 0 R (ttbxpopupmenu) 724 0 R (ttbxpopupmenu.toolboxpopup) 794 0 R (ttbxradiobutton) 967 0 R (ttbxresizingstage) 969 0 R (ttbxseparatoritem) 725 0 R (ttbxseparatortm.create) 818 0 R (ttbxseparatortm.size) 795 0 R (ttbxspinedititem) 1299 0 R (ttbxstatusbar) 1666 0 R (ttbxstatuspanel) 1667 0 R (ttbxstatuspanel.alignment) 1706 0 R (ttbxstatuspanel.caption) 1707 0 R (ttbxstatuspanel.control) 1720 0 R (ttbxstatuspanel.enabled) 1721 0 R (ttbxstatuspanel.fontsettings) 1722 0 R (ttbxstatuspanel.framed) 1724 0 R (ttbxstatuspanel.hint) 1725 0 R (ttbxstatuspanel.imageindex) 1726 0 R (ttbxstatuspanel.maxsize) 1728 0 R (ttbxstatuspanel.size) 1730 0 R (ttbxstatuspanel.stretchpriority) 1737 0 R (ttbxstatuspanel.tag) 1739 0 R (ttbxstatuspanel.texttruncation) 1740 0 R (ttbxstatuspanel.viewpriority) 1741 0 R (ttbxstatuspanel.visible) 1743 0 R (ttbxstatuspanels) 1668 0 R (ttbxstatuspanls.findpanel) 1754 0 R (ttbxstatuspanls.items) 1751 0 R (ttbxstatuspanls.statusbar) 1752 0 R (ttbxstringlist) 761 0 R (ttbxstringlist.strings) 1606 0 R (ttbxsubmenuitem) 726 0 R (ttbxsubmenuitem.create) 822 0 R (ttbxsubmenuitem.dropdowncombo) 821 0 R (ttbxswitcher) 571 0 R (ttbxswitcher.enablexpstyles) 1763 0 R (ttbxswitcher.flatmenustyle) 1764 0 R (ttbxswitcher.onthemechange) 1782 0 R (ttbxswitcher.theme) 572 0 R (ttbxswitcher.themecount) 1779 0 R (ttbxswitcher.themes) 1780 0 R (ttbxtextobject) 968 0 R (ttbxtextobject.alignment) 1262 0 R (ttbxtextobject.margins) 992 0 R (ttbxtextobject.showaccelchar) 1276 0 R (ttbxtextobject.wrapping) 1277 0 R (ttbxtoolbar) 727 0 R (ttbxtoolbar.create) 849 0 R (ttbxtoolbar.effectivecolor) 844 0 R (ttbxtoolbar.embedded) 850 0 R (ttbxtoolbar.itemtransparncy) 846 0 R (ttbxtoolbar.snapdistance) 848 0 R (ttbxtoolbar.updatechildclrs) 851 0 R (ttbxtoolpalette) 762 0 R (ttbxtoolwindow) 728 0 R (ttbxtoolwindow.create) 876 0 R (ttbxtoolwindow.effectivecolor) 859 0 R (ttbxtoolwindow.snapdistance) 861 0 R (ttbxtoolwindow.updatechildclrs) 870 0 R (ttbxundolist) 1568 0 R (ttbxvisibilitytoggleitem) 729 0 R (ttbxvsbltytgglt.control) 892 0 R (ttristate) 734 0 R (usage) 508 0 R] +/Limits [(Doc-Start) (usage)] +>> endobj +2840 0 obj << +/Kids [2839 0 R] +>> endobj +2841 0 obj << +/Dests 2840 0 R +>> endobj +2842 0 obj << +/Type /Catalog +/Pages 2837 0 R +/Outlines 2838 0 R +/Names 2841 0 R +/PageMode /UseOutlines +/OpenAction 356 0 R +>> endobj +2843 0 obj << +/Author(Alex A. Denisov)/Title(TBX Package)/Subject()/Creator(LaTeX with hyperref package)/Producer(pdfeTeX-1.20a)/Keywords() +/CreationDate (D:20040529174004-04'00') +>> endobj +xref +0 2844 +0000000001 65535 f +0000000002 00000 f +0000000003 00000 f +0000000004 00000 f +0000000362 00000 f +0000000009 00000 n +0000032462 00000 n +0000940567 00000 n +0000000054 00000 n +0000000084 00000 n +0000032584 00000 n +0000940495 00000 n +0000000130 00000 n +0000000157 00000 n +0000036972 00000 n +0000940409 00000 n +0000000204 00000 n +0000000230 00000 n +0000037095 00000 n +0000940323 00000 n +0000000277 00000 n +0000000322 00000 n +0000039205 00000 n +0000940250 00000 n +0000000369 00000 n +0000000396 00000 n +0000042238 00000 n +0000940125 00000 n +0000000442 00000 n +0000000466 00000 n +0000042361 00000 n +0000940051 00000 n +0000000513 00000 n +0000000554 00000 n +0000052820 00000 n +0000939964 00000 n +0000000601 00000 n +0000000635 00000 n +0000066629 00000 n +0000939840 00000 n +0000000682 00000 n +0000000711 00000 n +0000117882 00000 n +0000939766 00000 n +0000000761 00000 n +0000000793 00000 n +0000146315 00000 n +0000939679 00000 n +0000000844 00000 n +0000000878 00000 n +0000225780 00000 n +0000939592 00000 n +0000000929 00000 n +0000000961 00000 n +0000225903 00000 n +0000939518 00000 n +0000001012 00000 n +0000001045 00000 n +0000229187 00000 n +0000939394 00000 n +0000001093 00000 n +0000001157 00000 n +0000229310 00000 n +0000939320 00000 n +0000001208 00000 n +0000001243 00000 n +0000252406 00000 n +0000939246 00000 n +0000001294 00000 n +0000001332 00000 n +0000256417 00000 n +0000939159 00000 n +0000001380 00000 n +0000001411 00000 n +0000256540 00000 n +0000939085 00000 n +0000001459 00000 n +0000001504 00000 n +0000262479 00000 n +0000938957 00000 n +0000001550 00000 n +0000001578 00000 n +0000262602 00000 n +0000938843 00000 n +0000001626 00000 n +0000001657 00000 n +0000267783 00000 n +0000938769 00000 n +0000001708 00000 n +0000001746 00000 n +0000270782 00000 n +0000938682 00000 n +0000001797 00000 n +0000001836 00000 n +0000277690 00000 n +0000938595 00000 n +0000001887 00000 n +0000001920 00000 n +0000283503 00000 n +0000938506 00000 n +0000001971 00000 n +0000002005 00000 n +0000291823 00000 n +0000938415 00000 n +0000002057 00000 n +0000002096 00000 n +0000292009 00000 n +0000938323 00000 n +0000002148 00000 n +0000002191 00000 n +0000300553 00000 n +0000938231 00000 n +0000002243 00000 n +0000002284 00000 n +0000300801 00000 n +0000938139 00000 n +0000002336 00000 n +0000002373 00000 n +0000310610 00000 n +0000938047 00000 n +0000002425 00000 n +0000002465 00000 n +0000317015 00000 n +0000937955 00000 n +0000002517 00000 n +0000002567 00000 n +0000319807 00000 n +0000937863 00000 n +0000002619 00000 n +0000002647 00000 n +0000324975 00000 n +0000937771 00000 n +0000002699 00000 n +0000002724 00000 n +0000325285 00000 n +0000937693 00000 n +0000002776 00000 n +0000002805 00000 n +0000325532 00000 n +0000937562 00000 n +0000002854 00000 n +0000002894 00000 n +0000340738 00000 n +0000937483 00000 n +0000002946 00000 n +0000002990 00000 n +0000340924 00000 n +0000937390 00000 n +0000003042 00000 n +0000003078 00000 n +0000347858 00000 n +0000937297 00000 n +0000003130 00000 n +0000003168 00000 n +0000350432 00000 n +0000937204 00000 n +0000003220 00000 n +0000003264 00000 n +0000350807 00000 n +0000937111 00000 n +0000003316 00000 n +0000003358 00000 n +0000361741 00000 n +0000937018 00000 n +0000003410 00000 n +0000003454 00000 n +0000365088 00000 n +0000936925 00000 n +0000003506 00000 n +0000003547 00000 n +0000368949 00000 n +0000936832 00000 n +0000003599 00000 n +0000003639 00000 n +0000372573 00000 n +0000936739 00000 n +0000003691 00000 n +0000003739 00000 n +0000376531 00000 n +0000936646 00000 n +0000003791 00000 n +0000003838 00000 n +0000382772 00000 n +0000936553 00000 n +0000003890 00000 n +0000003933 00000 n +0000405470 00000 n +0000936460 00000 n +0000003985 00000 n +0000004020 00000 n +0000405596 00000 n +0000936367 00000 n +0000004072 00000 n +0000004106 00000 n +0000411600 00000 n +0000936274 00000 n +0000004158 00000 n +0000004197 00000 n +0000411790 00000 n +0000936181 00000 n +0000004249 00000 n +0000004291 00000 n +0000416006 00000 n +0000936088 00000 n +0000004343 00000 n +0000004384 00000 n +0000425035 00000 n +0000935995 00000 n +0000004436 00000 n +0000004477 00000 n +0000425160 00000 n +0000935902 00000 n +0000004529 00000 n +0000004569 00000 n +0000430332 00000 n +0000935823 00000 n +0000004621 00000 n +0000004646 00000 n +0000430585 00000 n +0000935691 00000 n +0000004695 00000 n +0000004735 00000 n +0000441028 00000 n +0000935612 00000 n +0000004787 00000 n +0000004826 00000 n +0000441219 00000 n +0000935519 00000 n +0000004878 00000 n +0000004920 00000 n +0000450797 00000 n +0000935426 00000 n +0000004972 00000 n +0000005020 00000 n +0000453955 00000 n +0000935333 00000 n +0000005072 00000 n +0000005120 00000 n +0000479643 00000 n +0000935240 00000 n +0000005172 00000 n +0000005214 00000 n +0000479770 00000 n +0000935147 00000 n +0000005266 00000 n +0000005304 00000 n +0000488451 00000 n +0000935054 00000 n +0000005356 00000 n +0000005395 00000 n +0000495022 00000 n +0000934961 00000 n +0000005447 00000 n +0000005484 00000 n +0000504760 00000 n +0000934868 00000 n +0000005536 00000 n +0000005577 00000 n +0000505014 00000 n +0000934789 00000 n +0000005629 00000 n +0000005671 00000 n +0000510272 00000 n +0000934658 00000 n +0000005720 00000 n +0000005757 00000 n +0000510398 00000 n +0000934579 00000 n +0000005809 00000 n +0000005849 00000 n +0000527335 00000 n +0000934486 00000 n +0000005901 00000 n +0000005941 00000 n +0000527526 00000 n +0000934407 00000 n +0000005993 00000 n +0000006031 00000 n +0000536753 00000 n +0000934276 00000 n +0000006080 00000 n +0000006115 00000 n +0000536880 00000 n +0000934197 00000 n +0000006167 00000 n +0000006207 00000 n +0000537006 00000 n +0000934118 00000 n +0000006259 00000 n +0000006302 00000 n +0000540173 00000 n +0000933987 00000 n +0000006351 00000 n +0000006393 00000 n +0000540299 00000 n +0000933908 00000 n +0000006445 00000 n +0000006490 00000 n +0000552639 00000 n +0000933815 00000 n +0000006542 00000 n +0000006581 00000 n +0000552766 00000 n +0000933722 00000 n +0000006633 00000 n +0000006674 00000 n +0000562524 00000 n +0000933643 00000 n +0000006726 00000 n +0000006768 00000 n +0000569538 00000 n +0000933512 00000 n +0000006817 00000 n +0000006857 00000 n +0000569664 00000 n +0000933447 00000 n +0000006909 00000 n +0000006947 00000 n +0000573313 00000 n +0000933316 00000 n +0000006996 00000 n +0000007034 00000 n +0000573376 00000 n +0000933251 00000 n +0000007086 00000 n +0000007111 00000 n +0000584987 00000 n +0000933134 00000 n +0000007160 00000 n +0000007200 00000 n +0000585114 00000 n +0000933055 00000 n +0000007252 00000 n +0000007294 00000 n +0000592284 00000 n +0000932962 00000 n +0000007346 00000 n +0000007384 00000 n +0000596393 00000 n +0000932869 00000 n +0000007436 00000 n +0000007480 00000 n +0000600080 00000 n +0000932776 00000 n +0000007532 00000 n +0000007579 00000 n +0000612062 00000 n +0000932697 00000 n +0000007631 00000 n +0000007672 00000 n +0000614333 00000 n +0000932604 00000 n +0000007720 00000 n +0000007747 00000 n +0000932524 00000 n +0000007795 00000 n +0000007820 00000 n +0000008454 00000 n +0000008689 00000 n +0000007872 00000 n +0000008566 00000 n +0000008627 00000 n +0000000555 00000 f +0000929857 00000 n +0000929034 00000 n +0000923271 00000 n +0000928871 00000 n +0000921746 00000 n +0000903681 00000 n +0000921583 00000 n +0000903026 00000 n +0000900938 00000 n +0000902862 00000 n +0000929953 00000 n +0000016134 00000 n +0000011193 00000 n +0000008799 00000 n +0000016011 00000 n +0000900255 00000 n +0000888858 00000 n +0000900079 00000 n +0000016072 00000 n +0000011549 00000 n +0000887640 00000 n +0000873547 00000 n +0000887476 00000 n +0000011701 00000 n +0000011852 00000 n +0000012004 00000 n +0000012157 00000 n +0000012306 00000 n +0000012457 00000 n +0000012610 00000 n +0000012763 00000 n +0000012916 00000 n +0000013071 00000 n +0000013226 00000 n +0000013382 00000 n +0000013537 00000 n +0000013690 00000 n +0000013846 00000 n +0000014002 00000 n +0000014152 00000 n +0000014306 00000 n +0000014458 00000 n +0000014611 00000 n +0000014767 00000 n +0000014923 00000 n +0000015079 00000 n +0000015235 00000 n +0000015391 00000 n +0000015546 00000 n +0000015702 00000 n +0000015858 00000 n +0000872730 00000 n +0000859934 00000 n +0000872554 00000 n +0000025084 00000 n +0000018850 00000 n +0000016244 00000 n +0000025023 00000 n +0000019270 00000 n +0000019426 00000 n +0000019582 00000 n +0000019738 00000 n +0000019894 00000 n +0000020047 00000 n +0000020203 00000 n +0000020359 00000 n +0000020514 00000 n +0000020670 00000 n +0000020826 00000 n +0000020981 00000 n +0000021137 00000 n +0000021293 00000 n +0000021449 00000 n +0000021605 00000 n +0000021761 00000 n +0000021917 00000 n +0000022073 00000 n +0000022228 00000 n +0000022384 00000 n +0000022540 00000 n +0000022696 00000 n +0000022852 00000 n +0000023008 00000 n +0000023161 00000 n +0000023317 00000 n +0000023473 00000 n +0000023628 00000 n +0000023784 00000 n +0000023940 00000 n +0000024095 00000 n +0000024251 00000 n +0000024407 00000 n +0000024561 00000 n +0000024717 00000 n +0000024869 00000 n +0000030616 00000 n +0000026845 00000 n +0000025168 00000 n +0000030555 00000 n +0000027145 00000 n +0000027301 00000 n +0000027457 00000 n +0000027611 00000 n +0000027767 00000 n +0000027922 00000 n +0000028076 00000 n +0000028232 00000 n +0000028387 00000 n +0000028541 00000 n +0000028696 00000 n +0000028850 00000 n +0000029006 00000 n +0000029159 00000 n +0000029315 00000 n +0000029469 00000 n +0000029625 00000 n +0000029781 00000 n +0000029937 00000 n +0000030093 00000 n +0000030249 00000 n +0000030402 00000 n +0000032707 00000 n +0000032086 00000 n +0000030713 00000 n +0000032400 00000 n +0000032522 00000 n +0000032218 00000 n +0000032645 00000 n +0000037217 00000 n +0000035979 00000 n +0000032830 00000 n +0000036143 00000 n +0000036310 00000 n +0000037033 00000 n +0000036472 00000 n +0000036622 00000 n +0000036797 00000 n +0000037155 00000 n +0000039327 00000 n +0000038340 00000 n +0000037327 00000 n +0000038496 00000 n +0000038658 00000 n +0000038866 00000 n +0000039033 00000 n +0000039266 00000 n +0000930071 00000 n +0000042793 00000 n +0000041933 00000 n +0000039424 00000 n +0000042299 00000 n +0000858816 00000 n +0000847933 00000 n +0000858652 00000 n +0000042422 00000 n +0000847613 00000 n +0000845731 00000 n +0000847450 00000 n +0000042484 00000 n +0000042546 00000 n +0000042608 00000 n +0000042670 00000 n +0000042732 00000 n +0000042065 00000 n +0000046297 00000 n +0000056038 00000 n +0000052881 00000 n +0000046185 00000 n +0000042955 00000 n +0000052264 00000 n +0000052325 00000 n +0000052387 00000 n +0000052448 00000 n +0000052510 00000 n +0000052572 00000 n +0000052634 00000 n +0000052696 00000 n +0000052758 00000 n +0000046859 00000 n +0000047061 00000 n +0000049272 00000 n +0000049401 00000 n +0000049438 00000 n +0000049485 00000 n +0000052161 00000 n +0000066752 00000 n +0000055834 00000 n +0000053045 00000 n +0000066506 00000 n +0000064934 00000 n +0000065088 00000 n +0000065242 00000 n +0000001437 00000 f +0000845640 00000 n +0000066567 00000 n +0000065403 00000 n +0000065557 00000 n +0000065712 00000 n +0000065867 00000 n +0000066039 00000 n +0000066194 00000 n +0000066352 00000 n +0000066690 00000 n +0000056570 00000 n +0000056769 00000 n +0000062092 00000 n +0000062221 00000 n +0000062258 00000 n +0000569601 00000 n +0000569855 00000 n +0000146253 00000 n +0000146375 00000 n +0000320241 00000 n +0000320365 00000 n +0000067831 00000 n +0000086780 00000 n +0000117943 00000 n +0000067719 00000 n +0000066929 00000 n +0000117821 00000 n +0000068366 00000 n +0000068569 00000 n +0000083938 00000 n +0000084067 00000 n +0000084104 00000 n +0000087315 00000 n +0000087518 00000 n +0000114979 00000 n +0000115108 00000 n +0000115145 00000 n +0000119627 00000 n +0000147279 00000 n +0000146437 00000 n +0000119515 00000 n +0000118081 00000 n +0000146192 00000 n +0000120162 00000 n +0000120360 00000 n +0000143350 00000 n +0000143479 00000 n +0000143516 00000 n +0000176774 00000 n +0000225964 00000 n +0000147167 00000 n +0000146575 00000 n +0000225719 00000 n +0000225841 00000 n +0000930189 00000 n +0000147818 00000 n +0000148020 00000 n +0000173932 00000 n +0000174061 00000 n +0000174098 00000 n +0000177262 00000 n +0000177476 00000 n +0000219097 00000 n +0000219212 00000 n +0000229433 00000 n +0000228952 00000 n +0000226102 00000 n +0000229064 00000 n +0000229125 00000 n +0000229248 00000 n +0000845321 00000 n +0000843437 00000 n +0000845159 00000 n +0000229371 00000 n +0000231419 00000 n +0000252529 00000 n +0000231307 00000 n +0000229608 00000 n +0000252345 00000 n +0000252467 00000 n +0000231965 00000 n +0000232169 00000 n +0000249503 00000 n +0000249632 00000 n +0000249669 00000 n +0000256601 00000 n +0000256052 00000 n +0000252680 00000 n +0000256356 00000 n +0000256478 00000 n +0000843052 00000 n +0000840936 00000 n +0000842887 00000 n +0000256184 00000 n +0000258269 00000 n +0000257806 00000 n +0000256737 00000 n +0000258146 00000 n +0000257938 00000 n +0000258207 00000 n +0000262663 00000 n +0000260210 00000 n +0000258392 00000 n +0000262418 00000 n +0000260438 00000 n +0000260584 00000 n +0000260737 00000 n +0000260891 00000 n +0000261041 00000 n +0000261190 00000 n +0000261346 00000 n +0000261500 00000 n +0000261651 00000 n +0000262540 00000 n +0000839934 00000 n +0000829342 00000 n +0000839772 00000 n +0000829025 00000 n +0000827608 00000 n +0000828863 00000 n +0000261805 00000 n +0000261961 00000 n +0000262118 00000 n +0000262269 00000 n +0000325470 00000 n +0000430522 00000 n +0000510209 00000 n +0000536690 00000 n +0000540110 00000 n +0000562779 00000 n +0000573250 00000 n +0000573567 00000 n +0000267721 00000 n +0000270720 00000 n +0000277628 00000 n +0000283442 00000 n +0000268028 00000 n +0000265044 00000 n +0000262812 00000 n +0000267660 00000 n +0000265288 00000 n +0000265444 00000 n +0000265603 00000 n +0000265761 00000 n +0000265914 00000 n +0000266071 00000 n +0000266238 00000 n +0000266401 00000 n +0000266561 00000 n +0000266727 00000 n +0000266885 00000 n +0000267039 00000 n +0000267202 00000 n +0000267354 00000 n +0000267844 00000 n +0000827126 00000 n +0000822927 00000 n +0000826963 00000 n +0000822448 00000 n +0000819621 00000 n +0000822285 00000 n +0000818671 00000 n +0000808602 00000 n +0000818509 00000 n +0000267509 00000 n +0000267906 00000 n +0000267968 00000 n +0000930307 00000 n +0000283564 00000 n +0000291947 00000 n +0000300491 00000 n +0000300739 00000 n +0000310549 00000 n +0000316954 00000 n +0000319869 00000 n +0000319993 00000 n +0000320117 00000 n +0000325037 00000 n +0000325161 00000 n +0000325346 00000 n +0000270843 00000 n +0000270132 00000 n +0000268216 00000 n +0000270413 00000 n +0000270474 00000 n +0000270535 00000 n +0000270596 00000 n +0000270658 00000 n +0000270264 00000 n +0000274366 00000 n +0000273077 00000 n +0000270992 00000 n +0000273872 00000 n +0000273933 00000 n +0000273995 00000 n +0000273233 00000 n +0000273401 00000 n +0000274057 00000 n +0000274119 00000 n +0000274181 00000 n +0000274243 00000 n +0000274305 00000 n +0000273557 00000 n +0000273714 00000 n +0000277504 00000 n +0000527272 00000 n +0000611999 00000 n +0000277751 00000 n +0000276788 00000 n +0000274541 00000 n +0000277443 00000 n +0000276936 00000 n +0000277104 00000 n +0000277566 00000 n +0000277274 00000 n +0000279904 00000 n +0000283626 00000 n +0000279756 00000 n +0000277926 00000 n +0000283319 00000 n +0000282838 00000 n +0000283380 00000 n +0000283005 00000 n +0000283162 00000 n +0000280545 00000 n +0000280714 00000 n +0000282189 00000 n +0000282700 00000 n +0000282756 00000 n +0000282776 00000 n +0000282798 00000 n +0000282819 00000 n +0000285442 00000 n +0000288848 00000 n +0000292132 00000 n +0000285330 00000 n +0000283803 00000 n +0000291762 00000 n +0000291885 00000 n +0000292070 00000 n +0000286088 00000 n +0000286257 00000 n +0000287932 00000 n +0000288710 00000 n +0000288766 00000 n +0000288786 00000 n +0000288808 00000 n +0000288829 00000 n +0000289498 00000 n +0000289667 00000 n +0000291109 00000 n +0000291624 00000 n +0000291680 00000 n +0000291700 00000 n +0000291722 00000 n +0000291743 00000 n +0000293849 00000 n +0000296890 00000 n +0000300863 00000 n +0000293709 00000 n +0000292337 00000 n +0000300368 00000 n +0000300429 00000 n +0000300048 00000 n +0000300211 00000 n +0000300615 00000 n +0000300677 00000 n +0000930425 00000 n +0000294497 00000 n +0000294666 00000 n +0000296195 00000 n +0000296752 00000 n +0000296808 00000 n +0000296828 00000 n +0000296850 00000 n +0000296871 00000 n +0000297534 00000 n +0000297703 00000 n +0000299311 00000 n +0000299910 00000 n +0000299966 00000 n +0000299986 00000 n +0000300008 00000 n +0000300029 00000 n +0000304173 00000 n +0000303330 00000 n +0000301055 00000 n +0000303803 00000 n +0000303864 00000 n +0000303470 00000 n +0000303926 00000 n +0000303640 00000 n +0000303987 00000 n +0000304049 00000 n +0000304111 00000 n +0000310487 00000 n +0000306857 00000 n +0000310795 00000 n +0000306709 00000 n +0000304348 00000 n +0000310426 00000 n +0000309915 00000 n +0000310084 00000 n +0000310672 00000 n +0000310253 00000 n +0000310734 00000 n +0000307504 00000 n +0000307673 00000 n +0000309208 00000 n +0000309777 00000 n +0000309833 00000 n +0000309853 00000 n +0000309875 00000 n +0000309896 00000 n +0000316892 00000 n +0000313188 00000 n +0000317077 00000 n +0000313040 00000 n +0000310999 00000 n +0000316769 00000 n +0000316830 00000 n +0000316268 00000 n +0000316440 00000 n +0000316612 00000 n +0000313845 00000 n +0000314014 00000 n +0000315563 00000 n +0000316130 00000 n +0000316186 00000 n +0000316206 00000 n +0000316228 00000 n +0000316249 00000 n +0000320488 00000 n +0000319215 00000 n +0000317294 00000 n +0000319684 00000 n +0000319745 00000 n +0000319931 00000 n +0000319355 00000 n +0000320055 00000 n +0000320179 00000 n +0000319521 00000 n +0000320303 00000 n +0000320426 00000 n +0000325594 00000 n +0000322794 00000 n +0000320650 00000 n +0000324914 00000 n +0000325099 00000 n +0000325223 00000 n +0000325408 00000 n +0000323014 00000 n +0000323175 00000 n +0000323327 00000 n +0000323482 00000 n +0000323643 00000 n +0000323802 00000 n +0000323963 00000 n +0000324121 00000 n +0000324277 00000 n +0000324442 00000 n +0000324606 00000 n +0000324765 00000 n +0000340676 00000 n +0000340862 00000 n +0000347796 00000 n +0000347920 00000 n +0000350745 00000 n +0000361678 00000 n +0000365025 00000 n +0000368886 00000 n +0000369140 00000 n +0000376468 00000 n +0000382709 00000 n +0000405407 00000 n +0000327977 00000 n +0000331420 00000 n +0000340986 00000 n +0000327773 00000 n +0000325743 00000 n +0000340615 00000 n +0000339044 00000 n +0000339195 00000 n +0000339350 00000 n +0000339509 00000 n +0000339667 00000 n +0000339825 00000 n +0000339982 00000 n +0000340142 00000 n +0000340300 00000 n +0000340800 00000 n +0000340454 00000 n +0000930543 00000 n +0000328628 00000 n +0000328797 00000 n +0000330462 00000 n +0000331282 00000 n +0000331338 00000 n +0000331358 00000 n +0000331380 00000 n +0000331401 00000 n +0000331924 00000 n +0000332139 00000 n +0000332188 00000 n +0000332559 00000 n +0000332674 00000 n +0000332855 00000 n +0000405533 00000 n +0000411537 00000 n +0000411727 00000 n +0000415944 00000 n +0000419443 00000 n +0000425098 00000 n +0000430395 00000 n +0000343138 00000 n +0000347982 00000 n +0000342942 00000 n +0000341217 00000 n +0000347735 00000 n +0000346308 00000 n +0000346466 00000 n +0000346622 00000 n +0000346780 00000 n +0000346937 00000 n +0000347095 00000 n +0000347260 00000 n +0000347418 00000 n +0000347574 00000 n +0000343783 00000 n +0000343952 00000 n +0000345526 00000 n +0000346170 00000 n +0000346226 00000 n +0000346246 00000 n +0000346268 00000 n +0000346289 00000 n +0000425287 00000 n +0000350869 00000 n +0000349579 00000 n +0000348134 00000 n +0000350371 00000 n +0000349737 00000 n +0000349898 00000 n +0000350494 00000 n +0000350556 00000 n +0000350619 00000 n +0000350682 00000 n +0000350055 00000 n +0000350214 00000 n +0000354685 00000 n +0000352953 00000 n +0000351044 00000 n +0000354110 00000 n +0000353134 00000 n +0000353288 00000 n +0000354173 00000 n +0000354237 00000 n +0000354301 00000 n +0000354365 00000 n +0000354429 00000 n +0000353442 00000 n +0000354493 00000 n +0000353612 00000 n +0000353782 00000 n +0000354557 00000 n +0000353953 00000 n +0000354621 00000 n +0000358108 00000 n +0000358555 00000 n +0000356843 00000 n +0000354835 00000 n +0000358045 00000 n +0000358172 00000 n +0000358236 00000 n +0000357024 00000 n +0000358299 00000 n +0000358363 00000 n +0000357192 00000 n +0000358427 00000 n +0000357361 00000 n +0000357531 00000 n +0000357702 00000 n +0000358491 00000 n +0000357876 00000 n +0000361995 00000 n +0000360414 00000 n +0000358679 00000 n +0000361551 00000 n +0000361614 00000 n +0000360595 00000 n +0000360754 00000 n +0000360911 00000 n +0000361066 00000 n +0000361804 00000 n +0000361867 00000 n +0000361221 00000 n +0000361386 00000 n +0000361931 00000 n +0000365341 00000 n +0000363756 00000 n +0000362171 00000 n +0000364898 00000 n +0000364961 00000 n +0000363938 00000 n +0000364103 00000 n +0000364262 00000 n +0000364419 00000 n +0000364572 00000 n +0000365150 00000 n +0000365214 00000 n +0000364725 00000 n +0000365277 00000 n +0000930664 00000 n +0000369203 00000 n +0000367265 00000 n +0000365517 00000 n +0000368759 00000 n +0000367465 00000 n +0000368822 00000 n +0000367634 00000 n +0000367808 00000 n +0000367967 00000 n +0000368124 00000 n +0000368274 00000 n +0000369012 00000 n +0000368425 00000 n +0000369076 00000 n +0000368590 00000 n +0000373019 00000 n +0000371527 00000 n +0000369379 00000 n +0000372510 00000 n +0000371700 00000 n +0000371860 00000 n +0000372020 00000 n +0000372636 00000 n +0000372180 00000 n +0000372700 00000 n +0000372764 00000 n +0000372345 00000 n +0000372828 00000 n +0000372892 00000 n +0000372956 00000 n +0000376149 00000 n +0000376594 00000 n +0000375079 00000 n +0000373208 00000 n +0000376086 00000 n +0000375252 00000 n +0000376212 00000 n +0000376276 00000 n +0000375420 00000 n +0000376340 00000 n +0000375595 00000 n +0000376404 00000 n +0000375770 00000 n +0000375929 00000 n +0000378774 00000 n +0000382963 00000 n +0000378619 00000 n +0000376757 00000 n +0000382454 00000 n +0000382517 00000 n +0000381952 00000 n +0000382581 00000 n +0000382122 00000 n +0000382645 00000 n +0000382289 00000 n +0000382835 00000 n +0000382899 00000 n +0000379431 00000 n +0000379601 00000 n +0000381215 00000 n +0000381808 00000 n +0000381866 00000 n +0000381887 00000 n +0000381910 00000 n +0000381932 00000 n +0000386374 00000 n +0000385185 00000 n +0000383182 00000 n +0000385864 00000 n +0000385927 00000 n +0000385990 00000 n +0000386054 00000 n +0000386118 00000 n +0000386182 00000 n +0000386246 00000 n +0000385340 00000 n +0000385515 00000 n +0000385690 00000 n +0000386310 00000 n +0000390298 00000 n +0000390744 00000 n +0000388651 00000 n +0000386524 00000 n +0000390235 00000 n +0000388851 00000 n +0000389023 00000 n +0000389195 00000 n +0000389370 00000 n +0000389544 00000 n +0000390361 00000 n +0000389717 00000 n +0000389891 00000 n +0000390425 00000 n +0000390489 00000 n +0000390553 00000 n +0000390616 00000 n +0000390065 00000 n +0000390680 00000 n +0000930789 00000 n +0000395530 00000 n +0000393525 00000 n +0000390907 00000 n +0000395275 00000 n +0000393734 00000 n +0000395338 00000 n +0000393905 00000 n +0000395402 00000 n +0000394061 00000 n +0000394235 00000 n +0000394410 00000 n +0000394581 00000 n +0000394753 00000 n +0000394926 00000 n +0000395466 00000 n +0000395101 00000 n +0000397921 00000 n +0000401156 00000 n +0000405659 00000 n +0000397748 00000 n +0000395719 00000 n +0000405280 00000 n +0000405343 00000 n +0000404487 00000 n +0000404647 00000 n +0000404806 00000 n +0000404963 00000 n +0000405122 00000 n +0000398570 00000 n +0000398740 00000 n +0000400352 00000 n +0000401012 00000 n +0000401070 00000 n +0000401091 00000 n +0000401114 00000 n +0000401136 00000 n +0000401804 00000 n +0000401974 00000 n +0000403638 00000 n +0000404343 00000 n +0000404401 00000 n +0000404422 00000 n +0000404445 00000 n +0000404467 00000 n +0000407560 00000 n +0000411853 00000 n +0000407387 00000 n +0000405893 00000 n +0000411474 00000 n +0000410693 00000 n +0000410852 00000 n +0000411009 00000 n +0000411165 00000 n +0000411317 00000 n +0000411663 00000 n +0000408216 00000 n +0000408386 00000 n +0000409960 00000 n +0000410549 00000 n +0000410607 00000 n +0000410628 00000 n +0000410651 00000 n +0000410673 00000 n +0000416069 00000 n +0000414727 00000 n +0000412020 00000 n +0000415881 00000 n +0000414909 00000 n +0000415075 00000 n +0000415236 00000 n +0000415398 00000 n +0000415560 00000 n +0000415721 00000 n +0000419506 00000 n +0000418396 00000 n +0000416193 00000 n +0000419060 00000 n +0000419123 00000 n +0000419187 00000 n +0000419251 00000 n +0000418551 00000 n +0000419315 00000 n +0000418716 00000 n +0000419379 00000 n +0000418888 00000 n +0000421277 00000 n +0000425350 00000 n +0000421113 00000 n +0000419682 00000 n +0000424972 00000 n +0000424332 00000 n +0000424491 00000 n +0000424648 00000 n +0000424813 00000 n +0000425223 00000 n +0000930914 00000 n +0000421932 00000 n +0000422102 00000 n +0000423610 00000 n +0000424188 00000 n +0000424246 00000 n +0000424267 00000 n +0000424290 00000 n +0000424312 00000 n +0000430710 00000 n +0000428148 00000 n +0000425530 00000 n +0000430142 00000 n +0000430205 00000 n +0000430269 00000 n +0000430458 00000 n +0000428375 00000 n +0000428550 00000 n +0000428707 00000 n +0000428866 00000 n +0000429032 00000 n +0000429197 00000 n +0000429357 00000 n +0000429513 00000 n +0000429669 00000 n +0000429824 00000 n +0000429982 00000 n +0000430647 00000 n +0000441155 00000 n +0000450733 00000 n +0000450860 00000 n +0000479579 00000 n +0000479706 00000 n +0000488387 00000 n +0000494958 00000 n +0000495148 00000 n +0000504951 00000 n +0000433322 00000 n +0000436338 00000 n +0000441282 00000 n +0000433113 00000 n +0000430912 00000 n +0000440965 00000 n +0000439503 00000 n +0000439661 00000 n +0000441091 00000 n +0000439818 00000 n +0000439973 00000 n +0000440137 00000 n +0000440296 00000 n +0000440453 00000 n +0000440619 00000 n +0000440792 00000 n +0000433975 00000 n +0000434145 00000 n +0000435659 00000 n +0000436194 00000 n +0000436252 00000 n +0000436273 00000 n +0000436296 00000 n +0000436318 00000 n +0000436994 00000 n +0000437164 00000 n +0000438767 00000 n +0000439359 00000 n +0000439417 00000 n +0000439438 00000 n +0000439461 00000 n +0000439483 00000 n +0000482798 00000 n +0000444173 00000 n +0000447510 00000 n +0000444300 00000 n +0000443122 00000 n +0000441477 00000 n +0000443790 00000 n +0000443853 00000 n +0000443917 00000 n +0000443981 00000 n +0000443277 00000 n +0000444045 00000 n +0000444109 00000 n +0000443449 00000 n +0000443621 00000 n +0000444236 00000 n +0000513510 00000 n +0000447764 00000 n +0000447079 00000 n +0000444463 00000 n +0000447383 00000 n +0000447446 00000 n +0000447216 00000 n +0000447574 00000 n +0000447638 00000 n +0000447701 00000 n +0000450924 00000 n +0000449743 00000 n +0000447940 00000 n +0000450542 00000 n +0000450605 00000 n +0000450669 00000 n +0000449907 00000 n +0000450063 00000 n +0000450223 00000 n +0000450382 00000 n +0000454274 00000 n +0000452741 00000 n +0000451074 00000 n +0000453892 00000 n +0000452923 00000 n +0000453079 00000 n +0000453239 00000 n +0000453399 00000 n +0000454018 00000 n +0000453559 00000 n +0000453724 00000 n +0000454082 00000 n +0000454146 00000 n +0000454210 00000 n +0000931039 00000 n +0000465403 00000 n +0000465467 00000 n +0000460552 00000 n +0000457223 00000 n +0000454411 00000 n +0000460169 00000 n +0000457495 00000 n +0000457660 00000 n +0000460232 00000 n +0000457828 00000 n +0000457993 00000 n +0000460296 00000 n +0000458161 00000 n +0000458330 00000 n +0000458504 00000 n +0000460360 00000 n +0000458670 00000 n +0000458837 00000 n +0000460424 00000 n +0000459012 00000 n +0000459176 00000 n +0000459343 00000 n +0000459508 00000 n +0000459677 00000 n +0000459840 00000 n +0000460005 00000 n +0000460488 00000 n +0000465339 00000 n +0000465594 00000 n +0000463040 00000 n +0000460702 00000 n +0000465276 00000 n +0000463276 00000 n +0000463441 00000 n +0000463607 00000 n +0000463774 00000 n +0000463943 00000 n +0000464110 00000 n +0000464277 00000 n +0000464442 00000 n +0000465531 00000 n +0000464611 00000 n +0000464777 00000 n +0000464944 00000 n +0000465112 00000 n +0000482542 00000 n +0000469005 00000 n +0000468379 00000 n +0000465770 00000 n +0000468687 00000 n +0000468750 00000 n +0000808249 00000 n +0000806483 00000 n +0000808083 00000 n +0000000000 00000 f +0000806383 00000 n +0000468814 00000 n +0000468878 00000 n +0000468516 00000 n +0000468942 00000 n +0000479516 00000 n +0000471646 00000 n +0000474773 00000 n +0000479833 00000 n +0000471428 00000 n +0000469209 00000 n +0000479453 00000 n +0000477824 00000 n +0000477989 00000 n +0000478154 00000 n +0000478326 00000 n +0000478482 00000 n +0000478648 00000 n +0000478804 00000 n +0000478963 00000 n +0000479122 00000 n +0000479288 00000 n +0000472302 00000 n +0000472472 00000 n +0000474066 00000 n +0000474629 00000 n +0000474687 00000 n +0000474708 00000 n +0000474731 00000 n +0000474753 00000 n +0000475425 00000 n +0000475595 00000 n +0000477150 00000 n +0000477680 00000 n +0000477738 00000 n +0000477759 00000 n +0000477782 00000 n +0000477804 00000 n +0000482925 00000 n +0000482171 00000 n +0000480054 00000 n +0000482479 00000 n +0000482606 00000 n +0000482308 00000 n +0000482670 00000 n +0000482734 00000 n +0000482862 00000 n +0000484929 00000 n +0000488767 00000 n +0000484792 00000 n +0000483088 00000 n +0000488260 00000 n +0000488323 00000 n +0000488513 00000 n +0000488577 00000 n +0000488089 00000 n +0000488641 00000 n +0000488705 00000 n +0000931164 00000 n +0000485582 00000 n +0000485752 00000 n +0000487263 00000 n +0000487945 00000 n +0000488003 00000 n +0000488024 00000 n +0000488047 00000 n +0000488069 00000 n +0000491156 00000 n +0000495211 00000 n +0000491010 00000 n +0000488947 00000 n +0000494703 00000 n +0000494766 00000 n +0000494830 00000 n +0000494367 00000 n +0000494894 00000 n +0000494532 00000 n +0000495084 00000 n +0000491807 00000 n +0000491977 00000 n +0000493577 00000 n +0000494223 00000 n +0000494281 00000 n +0000494302 00000 n +0000494325 00000 n +0000494347 00000 n +0000497345 00000 n +0000500617 00000 n +0000505077 00000 n +0000497163 00000 n +0000495391 00000 n +0000504697 00000 n +0000503754 00000 n +0000503912 00000 n +0000504067 00000 n +0000504823 00000 n +0000504221 00000 n +0000504887 00000 n +0000504376 00000 n +0000504532 00000 n +0000498000 00000 n +0000498170 00000 n +0000499743 00000 n +0000500473 00000 n +0000500531 00000 n +0000500552 00000 n +0000500575 00000 n +0000500597 00000 n +0000501273 00000 n +0000501443 00000 n +0000503040 00000 n +0000503610 00000 n +0000503668 00000 n +0000503689 00000 n +0000503712 00000 n +0000503734 00000 n +0000510460 00000 n +0000508460 00000 n +0000505272 00000 n +0000510146 00000 n +0000508669 00000 n +0000508838 00000 n +0000509009 00000 n +0000509180 00000 n +0000509345 00000 n +0000509502 00000 n +0000509660 00000 n +0000510335 00000 n +0000509816 00000 n +0000509974 00000 n +0000527462 00000 n +0000517182 00000 n +0000513702 00000 n +0000512379 00000 n +0000510597 00000 n +0000513191 00000 n +0000512543 00000 n +0000512701 00000 n +0000513254 00000 n +0000513318 00000 n +0000513382 00000 n +0000512857 00000 n +0000513446 00000 n +0000513024 00000 n +0000513574 00000 n +0000513638 00000 n +0000517565 00000 n +0000516457 00000 n +0000513865 00000 n +0000517119 00000 n +0000516612 00000 n +0000517246 00000 n +0000517310 00000 n +0000516781 00000 n +0000517374 00000 n +0000516950 00000 n +0000517438 00000 n +0000517502 00000 n +0000519799 00000 n +0000522951 00000 n +0000527589 00000 n +0000519608 00000 n +0000517728 00000 n +0000527209 00000 n +0000526092 00000 n +0000526265 00000 n +0000526423 00000 n +0000526581 00000 n +0000527398 00000 n +0000526736 00000 n +0000526894 00000 n +0000527052 00000 n +0000931289 00000 n +0000520453 00000 n +0000520623 00000 n +0000522248 00000 n +0000522807 00000 n +0000522865 00000 n +0000522886 00000 n +0000522909 00000 n +0000522931 00000 n +0000523603 00000 n +0000523773 00000 n +0000525392 00000 n +0000525948 00000 n +0000526006 00000 n +0000526027 00000 n +0000526050 00000 n +0000526072 00000 n +0000529679 00000 n +0000532856 00000 n +0000537069 00000 n +0000529515 00000 n +0000527810 00000 n +0000536627 00000 n +0000535990 00000 n +0000536147 00000 n +0000536305 00000 n +0000536816 00000 n +0000536466 00000 n +0000536943 00000 n +0000530333 00000 n +0000530503 00000 n +0000532056 00000 n +0000532712 00000 n +0000532770 00000 n +0000532791 00000 n +0000532814 00000 n +0000532836 00000 n +0000533513 00000 n +0000533683 00000 n +0000535246 00000 n +0000535846 00000 n +0000535904 00000 n +0000535925 00000 n +0000535948 00000 n +0000535970 00000 n +0000540362 00000 n +0000538913 00000 n +0000537264 00000 n +0000540047 00000 n +0000539095 00000 n +0000539253 00000 n +0000539411 00000 n +0000539574 00000 n +0000539730 00000 n +0000539888 00000 n +0000540235 00000 n +0000552576 00000 n +0000552702 00000 n +0000562460 00000 n +0000543998 00000 n +0000542358 00000 n +0000540512 00000 n +0000543487 00000 n +0000542540 00000 n +0000542697 00000 n +0000542854 00000 n +0000543550 00000 n +0000543614 00000 n +0000543011 00000 n +0000543678 00000 n +0000543168 00000 n +0000543327 00000 n +0000543742 00000 n +0000543806 00000 n +0000543870 00000 n +0000543934 00000 n +0000546451 00000 n +0000545888 00000 n +0000544161 00000 n +0000546004 00000 n +0000546067 00000 n +0000546131 00000 n +0000546195 00000 n +0000546259 00000 n +0000546323 00000 n +0000546387 00000 n +0000548555 00000 n +0000552956 00000 n +0000548382 00000 n +0000546588 00000 n +0000552513 00000 n +0000551710 00000 n +0000551873 00000 n +0000552031 00000 n +0000552197 00000 n +0000552356 00000 n +0000552828 00000 n +0000552892 00000 n +0000549208 00000 n +0000549378 00000 n +0000550924 00000 n +0000551566 00000 n +0000551624 00000 n +0000551645 00000 n +0000551668 00000 n +0000551690 00000 n +0000556177 00000 n +0000554949 00000 n +0000553136 00000 n +0000555604 00000 n +0000555667 00000 n +0000555731 00000 n +0000555795 00000 n +0000555104 00000 n +0000555858 00000 n +0000555922 00000 n +0000555986 00000 n +0000555275 00000 n +0000556050 00000 n +0000555441 00000 n +0000556114 00000 n +0000931414 00000 n +0000559864 00000 n +0000558830 00000 n +0000556301 00000 n +0000559483 00000 n +0000558985 00000 n +0000559546 00000 n +0000559152 00000 n +0000559610 00000 n +0000559672 00000 n +0000559736 00000 n +0000559319 00000 n +0000559800 00000 n +0000562842 00000 n +0000561589 00000 n +0000560001 00000 n +0000562397 00000 n +0000561753 00000 n +0000561925 00000 n +0000562084 00000 n +0000562587 00000 n +0000562651 00000 n +0000562241 00000 n +0000562715 00000 n +0000565469 00000 n +0000569918 00000 n +0000565314 00000 n +0000563005 00000 n +0000569475 00000 n +0000569005 00000 n +0000569161 00000 n +0000569320 00000 n +0000569727 00000 n +0000569791 00000 n +0000566121 00000 n +0000566291 00000 n +0000568135 00000 n +0000568861 00000 n +0000568919 00000 n +0000568940 00000 n +0000568963 00000 n +0000568985 00000 n +0000573630 00000 n +0000572193 00000 n +0000570124 00000 n +0000572995 00000 n +0000572357 00000 n +0000572512 00000 n +0000573058 00000 n +0000573122 00000 n +0000572671 00000 n +0000573186 00000 n +0000572837 00000 n +0000573439 00000 n +0000573503 00000 n +0000575985 00000 n +0000579262 00000 n +0000585305 00000 n +0000575776 00000 n +0000573845 00000 n +0000584924 00000 n +0000583477 00000 n +0000583637 00000 n +0000583793 00000 n +0000583955 00000 n +0000584119 00000 n +0000585050 00000 n +0000584278 00000 n +0000584436 00000 n +0000584601 00000 n +0000584768 00000 n +0000585177 00000 n +0000585241 00000 n +0000576641 00000 n +0000576811 00000 n +0000578459 00000 n +0000579118 00000 n +0000579176 00000 n +0000579197 00000 n +0000579220 00000 n +0000579242 00000 n +0000579825 00000 n +0000580026 00000 n +0000580422 00000 n +0000580552 00000 n +0000580591 00000 n +0000580641 00000 n +0000583318 00000 n +0000592220 00000 n +0000596329 00000 n +0000600016 00000 n +0000587699 00000 n +0000592347 00000 n +0000587544 00000 n +0000585513 00000 n +0000591965 00000 n +0000591480 00000 n +0000592028 00000 n +0000592092 00000 n +0000591635 00000 n +0000592156 00000 n +0000591803 00000 n +0000931539 00000 n +0000588351 00000 n +0000588521 00000 n +0000590377 00000 n +0000591336 00000 n +0000591394 00000 n +0000591415 00000 n +0000591438 00000 n +0000591460 00000 n +0000596711 00000 n +0000594583 00000 n +0000592553 00000 n +0000596266 00000 n +0000594792 00000 n +0000594952 00000 n +0000595120 00000 n +0000595288 00000 n +0000595462 00000 n +0000595618 00000 n +0000595774 00000 n +0000596455 00000 n +0000596519 00000 n +0000596583 00000 n +0000595934 00000 n +0000596108 00000 n +0000596647 00000 n +0000599952 00000 n +0000600335 00000 n +0000598896 00000 n +0000596874 00000 n +0000599889 00000 n +0000599069 00000 n +0000599241 00000 n +0000599398 00000 n +0000599556 00000 n +0000600143 00000 n +0000600207 00000 n +0000599714 00000 n +0000600271 00000 n +0000604280 00000 n +0000604344 00000 n +0000602880 00000 n +0000600511 00000 n +0000603898 00000 n +0000603961 00000 n +0000604024 00000 n +0000603053 00000 n +0000603221 00000 n +0000604088 00000 n +0000604152 00000 n +0000603389 00000 n +0000603556 00000 n +0000604216 00000 n +0000603727 00000 n +0000607562 00000 n +0000612188 00000 n +0000607371 00000 n +0000604481 00000 n +0000611808 00000 n +0000610656 00000 n +0000610830 00000 n +0000611871 00000 n +0000611935 00000 n +0000611004 00000 n +0000611162 00000 n +0000611327 00000 n +0000611486 00000 n +0000611644 00000 n +0000612125 00000 n +0000608217 00000 n +0000608387 00000 n +0000609935 00000 n +0000610512 00000 n +0000610570 00000 n +0000610591 00000 n +0000610614 00000 n +0000610636 00000 n +0000614396 00000 n +0000614154 00000 n +0000612394 00000 n +0000614270 00000 n +0000617286 00000 n +0000617107 00000 n +0000614533 00000 n +0000617223 00000 n +0000931664 00000 n +0000620329 00000 n +0000620150 00000 n +0000617397 00000 n +0000620266 00000 n +0000622933 00000 n +0000622754 00000 n +0000620453 00000 n +0000622870 00000 n +0000625795 00000 n +0000625616 00000 n +0000623044 00000 n +0000625732 00000 n +0000628305 00000 n +0000628126 00000 n +0000625906 00000 n +0000628242 00000 n +0000630109 00000 n +0000629930 00000 n +0000628416 00000 n +0000630046 00000 n +0000653147 00000 n +0000635269 00000 n +0000630220 00000 n +0000653084 00000 n +0000636396 00000 n +0000636547 00000 n +0000636698 00000 n +0000636849 00000 n +0000637000 00000 n +0000637151 00000 n +0000637301 00000 n +0000637452 00000 n +0000637602 00000 n +0000637753 00000 n +0000637903 00000 n +0000638054 00000 n +0000638203 00000 n +0000638354 00000 n +0000638505 00000 n +0000638656 00000 n +0000638807 00000 n +0000638958 00000 n +0000639108 00000 n +0000639258 00000 n +0000639408 00000 n +0000639558 00000 n +0000639708 00000 n +0000639858 00000 n +0000640008 00000 n +0000640159 00000 n +0000640310 00000 n +0000640461 00000 n +0000640612 00000 n +0000640761 00000 n +0000640912 00000 n +0000641063 00000 n +0000641213 00000 n +0000641363 00000 n +0000641513 00000 n +0000641664 00000 n +0000641815 00000 n +0000641965 00000 n +0000642115 00000 n +0000642266 00000 n +0000642417 00000 n +0000642566 00000 n +0000642716 00000 n +0000642866 00000 n +0000643015 00000 n +0000643166 00000 n +0000643317 00000 n +0000643468 00000 n +0000643619 00000 n +0000643770 00000 n +0000643916 00000 n +0000644064 00000 n +0000644215 00000 n +0000644366 00000 n +0000644517 00000 n +0000644668 00000 n +0000644819 00000 n +0000644970 00000 n +0000645119 00000 n +0000645270 00000 n +0000645420 00000 n +0000645571 00000 n +0000645720 00000 n +0000645870 00000 n +0000646021 00000 n +0000646171 00000 n +0000646322 00000 n +0000646473 00000 n +0000646623 00000 n +0000646774 00000 n +0000646925 00000 n +0000647076 00000 n +0000647226 00000 n +0000647377 00000 n +0000647528 00000 n +0000647679 00000 n +0000647829 00000 n +0000647980 00000 n +0000648131 00000 n +0000648282 00000 n +0000648432 00000 n +0000648582 00000 n +0000648731 00000 n +0000648882 00000 n +0000649031 00000 n +0000649182 00000 n +0000649333 00000 n +0000649483 00000 n +0000649634 00000 n +0000649785 00000 n +0000649936 00000 n +0000650087 00000 n +0000650237 00000 n +0000650388 00000 n +0000650539 00000 n +0000650688 00000 n +0000650839 00000 n +0000650988 00000 n +0000651138 00000 n +0000651287 00000 n +0000651437 00000 n +0000651586 00000 n +0000651736 00000 n +0000651885 00000 n +0000652036 00000 n +0000652187 00000 n +0000652338 00000 n +0000652489 00000 n +0000652640 00000 n +0000652788 00000 n +0000652936 00000 n +0000931789 00000 n +0000676383 00000 n +0000658505 00000 n +0000653245 00000 n +0000676320 00000 n +0000659632 00000 n +0000659781 00000 n +0000659930 00000 n +0000660081 00000 n +0000660231 00000 n +0000660381 00000 n +0000660531 00000 n +0000660681 00000 n +0000660832 00000 n +0000660983 00000 n +0000661134 00000 n +0000661285 00000 n +0000661436 00000 n +0000661587 00000 n +0000661737 00000 n +0000661888 00000 n +0000662039 00000 n +0000662190 00000 n +0000662341 00000 n +0000662492 00000 n +0000662643 00000 n +0000662792 00000 n +0000662943 00000 n +0000663092 00000 n +0000663242 00000 n +0000663392 00000 n +0000663543 00000 n +0000663694 00000 n +0000663845 00000 n +0000663995 00000 n +0000664146 00000 n +0000664296 00000 n +0000664447 00000 n +0000664598 00000 n +0000664749 00000 n +0000664900 00000 n +0000665051 00000 n +0000665198 00000 n +0000665349 00000 n +0000665500 00000 n +0000665647 00000 n +0000665797 00000 n +0000665948 00000 n +0000666099 00000 n +0000666250 00000 n +0000666401 00000 n +0000666552 00000 n +0000666703 00000 n +0000666853 00000 n +0000667004 00000 n +0000667153 00000 n +0000667304 00000 n +0000667455 00000 n +0000667604 00000 n +0000667751 00000 n +0000667900 00000 n +0000668051 00000 n +0000668201 00000 n +0000668352 00000 n +0000668502 00000 n +0000668653 00000 n +0000668804 00000 n +0000668955 00000 n +0000669105 00000 n +0000669255 00000 n +0000669406 00000 n +0000669557 00000 n +0000669708 00000 n +0000669859 00000 n +0000670010 00000 n +0000670161 00000 n +0000670310 00000 n +0000670461 00000 n +0000670611 00000 n +0000670761 00000 n +0000670912 00000 n +0000671061 00000 n +0000671212 00000 n +0000671363 00000 n +0000671514 00000 n +0000671665 00000 n +0000671815 00000 n +0000671965 00000 n +0000672116 00000 n +0000672265 00000 n +0000672414 00000 n +0000672565 00000 n +0000672715 00000 n +0000672866 00000 n +0000673016 00000 n +0000673166 00000 n +0000673316 00000 n +0000673467 00000 n +0000673618 00000 n +0000673769 00000 n +0000673919 00000 n +0000674069 00000 n +0000674220 00000 n +0000674371 00000 n +0000674521 00000 n +0000674671 00000 n +0000674822 00000 n +0000674973 00000 n +0000675123 00000 n +0000675274 00000 n +0000675424 00000 n +0000675575 00000 n +0000675723 00000 n +0000675873 00000 n +0000676023 00000 n +0000676172 00000 n +0000700166 00000 n +0000681641 00000 n +0000676468 00000 n +0000700103 00000 n +0000682804 00000 n +0000682954 00000 n +0000683105 00000 n +0000683254 00000 n +0000683405 00000 n +0000683555 00000 n +0000683706 00000 n +0000683856 00000 n +0000684005 00000 n +0000684156 00000 n +0000684305 00000 n +0000684456 00000 n +0000684607 00000 n +0000684758 00000 n +0000684908 00000 n +0000685058 00000 n +0000685209 00000 n +0000685359 00000 n +0000685509 00000 n +0000685660 00000 n +0000685810 00000 n +0000685961 00000 n +0000686112 00000 n +0000686263 00000 n +0000686414 00000 n +0000686565 00000 n +0000686716 00000 n +0000686866 00000 n +0000687017 00000 n +0000687168 00000 n +0000687317 00000 n +0000687468 00000 n +0000687619 00000 n +0000687770 00000 n +0000687921 00000 n +0000688070 00000 n +0000688221 00000 n +0000688371 00000 n +0000688522 00000 n +0000688672 00000 n +0000688823 00000 n +0000688974 00000 n +0000689124 00000 n +0000689275 00000 n +0000689426 00000 n +0000689577 00000 n +0000689728 00000 n +0000689879 00000 n +0000690030 00000 n +0000690181 00000 n +0000690332 00000 n +0000690481 00000 n +0000690630 00000 n +0000690780 00000 n +0000690930 00000 n +0000691081 00000 n +0000691231 00000 n +0000691382 00000 n +0000691531 00000 n +0000691681 00000 n +0000691830 00000 n +0000691981 00000 n +0000692131 00000 n +0000692282 00000 n +0000692433 00000 n +0000692582 00000 n +0000692733 00000 n +0000692884 00000 n +0000693035 00000 n +0000693186 00000 n +0000693337 00000 n +0000693488 00000 n +0000693639 00000 n +0000693790 00000 n +0000693940 00000 n +0000694089 00000 n +0000694239 00000 n +0000694389 00000 n +0000694539 00000 n +0000694689 00000 n +0000694839 00000 n +0000694988 00000 n +0000695139 00000 n +0000695289 00000 n +0000695440 00000 n +0000695591 00000 n +0000695742 00000 n +0000695893 00000 n +0000696044 00000 n +0000696195 00000 n +0000696345 00000 n +0000696495 00000 n +0000696644 00000 n +0000696795 00000 n +0000696946 00000 n +0000697097 00000 n +0000697247 00000 n +0000697398 00000 n +0000697548 00000 n +0000697699 00000 n +0000697849 00000 n +0000698000 00000 n +0000698151 00000 n +0000698302 00000 n +0000698453 00000 n +0000698603 00000 n +0000698754 00000 n +0000698905 00000 n +0000699056 00000 n +0000699206 00000 n +0000699355 00000 n +0000699506 00000 n +0000699656 00000 n +0000699806 00000 n +0000699954 00000 n +0000722929 00000 n +0000705685 00000 n +0000700251 00000 n +0000722866 00000 n +0000706776 00000 n +0000706927 00000 n +0000707077 00000 n +0000707228 00000 n +0000707379 00000 n +0000707529 00000 n +0000707680 00000 n +0000707831 00000 n +0000707982 00000 n +0000708131 00000 n +0000708282 00000 n +0000708432 00000 n +0000708583 00000 n +0000708733 00000 n +0000708884 00000 n +0000709035 00000 n +0000709186 00000 n +0000709335 00000 n +0000709486 00000 n +0000709637 00000 n +0000709788 00000 n +0000709935 00000 n +0000710085 00000 n +0000710236 00000 n +0000710386 00000 n +0000710537 00000 n +0000710688 00000 n +0000710839 00000 n +0000710990 00000 n +0000711141 00000 n +0000711290 00000 n +0000711439 00000 n +0000711590 00000 n +0000711739 00000 n +0000711890 00000 n +0000712040 00000 n +0000712190 00000 n +0000712341 00000 n +0000712492 00000 n +0000712642 00000 n +0000712793 00000 n +0000712944 00000 n +0000713095 00000 n +0000713245 00000 n +0000713396 00000 n +0000713546 00000 n +0000713697 00000 n +0000713846 00000 n +0000713997 00000 n +0000714147 00000 n +0000714298 00000 n +0000714449 00000 n +0000714597 00000 n +0000714746 00000 n +0000714897 00000 n +0000715047 00000 n +0000715196 00000 n +0000715346 00000 n +0000715496 00000 n +0000715645 00000 n +0000715796 00000 n +0000715945 00000 n +0000716096 00000 n +0000716247 00000 n +0000716398 00000 n +0000716549 00000 n +0000716700 00000 n +0000716850 00000 n +0000717000 00000 n +0000717149 00000 n +0000717299 00000 n +0000717449 00000 n +0000717600 00000 n +0000717750 00000 n +0000717901 00000 n +0000718050 00000 n +0000718201 00000 n +0000718352 00000 n +0000718503 00000 n +0000718653 00000 n +0000718804 00000 n +0000718955 00000 n +0000719106 00000 n +0000719256 00000 n +0000719407 00000 n +0000719557 00000 n +0000719708 00000 n +0000719859 00000 n +0000720009 00000 n +0000720160 00000 n +0000720311 00000 n +0000720462 00000 n +0000720613 00000 n +0000720763 00000 n +0000720913 00000 n +0000721064 00000 n +0000721214 00000 n +0000721365 00000 n +0000721516 00000 n +0000721667 00000 n +0000721817 00000 n +0000721967 00000 n +0000722117 00000 n +0000722268 00000 n +0000722417 00000 n +0000722568 00000 n +0000722717 00000 n +0000746769 00000 n +0000728385 00000 n +0000723014 00000 n +0000746706 00000 n +0000729539 00000 n +0000729690 00000 n +0000729840 00000 n +0000729991 00000 n +0000730142 00000 n +0000730292 00000 n +0000730443 00000 n +0000730593 00000 n +0000730744 00000 n +0000730895 00000 n +0000731046 00000 n +0000731197 00000 n +0000731348 00000 n +0000731499 00000 n +0000731650 00000 n +0000731800 00000 n +0000731951 00000 n +0000732101 00000 n +0000732252 00000 n +0000732403 00000 n +0000732553 00000 n +0000732704 00000 n +0000732855 00000 n +0000733006 00000 n +0000733157 00000 n +0000733308 00000 n +0000733459 00000 n +0000733609 00000 n +0000733760 00000 n +0000733911 00000 n +0000734061 00000 n +0000734212 00000 n +0000734363 00000 n +0000734513 00000 n +0000734664 00000 n +0000734815 00000 n +0000734966 00000 n +0000735115 00000 n +0000735265 00000 n +0000735416 00000 n +0000735567 00000 n +0000735717 00000 n +0000735868 00000 n +0000736019 00000 n +0000736170 00000 n +0000736321 00000 n +0000736472 00000 n +0000736622 00000 n +0000736772 00000 n +0000736923 00000 n +0000737073 00000 n +0000737224 00000 n +0000737374 00000 n +0000737524 00000 n +0000737675 00000 n +0000737826 00000 n +0000737977 00000 n +0000738127 00000 n +0000738276 00000 n +0000738427 00000 n +0000738577 00000 n +0000738727 00000 n +0000738878 00000 n +0000739028 00000 n +0000739178 00000 n +0000739329 00000 n +0000739480 00000 n +0000739630 00000 n +0000739781 00000 n +0000739932 00000 n +0000740083 00000 n +0000740233 00000 n +0000740383 00000 n +0000740534 00000 n +0000740685 00000 n +0000740835 00000 n +0000740985 00000 n +0000741135 00000 n +0000741286 00000 n +0000741437 00000 n +0000741587 00000 n +0000741738 00000 n +0000741889 00000 n +0000742040 00000 n +0000742191 00000 n +0000742342 00000 n +0000742493 00000 n +0000742644 00000 n +0000742794 00000 n +0000742945 00000 n +0000743095 00000 n +0000743246 00000 n +0000743397 00000 n +0000743546 00000 n +0000743697 00000 n +0000743847 00000 n +0000743998 00000 n +0000744147 00000 n +0000744297 00000 n +0000744448 00000 n +0000744599 00000 n +0000744750 00000 n +0000744901 00000 n +0000745052 00000 n +0000745202 00000 n +0000745353 00000 n +0000745504 00000 n +0000745654 00000 n +0000745805 00000 n +0000745955 00000 n +0000746106 00000 n +0000746257 00000 n +0000746408 00000 n +0000746558 00000 n +0000770468 00000 n +0000752259 00000 n +0000746854 00000 n +0000770405 00000 n +0000753404 00000 n +0000753555 00000 n +0000753704 00000 n +0000753854 00000 n +0000754005 00000 n +0000754155 00000 n +0000754306 00000 n +0000754456 00000 n +0000754607 00000 n +0000754758 00000 n +0000754909 00000 n +0000755060 00000 n +0000755211 00000 n +0000755362 00000 n +0000755513 00000 n +0000755663 00000 n +0000755813 00000 n +0000755964 00000 n +0000756114 00000 n +0000756265 00000 n +0000756415 00000 n +0000756565 00000 n +0000756716 00000 n +0000756867 00000 n +0000757018 00000 n +0000757168 00000 n +0000757318 00000 n +0000757469 00000 n +0000757620 00000 n +0000757771 00000 n +0000757921 00000 n +0000758072 00000 n +0000758223 00000 n +0000758374 00000 n +0000758523 00000 n +0000758674 00000 n +0000758823 00000 n +0000758974 00000 n +0000759124 00000 n +0000759275 00000 n +0000759426 00000 n +0000759576 00000 n +0000759727 00000 n +0000759878 00000 n +0000760029 00000 n +0000760179 00000 n +0000760330 00000 n +0000760481 00000 n +0000760630 00000 n +0000760781 00000 n +0000760929 00000 n +0000761080 00000 n +0000761230 00000 n +0000761381 00000 n +0000761532 00000 n +0000761683 00000 n +0000761833 00000 n +0000761982 00000 n +0000762133 00000 n +0000762283 00000 n +0000762433 00000 n +0000762583 00000 n +0000762734 00000 n +0000762883 00000 n +0000763033 00000 n +0000763184 00000 n +0000763335 00000 n +0000763485 00000 n +0000763636 00000 n +0000763787 00000 n +0000763938 00000 n +0000764089 00000 n +0000764239 00000 n +0000764390 00000 n +0000764538 00000 n +0000764688 00000 n +0000764837 00000 n +0000764988 00000 n +0000765139 00000 n +0000765290 00000 n +0000765441 00000 n +0000765592 00000 n +0000765743 00000 n +0000765894 00000 n +0000766045 00000 n +0000766196 00000 n +0000766347 00000 n +0000766498 00000 n +0000766649 00000 n +0000766800 00000 n +0000766950 00000 n +0000767101 00000 n +0000767251 00000 n +0000767401 00000 n +0000767552 00000 n +0000767700 00000 n +0000767850 00000 n +0000768001 00000 n +0000768152 00000 n +0000768303 00000 n +0000768452 00000 n +0000768602 00000 n +0000768753 00000 n +0000768904 00000 n +0000769054 00000 n +0000769205 00000 n +0000769355 00000 n +0000769506 00000 n +0000769656 00000 n +0000769807 00000 n +0000769957 00000 n +0000770108 00000 n +0000770257 00000 n +0000794781 00000 n +0000776087 00000 n +0000770553 00000 n +0000794718 00000 n +0000777259 00000 n +0000777409 00000 n +0000777559 00000 n +0000777710 00000 n +0000777860 00000 n +0000778009 00000 n +0000778159 00000 n +0000778310 00000 n +0000778461 00000 n +0000778612 00000 n +0000778763 00000 n +0000778914 00000 n +0000779064 00000 n +0000779215 00000 n +0000779365 00000 n +0000779515 00000 n +0000779666 00000 n +0000779815 00000 n +0000779966 00000 n +0000780116 00000 n +0000780267 00000 n +0000780418 00000 n +0000780567 00000 n +0000780718 00000 n +0000780869 00000 n +0000781019 00000 n +0000781170 00000 n +0000781321 00000 n +0000781472 00000 n +0000781623 00000 n +0000781774 00000 n +0000781925 00000 n +0000782076 00000 n +0000782227 00000 n +0000782378 00000 n +0000782529 00000 n +0000782680 00000 n +0000782831 00000 n +0000782980 00000 n +0000783131 00000 n +0000783282 00000 n +0000783433 00000 n +0000783584 00000 n +0000783735 00000 n +0000783885 00000 n +0000784036 00000 n +0000784187 00000 n +0000784338 00000 n +0000784488 00000 n +0000784639 00000 n +0000784790 00000 n +0000784939 00000 n +0000785090 00000 n +0000785240 00000 n +0000785391 00000 n +0000785542 00000 n +0000785693 00000 n +0000785843 00000 n +0000785991 00000 n +0000786142 00000 n +0000786293 00000 n +0000786443 00000 n +0000786594 00000 n +0000786743 00000 n +0000786894 00000 n +0000787044 00000 n +0000787194 00000 n +0000787345 00000 n +0000787495 00000 n +0000787645 00000 n +0000787796 00000 n +0000787947 00000 n +0000788098 00000 n +0000788249 00000 n +0000788399 00000 n +0000788549 00000 n +0000788699 00000 n +0000788849 00000 n +0000788999 00000 n +0000789149 00000 n +0000789300 00000 n +0000789451 00000 n +0000789602 00000 n +0000789753 00000 n +0000789904 00000 n +0000790054 00000 n +0000790205 00000 n +0000790355 00000 n +0000790506 00000 n +0000790656 00000 n +0000790806 00000 n +0000790957 00000 n +0000791108 00000 n +0000791259 00000 n +0000791409 00000 n +0000791560 00000 n +0000791710 00000 n +0000791861 00000 n +0000792011 00000 n +0000792162 00000 n +0000792313 00000 n +0000792464 00000 n +0000792614 00000 n +0000792765 00000 n +0000792916 00000 n +0000793066 00000 n +0000793216 00000 n +0000793367 00000 n +0000793517 00000 n +0000793668 00000 n +0000793818 00000 n +0000793968 00000 n +0000794119 00000 n +0000794270 00000 n +0000794420 00000 n +0000794569 00000 n +0000931914 00000 n +0000804409 00000 n +0000797363 00000 n +0000794866 00000 n +0000804346 00000 n +0000797878 00000 n +0000798029 00000 n +0000798179 00000 n +0000798329 00000 n +0000798479 00000 n +0000798630 00000 n +0000798779 00000 n +0000798929 00000 n +0000799079 00000 n +0000799229 00000 n +0000799380 00000 n +0000799530 00000 n +0000799681 00000 n +0000799832 00000 n +0000799983 00000 n +0000800132 00000 n +0000800283 00000 n +0000800433 00000 n +0000800584 00000 n +0000800733 00000 n +0000800884 00000 n +0000801033 00000 n +0000801184 00000 n +0000801334 00000 n +0000801485 00000 n +0000801635 00000 n +0000801786 00000 n +0000801935 00000 n +0000802085 00000 n +0000802236 00000 n +0000802387 00000 n +0000802537 00000 n +0000802688 00000 n +0000802838 00000 n +0000802988 00000 n +0000803139 00000 n +0000803289 00000 n +0000803440 00000 n +0000803591 00000 n +0000803742 00000 n +0000803893 00000 n +0000804044 00000 n +0000804195 00000 n +0000804494 00000 n +0000808498 00000 n +0000808469 00000 n +0000819317 00000 n +0000818973 00000 n +0000822756 00000 n +0000822657 00000 n +0000827436 00000 n +0000827349 00000 n +0000829254 00000 n +0000829229 00000 n +0000840611 00000 n +0000840257 00000 n +0000843334 00000 n +0000843261 00000 n +0000845551 00000 n +0000845526 00000 n +0000847844 00000 n +0000847819 00000 n +0000859461 00000 n +0000859134 00000 n +0000873104 00000 n +0000888440 00000 n +0000888060 00000 n +0000900573 00000 n +0000903503 00000 n +0000903275 00000 n +0000922730 00000 n +0000922303 00000 n +0000929516 00000 n +0000929293 00000 n +0000932003 00000 n +0000932123 00000 n +0000932249 00000 n +0000932366 00000 n +0000932448 00000 n +0000940677 00000 n +0000955909 00000 n +0000955950 00000 n +0000955990 00000 n +0000956124 00000 n +trailer +<< +/Size 2844 +/Root 2842 0 R +/Info 2843 0 R +/ID [<50CC741C2DC1A47730A035BCE17624A7> <50CC741C2DC1A47730A035BCE17624A7>] +>> +startxref +956314 +%%EOF diff --git a/official/2.1.6+2.1.beta1/TBX/Documentation/TBX Reference.chm b/official/2.1.6+2.1.beta1/TBX/Documentation/TBX Reference.chm new file mode 100644 index 0000000..d8e5790 Binary files /dev/null and b/official/2.1.6+2.1.beta1/TBX/Documentation/TBX Reference.chm differ diff --git a/official/2.1.6+2.1.beta1/TBX/Packages/tbx_GroupD10.bdsgroup b/official/2.1.6+2.1.beta1/TBX/Packages/tbx_GroupD10.bdsgroup new file mode 100644 index 0000000..c315a96 --- /dev/null +++ b/official/2.1.6+2.1.beta1/TBX/Packages/tbx_GroupD10.bdsgroup @@ -0,0 +1,20 @@ + + + + + + + + + + + + + tbx_d10.bdsproj + tbxdsgn_d10.bdsproj + tbx_d10.bpl tbxdsgn_d10.bpl + + + + diff --git a/official/2.1.6+2.1.beta1/TBX/Packages/tbx_cb5.bpk b/official/2.1.6+2.1.beta1/TBX/Packages/tbx_cb5.bpk new file mode 100644 index 0000000..16934e4 --- /dev/null +++ b/official/2.1.6+2.1.beta1/TBX/Packages/tbx_cb5.bpk @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/official/2.1.6+2.1.beta1/TBX/Packages/tbx_cb5.cpp b/official/2.1.6+2.1.beta1/TBX/Packages/tbx_cb5.cpp new file mode 100644 index 0000000..5631110 --- /dev/null +++ b/official/2.1.6+2.1.beta1/TBX/Packages/tbx_cb5.cpp @@ -0,0 +1,33 @@ +//--------------------------------------------------------------------------- + +#include +#pragma hdrstop +USEPACKAGE("vcl50.bpi"); +USEPACKAGE("TB2K_CB5.bpi"); +USEUNIT("..\TBXSwitcher.pas"); +USEUNIT("..\TBXMDI.pas"); +USEUNIT("..\TBXDefaultTheme.pas"); +USEUNIT("..\TBXStripesTheme.pas"); +USEUNIT("..\TBXOfficeXPTheme.pas"); +USEUNIT("..\TBX.pas"); +USEUNIT("..\TBXUtils.pas"); +USEUNIT("..\TBXExtItems.pas"); +USEUNIT("..\TBXLists.pas"); +USEUNIT("..\TBXUxThemes.pas"); +USEUNIT("..\TBXDkPanels.pas"); +USEUNIT("..\TBXStatusBars.pas"); +USEUNIT("..\TBXThemes.pas"); + +//--------------------------------------------------------------------------- +#pragma package(smart_init) +//--------------------------------------------------------------------------- + +// Package source. +//--------------------------------------------------------------------------- + +#pragma argsused +int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void*) +{ + return 1; +} +//--------------------------------------------------------------------------- diff --git a/official/2.1.6+2.1.beta1/TBX/Packages/tbx_cb5.res b/official/2.1.6+2.1.beta1/TBX/Packages/tbx_cb5.res new file mode 100644 index 0000000..54c0413 Binary files /dev/null and b/official/2.1.6+2.1.beta1/TBX/Packages/tbx_cb5.res differ diff --git a/official/2.1.6+2.1.beta1/TBX/Packages/tbx_cb6.bpk b/official/2.1.6+2.1.beta1/TBX/Packages/tbx_cb6.bpk new file mode 100644 index 0000000..bb836c4 --- /dev/null +++ b/official/2.1.6+2.1.beta1/TBX/Packages/tbx_cb6.bpk @@ -0,0 +1,115 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +[Version Info] +IncludeVerInfo=0 +AutoIncBuild=0 +MajorVer=1 +MinorVer=0 +Release=0 +Build=0 +Debug=0 +PreRelease=0 +Special=0 +Private=0 +DLL=0 +Locale=1033 +CodePage=1252 + +[Debugging] +DebugSourceDirs= + +[Parameters] +RunParams= +Launcher= +UseLauncher=0 +DebugCWD= +HostApplication= +RemoteHost= +RemotePath= +RemoteLauncher= +RemoteCWD= +RemoteDebug=0 + +[Compiler] +ShowInfoMsgs=0 +LinkDebugVcl=0 +LinkCGLIB=0 + +[Linker] +LibPrefix= +LibSuffix= +LibVersion= + + \ No newline at end of file diff --git a/official/2.1.6+2.1.beta1/TBX/Packages/tbx_cb6.cpp b/official/2.1.6+2.1.beta1/TBX/Packages/tbx_cb6.cpp new file mode 100644 index 0000000..bcffbe9 --- /dev/null +++ b/official/2.1.6+2.1.beta1/TBX/Packages/tbx_cb6.cpp @@ -0,0 +1,16 @@ +//--------------------------------------------------------------------------- + +#include +#pragma hdrstop +#pragma package(smart_init) +//--------------------------------------------------------------------------- + +// Package source. +//--------------------------------------------------------------------------- + +#pragma argsused +int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void*) +{ + return 1; +} +//--------------------------------------------------------------------------- diff --git a/official/2.1.6+2.1.beta1/TBX/Packages/tbx_cb6.res b/official/2.1.6+2.1.beta1/TBX/Packages/tbx_cb6.res new file mode 100644 index 0000000..54c0413 Binary files /dev/null and b/official/2.1.6+2.1.beta1/TBX/Packages/tbx_cb6.res differ diff --git a/official/2.1.6+2.1.beta1/TBX/Packages/tbx_d10.bdsproj b/official/2.1.6+2.1.beta1/TBX/Packages/tbx_d10.bdsproj new file mode 100644 index 0000000..8ce0d52 --- /dev/null +++ b/official/2.1.6+2.1.beta1/TBX/Packages/tbx_d10.bdsproj @@ -0,0 +1,658 @@ + + + + + + + + + + + + tbx_d10.dpk + + + 7.0 + + + 8 + 0 + 1 + 1 + 0 + 0 + 1 + 1 + 1 + 0 + 0 + 1 + 0 + 1 + 1 + 1 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 1 + 1 + 1 + True + True + WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE; + + False + + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + False + False + False + True + True + True + True + True + True + + + + 0 + 0 + False + 1 + False + False + False + 16384 + 1048576 + 801112064 + Toolbar2000 -- TBX Extensions (Alex Denisov) + + + + ..\..\Lib\D10 + ..\..\Lib\D10 + ..\..\Lib\D10 + ..\..\Lib\D10 + + + + False + + + + + + False + + + True + False + + + + $00000000 + + + + True + False + 1 + 0 + 0 + 0 + False + False + False + False + False + 3082 + 1252 + + + + + 1.0.0.0 + + + + + + 1.0.0.0 + + + + + diff --git a/official/2.1.6+2.1.beta1/TBX/Packages/tbx_d10.dpk b/official/2.1.6+2.1.beta1/TBX/Packages/tbx_d10.dpk new file mode 100644 index 0000000..5b9d4d1 --- /dev/null +++ b/official/2.1.6+2.1.beta1/TBX/Packages/tbx_d10.dpk @@ -0,0 +1,52 @@ +package tbx_d10; + +{$R *.res} +{$ALIGN 8} +{$ASSERTIONS ON} +{$BOOLEVAL OFF} +{$DEBUGINFO ON} +{$EXTENDEDSYNTAX ON} +{$IMPORTEDDATA ON} +{$IOCHECKS ON} +{$LOCALSYMBOLS ON} +{$LONGSTRINGS ON} +{$OPENSTRINGS ON} +{$OPTIMIZATION ON} +{$OVERFLOWCHECKS OFF} +{$RANGECHECKS OFF} +{$REFERENCEINFO ON} +{$SAFEDIVIDE OFF} +{$STACKFRAMES OFF} +{$TYPEDADDRESS OFF} +{$VARSTRINGCHECKS ON} +{$WRITEABLECONST OFF} +{$MINENUMSIZE 1} +{$IMAGEBASE $2FC00000} +{$DESCRIPTION 'Toolbar2000 -- TBX Extensions (Alex Denisov)'} +{$RUNONLY} +{$IMPLICITBUILD OFF} + +requires + vcl, + tb2k_d10, + rtl; + +contains + TBX in '..\TBX.pas', + TBXThemes in '..\TBXThemes.pas', + TBXDefaultTheme in '..\TBXDefaultTheme.pas', + TBXOfficeXPTheme in '..\TBXOfficeXPTheme.pas', + TBXMDI in '..\TBXMDI.pas', + TBXSwitcher in '..\TBXSwitcher.pas', + TBXExtItems in '..\TBXExtItems.pas', + TBXLists in '..\TBXLists.pas', + TBXUtils in '..\TBXUtils.pas', + TBXUxThemes in '..\TBXUxThemes.pas', + TBXDkPanels in '..\TBXDkPanels.pas', + TBXToolPals in '..\TBXToolPals.pas', + TBXStatusBars in '..\TBXStatusBars.pas', + TBXWhidbeyTheme in '..\TBXWhidbeyTheme.pas', + rmkThemes in '..\rmkThemes.pas', + TBXOffice2003Theme in '..\TBXOffice2003Theme.pas'; + +end. diff --git a/official/2.1.6+2.1.beta1/TBX/Packages/tbx_d10.res b/official/2.1.6+2.1.beta1/TBX/Packages/tbx_d10.res new file mode 100644 index 0000000..86c94e6 Binary files /dev/null and b/official/2.1.6+2.1.beta1/TBX/Packages/tbx_d10.res differ diff --git a/official/2.1.6+2.1.beta1/TBX/Packages/tbx_d4.dpk b/official/2.1.6+2.1.beta1/TBX/Packages/tbx_d4.dpk new file mode 100644 index 0000000..48665ff --- /dev/null +++ b/official/2.1.6+2.1.beta1/TBX/Packages/tbx_d4.dpk @@ -0,0 +1,47 @@ +package tbx_d4; + +{$R *.RES} +{$ALIGN ON} +{$ASSERTIONS ON} +{$BOOLEVAL OFF} +{$DEBUGINFO ON} +{$EXTENDEDSYNTAX ON} +{$IMPORTEDDATA ON} +{$IOCHECKS ON} +{$LOCALSYMBOLS ON} +{$LONGSTRINGS ON} +{$OPENSTRINGS ON} +{$OPTIMIZATION ON} +{$OVERFLOWCHECKS OFF} +{$RANGECHECKS OFF} +{$REFERENCEINFO ON} +{$SAFEDIVIDE OFF} +{$STACKFRAMES OFF} +{$TYPEDADDRESS OFF} +{$VARSTRINGCHECKS ON} +{$WRITEABLECONST OFF} +{$MINENUMSIZE 1} +{$IMAGEBASE $2FC00000} +{$DESCRIPTION 'Toolbar2000 -- TBX Extensions (Alex Denisov)'} +{$IMPLICITBUILD ON} + +requires + tb2k_d4; + +contains + TBX in '..\TBX.pas', + TBXThemes in '..\TBXThemes.pas', + TBXDefaultTheme in '..\TBXDefaultTheme.pas', + TBXStripesTheme in '..\TBXStripesTheme.pas', + TBXOfficeXPTheme in '..\TBXOfficeXPTheme.pas', + TBXMDI in '..\TBXMDI.pas', + TBXSwitcher in '..\TBXSwitcher.pas', + TBXLists in '..\TBXLists.pas', + TBXExtItems in '..\TBXExtItems.pas', + TBXUtils in '..\TBXUtils.pas', + TBXUxThemes in '..\TBXUxThemes.pas', + TBXToolPals in '..\TBXToolPals.pas', + TBXDkPanels in '..\TBXDkPanels.pas', + TBXStatusBars in '..\TBXStatusBars.pas'; + +end. diff --git a/official/2.1.6+2.1.beta1/TBX/Packages/tbx_d4.res b/official/2.1.6+2.1.beta1/TBX/Packages/tbx_d4.res new file mode 100644 index 0000000..54c0413 Binary files /dev/null and b/official/2.1.6+2.1.beta1/TBX/Packages/tbx_d4.res differ diff --git a/official/2.1.6+2.1.beta1/TBX/Packages/tbx_d5.dpk b/official/2.1.6+2.1.beta1/TBX/Packages/tbx_d5.dpk new file mode 100644 index 0000000..c9efe1b --- /dev/null +++ b/official/2.1.6+2.1.beta1/TBX/Packages/tbx_d5.dpk @@ -0,0 +1,47 @@ +package tbx_d5; + +{$R *.RES} +{$ALIGN ON} +{$ASSERTIONS ON} +{$BOOLEVAL OFF} +{$DEBUGINFO ON} +{$EXTENDEDSYNTAX ON} +{$IMPORTEDDATA ON} +{$IOCHECKS ON} +{$LOCALSYMBOLS ON} +{$LONGSTRINGS ON} +{$OPENSTRINGS ON} +{$OPTIMIZATION ON} +{$OVERFLOWCHECKS OFF} +{$RANGECHECKS OFF} +{$REFERENCEINFO ON} +{$SAFEDIVIDE OFF} +{$STACKFRAMES OFF} +{$TYPEDADDRESS OFF} +{$VARSTRINGCHECKS ON} +{$WRITEABLECONST OFF} +{$MINENUMSIZE 1} +{$IMAGEBASE $2FC00000} +{$DESCRIPTION 'Toolbar2000 -- TBX Extensions (Alex Denisov)'} +{$IMPLICITBUILD ON} + +requires + tb2k_d5; + +contains + TBX in '..\TBX.pas', + TBXThemes in '..\TBXThemes.pas', + TBXDefaultTheme in '..\TBXDefaultTheme.pas', + TBXStripesTheme in '..\TBXStripesTheme.pas', + TBXOfficeXPTheme in '..\TBXOfficeXPTheme.pas', + TBXMDI in '..\TBXMDI.pas', + TBXSwitcher in '..\TBXSwitcher.pas', + TBXLists in '..\TBXLists.pas', + TBXExtItems in '..\TBXExtItems.pas', + TBXUtils in '..\TBXUtils.pas', + TBXUxThemes in '..\TBXUxThemes.pas', + TBXDkPanels in '..\TBXDkPanels.pas', + TBXToolPals in '..\TBXToolPals.pas', + TBXStatusBars in '..\TBXStatusBars.pas'; + +end. diff --git a/official/2.1.6+2.1.beta1/TBX/Packages/tbx_d5.res b/official/2.1.6+2.1.beta1/TBX/Packages/tbx_d5.res new file mode 100644 index 0000000..54c0413 Binary files /dev/null and b/official/2.1.6+2.1.beta1/TBX/Packages/tbx_d5.res differ diff --git a/official/2.1.6+2.1.beta1/TBX/Packages/tbx_d6.dpk b/official/2.1.6+2.1.beta1/TBX/Packages/tbx_d6.dpk new file mode 100644 index 0000000..d5c28d2 --- /dev/null +++ b/official/2.1.6+2.1.beta1/TBX/Packages/tbx_d6.dpk @@ -0,0 +1,48 @@ +package tbx_d6; + +{$R *.res} +{$ALIGN 8} +{$ASSERTIONS ON} +{$BOOLEVAL OFF} +{$DEBUGINFO ON} +{$EXTENDEDSYNTAX ON} +{$IMPORTEDDATA ON} +{$IOCHECKS ON} +{$LOCALSYMBOLS ON} +{$LONGSTRINGS ON} +{$OPENSTRINGS ON} +{$OPTIMIZATION ON} +{$OVERFLOWCHECKS OFF} +{$RANGECHECKS OFF} +{$REFERENCEINFO ON} +{$SAFEDIVIDE OFF} +{$STACKFRAMES OFF} +{$TYPEDADDRESS OFF} +{$VARSTRINGCHECKS ON} +{$WRITEABLECONST OFF} +{$MINENUMSIZE 1} +{$IMAGEBASE $2FC00000} +{$DESCRIPTION 'Toolbar2000 -- TBX Extensions (Alex Denisov)'} +{$IMPLICITBUILD ON} + +requires + vcl, + tb2k_d6; + +contains + TBX in '..\TBX.pas', + TBXThemes in '..\TBXThemes.pas', + TBXDefaultTheme in '..\TBXDefaultTheme.pas', + TBXStripesTheme in '..\TBXStripesTheme.pas', + TBXOfficeXPTheme in '..\TBXOfficeXPTheme.pas', + TBXMDI in '..\TBXMDI.pas', + TBXSwitcher in '..\TBXSwitcher.pas', + TBXExtItems in '..\TBXExtItems.pas', + TBXLists in '..\TBXLists.pas', + TBXUtils in '..\TBXUtils.pas', + TBXUxThemes in '..\TBXUxThemes.pas', + TBXDkPanels in '..\TBXDkPanels.pas', + TBXToolPals in '..\TBXToolPals.pas', + TBXStatusBars in '..\TBXStatusBars.pas'; + +end. diff --git a/official/2.1.6+2.1.beta1/TBX/Packages/tbx_d6.res b/official/2.1.6+2.1.beta1/TBX/Packages/tbx_d6.res new file mode 100644 index 0000000..54c0413 Binary files /dev/null and b/official/2.1.6+2.1.beta1/TBX/Packages/tbx_d6.res differ diff --git a/official/2.1.6+2.1.beta1/TBX/Packages/tbx_d7.cfg b/official/2.1.6+2.1.beta1/TBX/Packages/tbx_d7.cfg new file mode 100644 index 0000000..ce76906 --- /dev/null +++ b/official/2.1.6+2.1.beta1/TBX/Packages/tbx_d7.cfg @@ -0,0 +1,45 @@ +-$A8 +-$B- +-$C+ +-$D+ +-$E- +-$F- +-$G+ +-$H+ +-$I+ +-$J- +-$K- +-$L+ +-$M- +-$N+ +-$O+ +-$P+ +-$Q- +-$R- +-$S- +-$T- +-$U- +-$V+ +-$W- +-$X+ +-$YD +-$Z1 +-GD +-cg +-AWinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE; +-H+ +-W+ +-M +-$M16384,1048576 +-K$2FC00000 +-N"..\..\Lib\D7" +-LE"c:\archivos de programa\borland\delphi7\Projects\Bpl" +-LN"c:\archivos de programa\borland\delphi7\Projects\Bpl" +-U"..\..\Source" +-O"..\..\Source" +-I"..\..\Source" +-R"..\..\Source" +-Z +-w-UNSAFE_TYPE +-w-UNSAFE_CODE +-w-UNSAFE_CAST diff --git a/official/2.1.6+2.1.beta1/TBX/Packages/tbx_d7.dof b/official/2.1.6+2.1.beta1/TBX/Packages/tbx_d7.dof new file mode 100644 index 0000000..38f2fa2 --- /dev/null +++ b/official/2.1.6+2.1.beta1/TBX/Packages/tbx_d7.dof @@ -0,0 +1,475 @@ +[FileVersion] +Version=7.0 +[Compiler] +A=8 +B=0 +C=1 +D=1 +E=0 +F=0 +G=1 +H=1 +I=1 +J=0 +K=0 +L=1 +M=0 +N=1 +O=1 +P=1 +Q=0 +R=0 +S=0 +T=0 +U=0 +V=1 +W=0 +X=1 +Y=1 +Z=1 +ShowHints=1 +ShowWarnings=1 +UnitAliases=WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE; +NamespacePrefix= +SymbolDeprecated=1 +SymbolLibrary=1 +SymbolPlatform=1 +UnitLibrary=1 +UnitPlatform=1 +UnitDeprecated=1 +HResultCompat=1 +HidingMember=1 +HiddenVirtual=1 +Garbage=1 +BoundsError=1 +ZeroNilCompat=1 +StringConstTruncated=1 +ForLoopVarVarPar=1 +TypedConstVarPar=1 +AsgToTypedConst=1 +CaseLabelRange=1 +ForVariable=1 +ConstructingAbstract=1 +ComparisonFalse=1 +ComparisonTrue=1 +ComparingSignedUnsigned=1 +CombiningSignedUnsigned=1 +UnsupportedConstruct=1 +FileOpen=1 +FileOpenUnitSrc=1 +BadGlobalSymbol=1 +DuplicateConstructorDestructor=1 +InvalidDirective=1 +PackageNoLink=1 +PackageThreadVar=1 +ImplicitImport=1 +HPPEMITIgnored=1 +NoRetVal=1 +UseBeforeDef=1 +ForLoopVarUndef=1 +UnitNameMismatch=1 +NoCFGFileFound=1 +MessageDirective=1 +ImplicitVariants=1 +UnicodeToLocale=1 +LocaleToUnicode=1 +ImagebaseMultiple=1 +SuspiciousTypecast=1 +PrivatePropAccessor=1 +UnsafeType=0 +UnsafeCode=0 +UnsafeCast=0 +[Linker] +MapFile=3 +OutputObjs=0 +ConsoleApp=1 +DebugInfo=0 +RemoteSymbols=0 +MinStackSize=16384 +MaxStackSize=1048576 +ImageBase=801112064 +ExeDescription=Toolbar2000 -- TBX Extensions (Alex Denisov) +[Directories] +OutputDir= +UnitOutputDir=..\..\Lib\D7 +PackageDLLOutputDir= +PackageDCPOutputDir= +SearchPath=..\..\Source +Packages=vcl;rtl;vclx;indy;inet;xmlrtl;vclie;inetdbbde;inetdbxpress;dbrtl;dsnap;dsnapcon;vcldb;soaprtl;VclSmp;dbexpress;dbxcds;inetdb;bdertl;vcldbx;webdsnap;websnap;adortl;ibxpress;teeui;teedb;tee;dss;visualclx;visualdbclx;vclactnband;vclshlctrls;dclOfficeXP;CEToolsPkgd7;FR7;FRIBX7;Hydra_Core_D7;Hydra_RO_D7;fqb70;frx7;frxADO7;frxBDE7;frxDB7;frxDBX7;frxe7;frxIBX7;fs7;fsADO7;fsBDE7;fsDB7;fsIBX7;DataAbstract_Core_D7;DataAbstract_IDE_D7;dxComnD7;dxsbD7;dxBarD7;dxBarDBNavD7;dxBarExtDBItemsD7;dxBarExtItemsD7;dxDockingD7;cxEditorsVCLD7;cxLibraryVCLD7;dxThemeD7;cxDataD7;cxExtEditorsVCLD7;cxGridVCLD7;cxPageControlVCLD7;cxSchedulerVCLD7;cxTreeListVCLD7;dxPSCoreD7 +Conditionals= +DebugSourceDirs= +UsePackages=0 +[Parameters] +RunParams= +HostApplication= +Launcher= +UseLauncher=0 +DebugCWD= +[Language] +ActiveLang= +ProjectLang= +RootDir=C:\Archivos de programa\Borland\Delphi7\Bin\ +[Version Info] +IncludeVerInfo=1 +AutoIncBuild=0 +MajorVer=1 +MinorVer=0 +Release=0 +Build=0 +Debug=0 +PreRelease=0 +Special=0 +Private=0 +DLL=0 +Locale=3082 +CodePage=1252 +[Version Info Keys] +CompanyName= +FileDescription= +FileVersion=1.0.0.0 +InternalName= +LegalCopyright= +LegalTrademarks= +OriginalFilename= +ProductName= +ProductVersion=1.0.0.0 +Comments= +[Excluded Packages] +C:\Archivos de programa\Borland\Delphi7\Projects\Bpl\DJclVcl70.bpl=JEDI Code Library VCL package for Delphi 7 +C:\Archivos de programa\Borland\Delphi7\Projects\Bpl\DJcl70.bpl=JEDI Code Library RTL package for Delphi 7 +C:\WINDOWS\system32\fqb70.bpl=FastQueryBuilder 1.01 +C:\Archivos de programa\Borland\Delphi7\Projects\Bpl\dxPSCoreD7.bpl=ExpressPrinting System (core 3.1) by Developer Express Inc. +C:\Archivos de programa\Borland\Delphi7\Projects\Bpl\dxComnD7.bpl=ExpressCommonLibrary by Developer Express Inc. +C:\Archivos de programa\Borland\Delphi7\Projects\Bpl\dxBarDBNavD7.bpl=ExpressBars DBNavigator by Developer Express Inc. +c:\archivos de programa\borland\delphi7\Projects\Bpl\EasyResizeD7.bpl=EasyResize for Delphi 7 +c:\archivos de programa\borland\delphi7\Projects\Bpl\RodaxFrameD7.bpl=Frames Acana (D7) +[HistoryLists\hlUnitAliases] +Count=1 +Item0=WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE; +[HistoryLists\hlUnitOutputDirectory] +Count=2 +Item0=..\..\Lib\D7 +Item1=..\Lib\D7 +[HistoryLists\hlBPLOutput] +Count=1 +Item0=..\Lib\D7 +[HistoryLists\hlDCPOutput] +Count=1 +Item0=..\Lib\D7 +[Exception Log] +EurekaLog Version=501 +Activate=1 +Activate Handle=1 +Save Log File=1 +Foreground Tab=0 +Freeze Activate=0 +Freeze Timeout=60 +Freeze Message=The application seems to be frozen. +SMTP From=eurekalog@email.com +SMTP Host= +SMTP Port=25 +SMTP UserID= +SMTP Password= +Append to Log=0 +Show TerminateBtn=1 +TerminateBtn Operation=1 +Errors Number=32 +Errors Terminate=3 +Email Address= +Email Object= +Email Send Options=0 +Output Path= +Encrypt Password= +AutoCloseDialogSecs=0 +WebSendMode=0 +SupportULR= +HTMLLayout Count=15 +HTMLLine0="%3Chtml%3E" +HTMLLine1=" %3Chead%3E" +HTMLLine2=" %3C/head%3E" +HTMLLine3=" %3Cbody TopMargin=10 LeftMargin=10%3E" +HTMLLine4=" %3Ctable width="100%%" border="0"%3E" +HTMLLine5=" %3Ctr%3E" +HTMLLine6=" %3Ctd nowrap%3E" +HTMLLine7=" %3Cfont face="Lucida Console, Courier" size="2"%3E" +HTMLLine8=" %3C%%HTML_TAG%%%3E" +HTMLLine9=" %3C/font%3E" +HTMLLine10=" %3C/td%3E" +HTMLLine11=" %3C/tr%3E" +HTMLLine12=" %3C/table%3E" +HTMLLine13=" %3C/body%3E" +HTMLLine14="%3C/html%3E" +AutoCrashOperation=1 +AutoCrashNumber=10 +AutoCrashMinutes=1 +WebURL= +WebUserID= +WebPassword= +WebPort=0 +AttachedFiles= +Count=0 +EMail Message Line Count=0 +loNoDuplicateErrors=0 +loAppendReproduceText=0 +loDeleteLogAtVersionChange=0 +loAddComputerNameInLogFileName=0 +loSaveModulesSection=1 +loSaveCPUSection=1 +soAppStartDate=1 +soAppName=1 +soAppVersionNumber=1 +soAppParameters=1 +soAppCompilationDate=1 +soExcDate=1 +soExcAddress=1 +soExcModule=1 +soExcType=1 +soExcMessage=1 +soActCtlsFormClass=1 +soActCtlsFormText=1 +soActCtlsControlClass=1 +soActCtlsControlText=1 +soCmpName=1 +soCmpUser=1 +soCmpTotalMemory=1 +soCmpFreeMemory=1 +soCmpTotalDisk=1 +soCmpFreeDisk=1 +soCmpSysUpTime=1 +soCmpProcessor=1 +soCmpDisplayMode=1 +soOSType=1 +soOSBuildN=1 +soOSUpdate=1 +soOSLanguage=1 +soNetIP=1 +soNetSubmask=1 +soNetGateway=1 +soNetDNS1=1 +soNetDNS2=1 +soNetDHCP=1 +sndShowSendDialog=1 +sndShowSuccessFailureMsg=0 +sndSendEntireLog=0 +sndSendXMLLogCopy=0 +sndSendScreenshot=1 +sndUseOnlyActiveWindow=0 +sndSendLastHTMLPage=1 +sndSendInSeparatedThread=0 +sndAddDateInFileName=0 +sndCompressAllFiles=0 +edoShowExceptionDialog=1 +edoSendEmailChecked=1 +edoAttachScreenshotChecked=1 +edoShowCopyToClipOption=1 +edoShowDetailsButton=1 +edoShowInDetailedMode=0 +edoShowInTopMostMode=0 +edoUseEurekaLogLookAndFeel=0 +csoShowDLLs=1 +csoShowBPLs=1 +csoShowBorlandThreads=1 +csoShowWindowsThreads=1 +csoShowProcedureOffset=0 +boActivateCrashDetection=0 +boPauseBorlandThreads=0 +boDoNotPauseMainThread=0 +boPauseWindowsThreads=0 +boUseMainModuleOptions=1 +boCopyLogInCaseOfError=1 +boSaveCompressedCopyInCaseOfError=0 +Count mtInformationMsgCaption=1 +mtInformationMsgCaption0="Information." +Count mtQuestionMsgCaption=1 +mtQuestionMsgCaption0="Question." +Count mtDialog_Caption=1 +mtDialog_Caption0="Error." +Count mtDialog_ErrorMsgCaption=2 +mtDialog_ErrorMsgCaption0="An error has occurred during program execution." +mtDialog_ErrorMsgCaption1="Please read the following information for further details." +Count mtDialog_GeneralCaption=1 +mtDialog_GeneralCaption0="General" +Count mtDialog_GeneralHeader=1 +mtDialog_GeneralHeader0="General Information" +Count mtDialog_CallStackCaption=1 +mtDialog_CallStackCaption0="Call Stack" +Count mtDialog_CallStackHeader=1 +mtDialog_CallStackHeader0="Call Stack Information" +Count mtDialog_ModulesCaption=1 +mtDialog_ModulesCaption0="Modules" +Count mtDialog_ModulesHeader=1 +mtDialog_ModulesHeader0="Modules Information" +Count mtDialog_CPUCaption=1 +mtDialog_CPUCaption0="CPU" +Count mtDialog_CPUHeader=1 +mtDialog_CPUHeader0="CPU Information" +Count mtDialog_CustomDataCaption=1 +mtDialog_CustomDataCaption0="Other" +Count mtDialog_CustomDataHeader=1 +mtDialog_CustomDataHeader0="Other Information" +Count mtDialog_OKButtonCaption=1 +mtDialog_OKButtonCaption0="&OK" +Count mtDialog_TerminateButtonCaption=1 +mtDialog_TerminateButtonCaption0="&Terminate" +Count mtDialog_RestartButtonCaption=1 +mtDialog_RestartButtonCaption0="&Restart" +Count mtDialog_DetailsButtonCaption=1 +mtDialog_DetailsButtonCaption0="&Details" +Count mtDialog_SendMessage=1 +mtDialog_SendMessage0="&Send this error via Internet" +Count mtDialog_ScreenshotMessage=1 +mtDialog_ScreenshotMessage0="&Attach a Screenshot image" +Count mtDialog_CopyMessage=1 +mtDialog_CopyMessage0="&Copy to Clipboard" +Count mtDialog_SupportMessage=1 +mtDialog_SupportMessage0="Go to the Support Page" +Count mtLog_AppHeader=1 +mtLog_AppHeader0="Application" +Count mtLog_AppStartDate=1 +mtLog_AppStartDate0="Start Date" +Count mtLog_AppName=1 +mtLog_AppName0="Name/Description" +Count mtLog_AppVersionNumber=1 +mtLog_AppVersionNumber0="Version Number" +Count mtLog_AppParameters=1 +mtLog_AppParameters0="Parameters" +Count mtLog_AppCompilationDate=1 +mtLog_AppCompilationDate0="Compilation Date" +Count mtLog_ExcHeader=1 +mtLog_ExcHeader0="Exception" +Count mtLog_ExcDate=1 +mtLog_ExcDate0="Date" +Count mtLog_ExcAddress=1 +mtLog_ExcAddress0="Address" +Count mtLog_ExcModule=1 +mtLog_ExcModule0="Module" +Count mtLog_ExcType=1 +mtLog_ExcType0="Type" +Count mtLog_ExcMessage=1 +mtLog_ExcMessage0="Message" +Count mtLog_ActCtrlsHeader=1 +mtLog_ActCtrlsHeader0="Active Controls" +Count mtLog_ActCtrlsFormClass=1 +mtLog_ActCtrlsFormClass0="Form Class" +Count mtLog_ActCtrlsFormText=1 +mtLog_ActCtrlsFormText0="Form Text" +Count mtLog_ActCtrlsControlClass=1 +mtLog_ActCtrlsControlClass0="Control Class" +Count mtLog_ActCtrlsControlText=1 +mtLog_ActCtrlsControlText0="Control Text" +Count mtLog_CmpHeader=1 +mtLog_CmpHeader0="Computer" +Count mtLog_CmpName=1 +mtLog_CmpName0="Name" +Count mtLog_CmpUser=1 +mtLog_CmpUser0="User" +Count mtLog_CmpTotalMemory=1 +mtLog_CmpTotalMemory0="Total Memory" +Count mtLog_CmpFreeMemory=1 +mtLog_CmpFreeMemory0="Free Memory" +Count mtLog_CmpTotalDisk=1 +mtLog_CmpTotalDisk0="Total Disk" +Count mtLog_CmpFreeDisk=1 +mtLog_CmpFreeDisk0="Free Disk" +Count mtLog_CmpSystemUpTime=1 +mtLog_CmpSystemUpTime0="System Up Time" +Count mtLog_CmpProcessor=1 +mtLog_CmpProcessor0="Processor" +Count mtLog_CmpDisplayMode=1 +mtLog_CmpDisplayMode0="Display Mode" +Count mtLog_OSHeader=1 +mtLog_OSHeader0="Operating System" +Count mtLog_OSType=1 +mtLog_OSType0="Type" +Count mtLog_OSBuildN=1 +mtLog_OSBuildN0="Build #" +Count mtLog_OSUpdate=1 +mtLog_OSUpdate0="Update" +Count mtLog_OSLanguage=1 +mtLog_OSLanguage0="Language" +Count mtLog_NetHeader=1 +mtLog_NetHeader0="Network" +Count mtLog_NetIP=1 +mtLog_NetIP0="IP Address" +Count mtLog_NetSubmask=1 +mtLog_NetSubmask0="Submask" +Count mtLog_NetGateway=1 +mtLog_NetGateway0="Gateway" +Count mtLog_NetDNS1=1 +mtLog_NetDNS10="DNS 1" +Count mtLog_NetDNS2=1 +mtLog_NetDNS20="DNS 2" +Count mtLog_NetDHCP=1 +mtLog_NetDHCP0="DHCP" +Count mtLog_CustInfoHeader=1 +mtLog_CustInfoHeader0="Custom Information" +Count mtCallStack_Address=1 +mtCallStack_Address0="Address" +Count mtCallStack_Name=1 +mtCallStack_Name0="Module" +Count mtCallStack_Unit=1 +mtCallStack_Unit0="Unit" +Count mtCallStack_Class=1 +mtCallStack_Class0="Class" +Count mtCallStack_Procedure=1 +mtCallStack_Procedure0="Procedure/Method" +Count mtCallStack_Line=1 +mtCallStack_Line0="Line" +Count mtCallStack_MainThread=1 +mtCallStack_MainThread0="Main" +Count mtCallStack_ExceptionThread=1 +mtCallStack_ExceptionThread0="Exception Thread" +Count mtCallStack_RunningThread=1 +mtCallStack_RunningThread0="Running Thread" +Count mtCallStack_CallingThread=1 +mtCallStack_CallingThread0="Calling Thread" +Count mtCallStack_ThreadID=1 +mtCallStack_ThreadID0="ID" +Count mtCallStack_ThreadPriority=1 +mtCallStack_ThreadPriority0="Priority" +Count mtCallStack_ThreadClass=1 +mtCallStack_ThreadClass0="Class" +Count mtSendDialog_Caption=1 +mtSendDialog_Caption0="Send." +Count mtSendDialog_Message=1 +mtSendDialog_Message0="Message" +Count mtSendDialog_Resolving=1 +mtSendDialog_Resolving0="Resolving DNS..." +Count mtSendDialog_Connecting=1 +mtSendDialog_Connecting0="Connecting with server..." +Count mtSendDialog_Connected=1 +mtSendDialog_Connected0="Connected with server." +Count mtSendDialog_Sending=1 +mtSendDialog_Sending0="Sending message..." +Count mtReproduceDialog_Caption=1 +mtReproduceDialog_Caption0="Request" +Count mtReproduceDialog_Request=1 +mtReproduceDialog_Request0="Please describe the steps to reproduce the error:" +Count mtReproduceDialog_OKButtonCaption=1 +mtReproduceDialog_OKButtonCaption0="&OK" +Count mtModules_Handle=1 +mtModules_Handle0="Handle" +Count mtModules_Name=1 +mtModules_Name0="Name" +Count mtModules_Description=1 +mtModules_Description0="Description" +Count mtModules_Version=1 +mtModules_Version0="Version" +Count mtModules_Size=1 +mtModules_Size0="Size" +Count mtModules_LastModified=1 +mtModules_LastModified0="Modified" +Count mtModules_Path=1 +mtModules_Path0="Path" +Count mtCPU_Registers=1 +mtCPU_Registers0="Registers" +Count mtCPU_Stack=1 +mtCPU_Stack0="Stack" +Count mtCPU_MemoryDump=1 +mtCPU_MemoryDump0="Memory Dump" +Count mtSend_SuccessMsg=1 +mtSend_SuccessMsg0="The message was sent successfully." +Count mtSend_FailureMsg=1 +mtSend_FailureMsg0="Sorry, sending the message didn't work." + + diff --git a/official/2.1.6+2.1.beta1/TBX/Packages/tbx_d7.dpk b/official/2.1.6+2.1.beta1/TBX/Packages/tbx_d7.dpk new file mode 100644 index 0000000..d31ff9c --- /dev/null +++ b/official/2.1.6+2.1.beta1/TBX/Packages/tbx_d7.dpk @@ -0,0 +1,51 @@ +package tbx_d7; + +{$R *.res} +{$ALIGN 8} +{$ASSERTIONS ON} +{$BOOLEVAL OFF} +{$DEBUGINFO ON} +{$EXTENDEDSYNTAX ON} +{$IMPORTEDDATA ON} +{$IOCHECKS ON} +{$LOCALSYMBOLS ON} +{$LONGSTRINGS ON} +{$OPENSTRINGS ON} +{$OPTIMIZATION ON} +{$OVERFLOWCHECKS OFF} +{$RANGECHECKS OFF} +{$REFERENCEINFO ON} +{$SAFEDIVIDE OFF} +{$STACKFRAMES OFF} +{$TYPEDADDRESS OFF} +{$VARSTRINGCHECKS ON} +{$WRITEABLECONST OFF} +{$MINENUMSIZE 1} +{$IMAGEBASE $2FC00000} +{$DESCRIPTION 'Toolbar2000 -- TBX Extensions (Alex Denisov)'} +{$IMPLICITBUILD OFF} + +requires + vcl, + tb2k_d7, + rtl; + +contains + TBX in '..\TBX.pas', + TBXThemes in '..\TBXThemes.pas', + TBXDefaultTheme in '..\TBXDefaultTheme.pas', + TBXOfficeXPTheme in '..\TBXOfficeXPTheme.pas', + TBXMDI in '..\TBXMDI.pas', + TBXSwitcher in '..\TBXSwitcher.pas', + TBXExtItems in '..\TBXExtItems.pas', + TBXLists in '..\TBXLists.pas', + TBXUtils in '..\TBXUtils.pas', + TBXUxThemes in '..\TBXUxThemes.pas', + TBXDkPanels in '..\TBXDkPanels.pas', + TBXToolPals in '..\TBXToolPals.pas', + TBXStatusBars in '..\TBXStatusBars.pas', + TBXWhidbeyTheme in '..\TBXWhidbeyTheme.pas', + rmkThemes in '..\rmkThemes.pas', + TBXOffice2003Theme in '..\TBXOffice2003Theme.pas'; + +end. diff --git a/official/2.1.6+2.1.beta1/TBX/Packages/tbx_d7.drc b/official/2.1.6+2.1.beta1/TBX/Packages/tbx_d7.drc new file mode 100644 index 0000000..a5d5271 --- /dev/null +++ b/official/2.1.6+2.1.beta1/TBX/Packages/tbx_d7.drc @@ -0,0 +1,14 @@ +/* VER150 + Generated by the Borland Delphi Pascal Compiler + because -GD or --drc was supplied to the compiler. + + This file contains compiler-generated resources that + were bound to the executable. + If this file is empty, then no compiler-generated + resources were bound to the produced executable. +*/ + +STRINGTABLE +BEGIN +END + diff --git a/official/2.1.6+2.1.beta1/TBX/Packages/tbx_d7.res b/official/2.1.6+2.1.beta1/TBX/Packages/tbx_d7.res new file mode 100644 index 0000000..528d18b Binary files /dev/null and b/official/2.1.6+2.1.beta1/TBX/Packages/tbx_d7.res differ diff --git a/official/2.1.6+2.1.beta1/TBX/Packages/tbxdsgn_cb5.bpk b/official/2.1.6+2.1.beta1/TBX/Packages/tbxdsgn_cb5.bpk new file mode 100644 index 0000000..22734bc --- /dev/null +++ b/official/2.1.6+2.1.beta1/TBX/Packages/tbxdsgn_cb5.bpk @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/official/2.1.6+2.1.beta1/TBX/Packages/tbxdsgn_cb5.cpp b/official/2.1.6+2.1.beta1/TBX/Packages/tbxdsgn_cb5.cpp new file mode 100644 index 0000000..9648bf6 --- /dev/null +++ b/official/2.1.6+2.1.beta1/TBX/Packages/tbxdsgn_cb5.cpp @@ -0,0 +1,25 @@ +//--------------------------------------------------------------------------- + +#include +#pragma hdrstop +USERES("tbxdsgn_cb5.res"); +USEPACKAGE("vcl50.bpi"); +USEUNIT("..\TBXStrEdit.pas"); +USEUNIT("..\TBXReg.pas"); +USERES("..\TBXReg.dcr"); +USEPACKAGE("tb2k_cb5.bpi"); +USEPACKAGE("tb2kdsgn_cb5.bpi"); +USEPACKAGE("tbx_cb5.bpi"); +//--------------------------------------------------------------------------- +#pragma package(smart_init) +//--------------------------------------------------------------------------- + +// Package source. +//--------------------------------------------------------------------------- + +#pragma argsused +int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void*) +{ + return 1; +} +//--------------------------------------------------------------------------- diff --git a/official/2.1.6+2.1.beta1/TBX/Packages/tbxdsgn_cb5.res b/official/2.1.6+2.1.beta1/TBX/Packages/tbxdsgn_cb5.res new file mode 100644 index 0000000..3a603f1 Binary files /dev/null and b/official/2.1.6+2.1.beta1/TBX/Packages/tbxdsgn_cb5.res differ diff --git a/official/2.1.6+2.1.beta1/TBX/Packages/tbxdsgn_cb6.bpk b/official/2.1.6+2.1.beta1/TBX/Packages/tbxdsgn_cb6.bpk new file mode 100644 index 0000000..c98de3a --- /dev/null +++ b/official/2.1.6+2.1.beta1/TBX/Packages/tbxdsgn_cb6.bpk @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/official/2.1.6+2.1.beta1/TBX/Packages/tbxdsgn_cb6.cpp b/official/2.1.6+2.1.beta1/TBX/Packages/tbxdsgn_cb6.cpp new file mode 100644 index 0000000..287da75 --- /dev/null +++ b/official/2.1.6+2.1.beta1/TBX/Packages/tbxdsgn_cb6.cpp @@ -0,0 +1,17 @@ +//--------------------------------------------------------------------------- + +#include +#pragma hdrstop +//--------------------------------------------------------------------------- +#pragma package(smart_init) +//--------------------------------------------------------------------------- + +// Package source. +//--------------------------------------------------------------------------- + +#pragma argsused +int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void*) +{ + return 1; +} +//--------------------------------------------------------------------------- diff --git a/official/2.1.6+2.1.beta1/TBX/Packages/tbxdsgn_cb6.res b/official/2.1.6+2.1.beta1/TBX/Packages/tbxdsgn_cb6.res new file mode 100644 index 0000000..392d1d7 Binary files /dev/null and b/official/2.1.6+2.1.beta1/TBX/Packages/tbxdsgn_cb6.res differ diff --git a/official/2.1.6+2.1.beta1/TBX/Packages/tbxdsgn_d10.bdsproj b/official/2.1.6+2.1.beta1/TBX/Packages/tbxdsgn_d10.bdsproj new file mode 100644 index 0000000..cfa3b80 --- /dev/null +++ b/official/2.1.6+2.1.beta1/TBX/Packages/tbxdsgn_d10.bdsproj @@ -0,0 +1,658 @@ + + + + + + + + + + + + tbxdsgn_d10.dpk + + + 7.0 + + + 8 + 0 + 1 + 1 + 0 + 0 + 1 + 1 + 1 + 0 + 0 + 1 + 0 + 1 + 1 + 1 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 1 + 1 + 1 + True + True + WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE; + + False + + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + False + False + False + True + True + True + True + True + True + + + + 0 + 0 + False + 1 + False + False + False + 16384 + 1048576 + 796917760 + Toolbar2000 -- TBX Extensions Design Package (Alex Denisov) + + + + ..\..\Lib\D10 + ..\..\Lib\D10 + ..\..\Lib\D10 + ..\..\Lib\D10 + + + + False + + + + + + False + + + True + False + + + + $00000000 + + + + True + False + 1 + 0 + 0 + 0 + False + False + False + False + False + 3082 + 1252 + + + + + 1.0.0.0 + + + + + + 1.0.0.0 + + + + + diff --git a/official/2.1.6+2.1.beta1/TBX/Packages/tbxdsgn_d10.dpk b/official/2.1.6+2.1.beta1/TBX/Packages/tbxdsgn_d10.dpk new file mode 100644 index 0000000..122351b --- /dev/null +++ b/official/2.1.6+2.1.beta1/TBX/Packages/tbxdsgn_d10.dpk @@ -0,0 +1,40 @@ +package tbxdsgn_d10; + +{$R *.res} +{$R '..\TBXReg.dcr'} +{$ALIGN 8} +{$ASSERTIONS ON} +{$BOOLEVAL OFF} +{$DEBUGINFO ON} +{$EXTENDEDSYNTAX ON} +{$IMPORTEDDATA ON} +{$IOCHECKS ON} +{$LOCALSYMBOLS ON} +{$LONGSTRINGS ON} +{$OPENSTRINGS ON} +{$OPTIMIZATION ON} +{$OVERFLOWCHECKS OFF} +{$RANGECHECKS OFF} +{$REFERENCEINFO ON} +{$SAFEDIVIDE OFF} +{$STACKFRAMES OFF} +{$TYPEDADDRESS OFF} +{$VARSTRINGCHECKS ON} +{$WRITEABLECONST OFF} +{$MINENUMSIZE 1} +{$IMAGEBASE $2F800000} +{$DESCRIPTION 'Toolbar2000 -- TBX Extensions Design Package (Alex Denisov)'} +{$DESIGNONLY} +{$IMPLICITBUILD ON} + +requires + tb2k_d10, + tb2kdsgn_d10, + tbx_d10, + vcl; + +contains + TBXStrEdit in '..\TBXStrEdit.pas', + TBXReg in '..\TBXReg.pas'; + +end. diff --git a/official/2.1.6+2.1.beta1/TBX/Packages/tbxdsgn_d10.res b/official/2.1.6+2.1.beta1/TBX/Packages/tbxdsgn_d10.res new file mode 100644 index 0000000..86c94e6 Binary files /dev/null and b/official/2.1.6+2.1.beta1/TBX/Packages/tbxdsgn_d10.res differ diff --git a/official/2.1.6+2.1.beta1/TBX/Packages/tbxdsgn_d4.dpk b/official/2.1.6+2.1.beta1/TBX/Packages/tbxdsgn_d4.dpk new file mode 100644 index 0000000..95e5193 --- /dev/null +++ b/official/2.1.6+2.1.beta1/TBX/Packages/tbxdsgn_d4.dpk @@ -0,0 +1,39 @@ +package tbxdsgn_d5; + +{$R *.RES} +{$R '..\TBXReg.dcr'} +{$ALIGN ON} +{$ASSERTIONS ON} +{$BOOLEVAL OFF} +{$DEBUGINFO ON} +{$EXTENDEDSYNTAX ON} +{$IMPORTEDDATA ON} +{$IOCHECKS ON} +{$LOCALSYMBOLS ON} +{$LONGSTRINGS ON} +{$OPENSTRINGS ON} +{$OPTIMIZATION ON} +{$OVERFLOWCHECKS OFF} +{$RANGECHECKS OFF} +{$REFERENCEINFO ON} +{$SAFEDIVIDE OFF} +{$STACKFRAMES OFF} +{$TYPEDADDRESS OFF} +{$VARSTRINGCHECKS ON} +{$WRITEABLECONST OFF} +{$MINENUMSIZE 1} +{$IMAGEBASE $2F800000} +{$DESCRIPTION 'Toolbar2000 -- TBX Extensions Design Package (Alex Denisov)'} +{$DESIGNONLY} +{$IMPLICITBUILD ON} + +requires + tb2k_d4, + tb2kdsgn_d4, + tbx_d4; + +contains + TBXReg in '..\TBXReg.pas', + TBXStrEdit in '..\TBXStrEdit.pas'; + +end. diff --git a/official/2.1.6+2.1.beta1/TBX/Packages/tbxdsgn_d4.res b/official/2.1.6+2.1.beta1/TBX/Packages/tbxdsgn_d4.res new file mode 100644 index 0000000..54c0413 Binary files /dev/null and b/official/2.1.6+2.1.beta1/TBX/Packages/tbxdsgn_d4.res differ diff --git a/official/2.1.6+2.1.beta1/TBX/Packages/tbxdsgn_d5.dpk b/official/2.1.6+2.1.beta1/TBX/Packages/tbxdsgn_d5.dpk new file mode 100644 index 0000000..af87b19 --- /dev/null +++ b/official/2.1.6+2.1.beta1/TBX/Packages/tbxdsgn_d5.dpk @@ -0,0 +1,39 @@ +package tbxdsgn_d5; + +{$R *.RES} +{$R '..\TBXReg.dcr'} +{$ALIGN ON} +{$ASSERTIONS ON} +{$BOOLEVAL OFF} +{$DEBUGINFO ON} +{$EXTENDEDSYNTAX ON} +{$IMPORTEDDATA ON} +{$IOCHECKS ON} +{$LOCALSYMBOLS ON} +{$LONGSTRINGS ON} +{$OPENSTRINGS ON} +{$OPTIMIZATION ON} +{$OVERFLOWCHECKS OFF} +{$RANGECHECKS OFF} +{$REFERENCEINFO ON} +{$SAFEDIVIDE OFF} +{$STACKFRAMES OFF} +{$TYPEDADDRESS OFF} +{$VARSTRINGCHECKS ON} +{$WRITEABLECONST OFF} +{$MINENUMSIZE 1} +{$IMAGEBASE $2F800000} +{$DESCRIPTION 'Toolbar2000 -- TBX Extensions Design Package (Alex Denisov)'} +{$DESIGNONLY} +{$IMPLICITBUILD ON} + +requires + tb2k_d5, + tb2kdsgn_d5, + tbx_d5; + +contains + TBXReg in '..\TBXReg.pas', + TBXStrEdit in '..\TBXStrEdit.pas'; + +end. diff --git a/official/2.1.6+2.1.beta1/TBX/Packages/tbxdsgn_d5.res b/official/2.1.6+2.1.beta1/TBX/Packages/tbxdsgn_d5.res new file mode 100644 index 0000000..54c0413 Binary files /dev/null and b/official/2.1.6+2.1.beta1/TBX/Packages/tbxdsgn_d5.res differ diff --git a/official/2.1.6+2.1.beta1/TBX/Packages/tbxdsgn_d6.dpk b/official/2.1.6+2.1.beta1/TBX/Packages/tbxdsgn_d6.dpk new file mode 100644 index 0000000..a3f17a6 --- /dev/null +++ b/official/2.1.6+2.1.beta1/TBX/Packages/tbxdsgn_d6.dpk @@ -0,0 +1,40 @@ +package tbxdsgn_d6; + +{$R *.res} +{$R '..\TBXReg.dcr'} +{$ALIGN 8} +{$ASSERTIONS ON} +{$BOOLEVAL OFF} +{$DEBUGINFO ON} +{$EXTENDEDSYNTAX ON} +{$IMPORTEDDATA ON} +{$IOCHECKS ON} +{$LOCALSYMBOLS ON} +{$LONGSTRINGS ON} +{$OPENSTRINGS ON} +{$OPTIMIZATION ON} +{$OVERFLOWCHECKS OFF} +{$RANGECHECKS OFF} +{$REFERENCEINFO ON} +{$SAFEDIVIDE OFF} +{$STACKFRAMES OFF} +{$TYPEDADDRESS OFF} +{$VARSTRINGCHECKS ON} +{$WRITEABLECONST OFF} +{$MINENUMSIZE 1} +{$IMAGEBASE $2F800000} +{$DESCRIPTION 'Toolbar2000 -- TBX Extensions Design Package (Alex Denisov)'} +{$DESIGNONLY} +{$IMPLICITBUILD ON} + +requires + tb2k_d6, + tb2kdsgn_d6, + tbx_d6, + vcl; + +contains + TBXStrEdit in '..\TBXStrEdit.pas', + TBXReg in '..\TBXReg.pas'; + +end. diff --git a/official/2.1.6+2.1.beta1/TBX/Packages/tbxdsgn_d6.res b/official/2.1.6+2.1.beta1/TBX/Packages/tbxdsgn_d6.res new file mode 100644 index 0000000..54c0413 Binary files /dev/null and b/official/2.1.6+2.1.beta1/TBX/Packages/tbxdsgn_d6.res differ diff --git a/official/2.1.6+2.1.beta1/TBX/Packages/tbxdsgn_d7.cfg b/official/2.1.6+2.1.beta1/TBX/Packages/tbxdsgn_d7.cfg new file mode 100644 index 0000000..158b5cd --- /dev/null +++ b/official/2.1.6+2.1.beta1/TBX/Packages/tbxdsgn_d7.cfg @@ -0,0 +1,44 @@ +-$A8 +-$B- +-$C+ +-$D+ +-$E- +-$F- +-$G+ +-$H+ +-$I+ +-$J- +-$K- +-$L+ +-$M- +-$N+ +-$O+ +-$P+ +-$Q- +-$R- +-$S- +-$T- +-$U- +-$V+ +-$W- +-$X+ +-$YD +-$Z1 +-GD +-cg +-AWinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE; +-H+ +-W+ +-M +-$M16384,1048576 +-K$2F800000 +-N"..\..\Lib\D7" +-LE"c:\archivos de programa\borland\delphi7\Projects\Bpl" +-LN"c:\archivos de programa\borland\delphi7\Projects\Bpl" +-U"..\..\Source" +-O"..\..\Source" +-I"..\..\Source" +-R"..\..\Source" +-w-UNSAFE_TYPE +-w-UNSAFE_CODE +-w-UNSAFE_CAST diff --git a/official/2.1.6+2.1.beta1/TBX/Packages/tbxdsgn_d7.dof b/official/2.1.6+2.1.beta1/TBX/Packages/tbxdsgn_d7.dof new file mode 100644 index 0000000..f9fd929 --- /dev/null +++ b/official/2.1.6+2.1.beta1/TBX/Packages/tbxdsgn_d7.dof @@ -0,0 +1,474 @@ +[FileVersion] +Version=7.0 +[Compiler] +A=8 +B=0 +C=1 +D=1 +E=0 +F=0 +G=1 +H=1 +I=1 +J=0 +K=0 +L=1 +M=0 +N=1 +O=1 +P=1 +Q=0 +R=0 +S=0 +T=0 +U=0 +V=1 +W=0 +X=1 +Y=1 +Z=1 +ShowHints=1 +ShowWarnings=1 +UnitAliases=WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE; +NamespacePrefix= +SymbolDeprecated=1 +SymbolLibrary=1 +SymbolPlatform=1 +UnitLibrary=1 +UnitPlatform=1 +UnitDeprecated=1 +HResultCompat=1 +HidingMember=1 +HiddenVirtual=1 +Garbage=1 +BoundsError=1 +ZeroNilCompat=1 +StringConstTruncated=1 +ForLoopVarVarPar=1 +TypedConstVarPar=1 +AsgToTypedConst=1 +CaseLabelRange=1 +ForVariable=1 +ConstructingAbstract=1 +ComparisonFalse=1 +ComparisonTrue=1 +ComparingSignedUnsigned=1 +CombiningSignedUnsigned=1 +UnsupportedConstruct=1 +FileOpen=1 +FileOpenUnitSrc=1 +BadGlobalSymbol=1 +DuplicateConstructorDestructor=1 +InvalidDirective=1 +PackageNoLink=1 +PackageThreadVar=1 +ImplicitImport=1 +HPPEMITIgnored=1 +NoRetVal=1 +UseBeforeDef=1 +ForLoopVarUndef=1 +UnitNameMismatch=1 +NoCFGFileFound=1 +MessageDirective=1 +ImplicitVariants=1 +UnicodeToLocale=1 +LocaleToUnicode=1 +ImagebaseMultiple=1 +SuspiciousTypecast=1 +PrivatePropAccessor=1 +UnsafeType=0 +UnsafeCode=0 +UnsafeCast=0 +[Linker] +MapFile=3 +OutputObjs=0 +ConsoleApp=1 +DebugInfo=0 +RemoteSymbols=0 +MinStackSize=16384 +MaxStackSize=1048576 +ImageBase=796917760 +ExeDescription=Toolbar2000 -- TBX Extensions Design Package (Alex Denisov) +[Directories] +OutputDir= +UnitOutputDir=..\..\Lib\D7 +PackageDLLOutputDir= +PackageDCPOutputDir= +SearchPath=..\..\Source +Packages=vcl;rtl;vclx;indy;inet;xmlrtl;vclie;inetdbbde;inetdbxpress;dbrtl;dsnap;dsnapcon;vcldb;soaprtl;VclSmp;dbexpress;dbxcds;inetdb;bdertl;vcldbx;webdsnap;websnap;adortl;ibxpress;teeui;teedb;tee;dss;visualclx;visualdbclx;vclactnband;vclshlctrls;dclOfficeXP;CEToolsPkgd7;FR7;FRIBX7;Hydra_Core_D7;Hydra_RO_D7;fqb70;frx7;frxADO7;frxBDE7;frxDB7;frxDBX7;frxe7;frxIBX7;fs7;fsADO7;fsBDE7;fsDB7;fsIBX7;DataAbstract_Core_D7;DataAbstract_IDE_D7;dxComnD7;dxsbD7;dxBarD7;dxBarDBNavD7;dxBarExtDBItemsD7;dxBarExtItemsD7;dxDockingD7;cxEditorsVCLD7;cxLibraryVCLD7;dxThemeD7;cxDataD7;cxExtEditorsVCLD7;cxGridVCLD7;cxPageControlVCLD7;cxSchedulerVCLD7;cxTreeListVCLD7;dxPSCoreD7 +Conditionals= +DebugSourceDirs= +UsePackages=0 +[Parameters] +RunParams= +HostApplication= +Launcher= +UseLauncher=0 +DebugCWD= +[Language] +ActiveLang= +ProjectLang= +RootDir=C:\Archivos de programa\Borland\Delphi7\Bin\ +[Version Info] +IncludeVerInfo=1 +AutoIncBuild=0 +MajorVer=1 +MinorVer=0 +Release=0 +Build=0 +Debug=0 +PreRelease=0 +Special=0 +Private=0 +DLL=0 +Locale=3082 +CodePage=1252 +[Version Info Keys] +CompanyName= +FileDescription= +FileVersion=1.0.0.0 +InternalName= +LegalCopyright= +LegalTrademarks= +OriginalFilename= +ProductName= +ProductVersion=1.0.0.0 +Comments= +[Excluded Packages] +C:\Archivos de programa\Borland\Delphi7\Projects\Bpl\DJclVcl70.bpl=JEDI Code Library VCL package for Delphi 7 +C:\Archivos de programa\Borland\Delphi7\Projects\Bpl\DJcl70.bpl=JEDI Code Library RTL package for Delphi 7 +C:\WINDOWS\system32\fqb70.bpl=FastQueryBuilder 1.01 +C:\Archivos de programa\Borland\Delphi7\Projects\Bpl\dxPSCoreD7.bpl=ExpressPrinting System (core 3.1) by Developer Express Inc. +C:\Archivos de programa\Borland\Delphi7\Projects\Bpl\dxComnD7.bpl=ExpressCommonLibrary by Developer Express Inc. +c:\archivos de programa\borland\delphi7\Projects\Bpl\EasyResizeD7.bpl=EasyResize for Delphi 7 +c:\archivos de programa\borland\delphi7\Projects\Bpl\RodaxFrameD7.bpl=Frames Acana (D7) +[HistoryLists\hlUnitAliases] +Count=1 +Item0=WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE; +[HistoryLists\hlSearchPath] +Count=1 +Item0=..\..\Source +[HistoryLists\hlUnitOutputDirectory] +Count=1 +Item0=..\..\Lib\D7 +[HistoryLists\hlDCPOutput] +Count=1 +Item0=..\..\Lib\D7 +[Exception Log] +EurekaLog Version=501 +Activate=1 +Activate Handle=1 +Save Log File=1 +Foreground Tab=0 +Freeze Activate=0 +Freeze Timeout=60 +Freeze Message=The application seems to be frozen. +SMTP From=eurekalog@email.com +SMTP Host= +SMTP Port=25 +SMTP UserID= +SMTP Password= +Append to Log=0 +Show TerminateBtn=1 +TerminateBtn Operation=1 +Errors Number=32 +Errors Terminate=3 +Email Address= +Email Object= +Email Send Options=0 +Output Path= +Encrypt Password= +AutoCloseDialogSecs=0 +WebSendMode=0 +SupportULR= +HTMLLayout Count=15 +HTMLLine0="%3Chtml%3E" +HTMLLine1=" %3Chead%3E" +HTMLLine2=" %3C/head%3E" +HTMLLine3=" %3Cbody TopMargin=10 LeftMargin=10%3E" +HTMLLine4=" %3Ctable width="100%%" border="0"%3E" +HTMLLine5=" %3Ctr%3E" +HTMLLine6=" %3Ctd nowrap%3E" +HTMLLine7=" %3Cfont face="Lucida Console, Courier" size="2"%3E" +HTMLLine8=" %3C%%HTML_TAG%%%3E" +HTMLLine9=" %3C/font%3E" +HTMLLine10=" %3C/td%3E" +HTMLLine11=" %3C/tr%3E" +HTMLLine12=" %3C/table%3E" +HTMLLine13=" %3C/body%3E" +HTMLLine14="%3C/html%3E" +AutoCrashOperation=1 +AutoCrashNumber=10 +AutoCrashMinutes=1 +WebURL= +WebUserID= +WebPassword= +WebPort=0 +AttachedFiles= +Count=0 +EMail Message Line Count=0 +loNoDuplicateErrors=0 +loAppendReproduceText=0 +loDeleteLogAtVersionChange=0 +loAddComputerNameInLogFileName=0 +loSaveModulesSection=1 +loSaveCPUSection=1 +soAppStartDate=1 +soAppName=1 +soAppVersionNumber=1 +soAppParameters=1 +soAppCompilationDate=1 +soExcDate=1 +soExcAddress=1 +soExcModule=1 +soExcType=1 +soExcMessage=1 +soActCtlsFormClass=1 +soActCtlsFormText=1 +soActCtlsControlClass=1 +soActCtlsControlText=1 +soCmpName=1 +soCmpUser=1 +soCmpTotalMemory=1 +soCmpFreeMemory=1 +soCmpTotalDisk=1 +soCmpFreeDisk=1 +soCmpSysUpTime=1 +soCmpProcessor=1 +soCmpDisplayMode=1 +soOSType=1 +soOSBuildN=1 +soOSUpdate=1 +soOSLanguage=1 +soNetIP=1 +soNetSubmask=1 +soNetGateway=1 +soNetDNS1=1 +soNetDNS2=1 +soNetDHCP=1 +sndShowSendDialog=1 +sndShowSuccessFailureMsg=0 +sndSendEntireLog=0 +sndSendXMLLogCopy=0 +sndSendScreenshot=1 +sndUseOnlyActiveWindow=0 +sndSendLastHTMLPage=1 +sndSendInSeparatedThread=0 +sndAddDateInFileName=0 +sndCompressAllFiles=0 +edoShowExceptionDialog=1 +edoSendEmailChecked=1 +edoAttachScreenshotChecked=1 +edoShowCopyToClipOption=1 +edoShowDetailsButton=1 +edoShowInDetailedMode=0 +edoShowInTopMostMode=0 +edoUseEurekaLogLookAndFeel=0 +csoShowDLLs=1 +csoShowBPLs=1 +csoShowBorlandThreads=1 +csoShowWindowsThreads=1 +csoShowProcedureOffset=0 +boActivateCrashDetection=0 +boPauseBorlandThreads=0 +boDoNotPauseMainThread=0 +boPauseWindowsThreads=0 +boUseMainModuleOptions=1 +boCopyLogInCaseOfError=1 +boSaveCompressedCopyInCaseOfError=0 +Count mtInformationMsgCaption=1 +mtInformationMsgCaption0="Information." +Count mtQuestionMsgCaption=1 +mtQuestionMsgCaption0="Question." +Count mtDialog_Caption=1 +mtDialog_Caption0="Error." +Count mtDialog_ErrorMsgCaption=2 +mtDialog_ErrorMsgCaption0="An error has occurred during program execution." +mtDialog_ErrorMsgCaption1="Please read the following information for further details." +Count mtDialog_GeneralCaption=1 +mtDialog_GeneralCaption0="General" +Count mtDialog_GeneralHeader=1 +mtDialog_GeneralHeader0="General Information" +Count mtDialog_CallStackCaption=1 +mtDialog_CallStackCaption0="Call Stack" +Count mtDialog_CallStackHeader=1 +mtDialog_CallStackHeader0="Call Stack Information" +Count mtDialog_ModulesCaption=1 +mtDialog_ModulesCaption0="Modules" +Count mtDialog_ModulesHeader=1 +mtDialog_ModulesHeader0="Modules Information" +Count mtDialog_CPUCaption=1 +mtDialog_CPUCaption0="CPU" +Count mtDialog_CPUHeader=1 +mtDialog_CPUHeader0="CPU Information" +Count mtDialog_CustomDataCaption=1 +mtDialog_CustomDataCaption0="Other" +Count mtDialog_CustomDataHeader=1 +mtDialog_CustomDataHeader0="Other Information" +Count mtDialog_OKButtonCaption=1 +mtDialog_OKButtonCaption0="&OK" +Count mtDialog_TerminateButtonCaption=1 +mtDialog_TerminateButtonCaption0="&Terminate" +Count mtDialog_RestartButtonCaption=1 +mtDialog_RestartButtonCaption0="&Restart" +Count mtDialog_DetailsButtonCaption=1 +mtDialog_DetailsButtonCaption0="&Details" +Count mtDialog_SendMessage=1 +mtDialog_SendMessage0="&Send this error via Internet" +Count mtDialog_ScreenshotMessage=1 +mtDialog_ScreenshotMessage0="&Attach a Screenshot image" +Count mtDialog_CopyMessage=1 +mtDialog_CopyMessage0="&Copy to Clipboard" +Count mtDialog_SupportMessage=1 +mtDialog_SupportMessage0="Go to the Support Page" +Count mtLog_AppHeader=1 +mtLog_AppHeader0="Application" +Count mtLog_AppStartDate=1 +mtLog_AppStartDate0="Start Date" +Count mtLog_AppName=1 +mtLog_AppName0="Name/Description" +Count mtLog_AppVersionNumber=1 +mtLog_AppVersionNumber0="Version Number" +Count mtLog_AppParameters=1 +mtLog_AppParameters0="Parameters" +Count mtLog_AppCompilationDate=1 +mtLog_AppCompilationDate0="Compilation Date" +Count mtLog_ExcHeader=1 +mtLog_ExcHeader0="Exception" +Count mtLog_ExcDate=1 +mtLog_ExcDate0="Date" +Count mtLog_ExcAddress=1 +mtLog_ExcAddress0="Address" +Count mtLog_ExcModule=1 +mtLog_ExcModule0="Module" +Count mtLog_ExcType=1 +mtLog_ExcType0="Type" +Count mtLog_ExcMessage=1 +mtLog_ExcMessage0="Message" +Count mtLog_ActCtrlsHeader=1 +mtLog_ActCtrlsHeader0="Active Controls" +Count mtLog_ActCtrlsFormClass=1 +mtLog_ActCtrlsFormClass0="Form Class" +Count mtLog_ActCtrlsFormText=1 +mtLog_ActCtrlsFormText0="Form Text" +Count mtLog_ActCtrlsControlClass=1 +mtLog_ActCtrlsControlClass0="Control Class" +Count mtLog_ActCtrlsControlText=1 +mtLog_ActCtrlsControlText0="Control Text" +Count mtLog_CmpHeader=1 +mtLog_CmpHeader0="Computer" +Count mtLog_CmpName=1 +mtLog_CmpName0="Name" +Count mtLog_CmpUser=1 +mtLog_CmpUser0="User" +Count mtLog_CmpTotalMemory=1 +mtLog_CmpTotalMemory0="Total Memory" +Count mtLog_CmpFreeMemory=1 +mtLog_CmpFreeMemory0="Free Memory" +Count mtLog_CmpTotalDisk=1 +mtLog_CmpTotalDisk0="Total Disk" +Count mtLog_CmpFreeDisk=1 +mtLog_CmpFreeDisk0="Free Disk" +Count mtLog_CmpSystemUpTime=1 +mtLog_CmpSystemUpTime0="System Up Time" +Count mtLog_CmpProcessor=1 +mtLog_CmpProcessor0="Processor" +Count mtLog_CmpDisplayMode=1 +mtLog_CmpDisplayMode0="Display Mode" +Count mtLog_OSHeader=1 +mtLog_OSHeader0="Operating System" +Count mtLog_OSType=1 +mtLog_OSType0="Type" +Count mtLog_OSBuildN=1 +mtLog_OSBuildN0="Build #" +Count mtLog_OSUpdate=1 +mtLog_OSUpdate0="Update" +Count mtLog_OSLanguage=1 +mtLog_OSLanguage0="Language" +Count mtLog_NetHeader=1 +mtLog_NetHeader0="Network" +Count mtLog_NetIP=1 +mtLog_NetIP0="IP Address" +Count mtLog_NetSubmask=1 +mtLog_NetSubmask0="Submask" +Count mtLog_NetGateway=1 +mtLog_NetGateway0="Gateway" +Count mtLog_NetDNS1=1 +mtLog_NetDNS10="DNS 1" +Count mtLog_NetDNS2=1 +mtLog_NetDNS20="DNS 2" +Count mtLog_NetDHCP=1 +mtLog_NetDHCP0="DHCP" +Count mtLog_CustInfoHeader=1 +mtLog_CustInfoHeader0="Custom Information" +Count mtCallStack_Address=1 +mtCallStack_Address0="Address" +Count mtCallStack_Name=1 +mtCallStack_Name0="Module" +Count mtCallStack_Unit=1 +mtCallStack_Unit0="Unit" +Count mtCallStack_Class=1 +mtCallStack_Class0="Class" +Count mtCallStack_Procedure=1 +mtCallStack_Procedure0="Procedure/Method" +Count mtCallStack_Line=1 +mtCallStack_Line0="Line" +Count mtCallStack_MainThread=1 +mtCallStack_MainThread0="Main" +Count mtCallStack_ExceptionThread=1 +mtCallStack_ExceptionThread0="Exception Thread" +Count mtCallStack_RunningThread=1 +mtCallStack_RunningThread0="Running Thread" +Count mtCallStack_CallingThread=1 +mtCallStack_CallingThread0="Calling Thread" +Count mtCallStack_ThreadID=1 +mtCallStack_ThreadID0="ID" +Count mtCallStack_ThreadPriority=1 +mtCallStack_ThreadPriority0="Priority" +Count mtCallStack_ThreadClass=1 +mtCallStack_ThreadClass0="Class" +Count mtSendDialog_Caption=1 +mtSendDialog_Caption0="Send." +Count mtSendDialog_Message=1 +mtSendDialog_Message0="Message" +Count mtSendDialog_Resolving=1 +mtSendDialog_Resolving0="Resolving DNS..." +Count mtSendDialog_Connecting=1 +mtSendDialog_Connecting0="Connecting with server..." +Count mtSendDialog_Connected=1 +mtSendDialog_Connected0="Connected with server." +Count mtSendDialog_Sending=1 +mtSendDialog_Sending0="Sending message..." +Count mtReproduceDialog_Caption=1 +mtReproduceDialog_Caption0="Request" +Count mtReproduceDialog_Request=1 +mtReproduceDialog_Request0="Please describe the steps to reproduce the error:" +Count mtReproduceDialog_OKButtonCaption=1 +mtReproduceDialog_OKButtonCaption0="&OK" +Count mtModules_Handle=1 +mtModules_Handle0="Handle" +Count mtModules_Name=1 +mtModules_Name0="Name" +Count mtModules_Description=1 +mtModules_Description0="Description" +Count mtModules_Version=1 +mtModules_Version0="Version" +Count mtModules_Size=1 +mtModules_Size0="Size" +Count mtModules_LastModified=1 +mtModules_LastModified0="Modified" +Count mtModules_Path=1 +mtModules_Path0="Path" +Count mtCPU_Registers=1 +mtCPU_Registers0="Registers" +Count mtCPU_Stack=1 +mtCPU_Stack0="Stack" +Count mtCPU_MemoryDump=1 +mtCPU_MemoryDump0="Memory Dump" +Count mtSend_SuccessMsg=1 +mtSend_SuccessMsg0="The message was sent successfully." +Count mtSend_FailureMsg=1 +mtSend_FailureMsg0="Sorry, sending the message didn't work." + + + {|t diff --git a/official/2.1.6+2.1.beta1/TBX/Packages/tbxdsgn_d7.dpk b/official/2.1.6+2.1.beta1/TBX/Packages/tbxdsgn_d7.dpk new file mode 100644 index 0000000..185da32 --- /dev/null +++ b/official/2.1.6+2.1.beta1/TBX/Packages/tbxdsgn_d7.dpk @@ -0,0 +1,40 @@ +package tbxdsgn_d7; + +{$R *.res} +{$R '..\TBXReg.dcr'} +{$ALIGN 8} +{$ASSERTIONS ON} +{$BOOLEVAL OFF} +{$DEBUGINFO ON} +{$EXTENDEDSYNTAX ON} +{$IMPORTEDDATA ON} +{$IOCHECKS ON} +{$LOCALSYMBOLS ON} +{$LONGSTRINGS ON} +{$OPENSTRINGS ON} +{$OPTIMIZATION ON} +{$OVERFLOWCHECKS OFF} +{$RANGECHECKS OFF} +{$REFERENCEINFO ON} +{$SAFEDIVIDE OFF} +{$STACKFRAMES OFF} +{$TYPEDADDRESS OFF} +{$VARSTRINGCHECKS ON} +{$WRITEABLECONST OFF} +{$MINENUMSIZE 1} +{$IMAGEBASE $2F800000} +{$DESCRIPTION 'Toolbar2000 -- TBX Extensions Design Package (Alex Denisov)'} +{$DESIGNONLY} +{$IMPLICITBUILD ON} + +requires + tb2k_d7, + tb2kdsgn_d7, + tbx_d7, + vcl; + +contains + TBXStrEdit in '..\TBXStrEdit.pas', + TBXReg in '..\TBXReg.pas'; + +end. diff --git a/official/2.1.6+2.1.beta1/TBX/Packages/tbxdsgn_d7.drc b/official/2.1.6+2.1.beta1/TBX/Packages/tbxdsgn_d7.drc new file mode 100644 index 0000000..a5d5271 --- /dev/null +++ b/official/2.1.6+2.1.beta1/TBX/Packages/tbxdsgn_d7.drc @@ -0,0 +1,14 @@ +/* VER150 + Generated by the Borland Delphi Pascal Compiler + because -GD or --drc was supplied to the compiler. + + This file contains compiler-generated resources that + were bound to the executable. + If this file is empty, then no compiler-generated + resources were bound to the produced executable. +*/ + +STRINGTABLE +BEGIN +END + diff --git a/official/2.1.6+2.1.beta1/TBX/Packages/tbxdsgn_d7.res b/official/2.1.6+2.1.beta1/TBX/Packages/tbxdsgn_d7.res new file mode 100644 index 0000000..528d18b Binary files /dev/null and b/official/2.1.6+2.1.beta1/TBX/Packages/tbxdsgn_d7.res differ diff --git a/official/2.1.6+2.1.beta1/TBX/TBX.inc b/official/2.1.6+2.1.beta1/TBX/TBX.inc new file mode 100644 index 0000000..dc7a561 --- /dev/null +++ b/official/2.1.6+2.1.beta1/TBX/TBX.inc @@ -0,0 +1,16 @@ +{$IFDEF JR_D7} + {$WARN SYMBOL_PLATFORM OFF} // TBX only supports Win32 +{$ENDIF} + +{$DEFINE TBX_UNICODE} // experimental +{*$DEFINE COMPATIBLE_CTL} // register duplicate controls with older names +{*$DEFINE COMPATIBLE_GFX} // compatibility with third-party themes +{$DEFINE WIN4_SHADOW} // enable shadow simulation in Win98/ME + +{$DEFINE NARROWCOMBOBUTTON} // removes gap after a combo item (default theme only) +{*$DEFINE OFFICE2K_COMBOS} // alternative border painting in popups of combo boxes + +{$DEFINE NEWCOLORPROPERTY} // register alternative color property editor + +{$DEFINE NARROWCOMBOBUTTON} + diff --git a/official/2.1.6+2.1.beta1/TBX/TBX.pas b/official/2.1.6+2.1.beta1/TBX/TBX.pas new file mode 100644 index 0000000..2ca78f3 --- /dev/null +++ b/official/2.1.6+2.1.beta1/TBX/TBX.pas @@ -0,0 +1,3837 @@ +unit TBX; + +// TBX Package +// Copyright 2001-2004 Alex A. Denisov. All Rights Reserved +// See TBX.chm for license and installation instructions +// +// $Id: TBX.pas 21 2004-05-29 22:16:01Z Alex@ZEISS $ + +interface + +{$I ..\..\Source\TB2Ver.inc} +{$I TBX.inc} + +{x$DEFINE TBX_NO_ANIMATION} + { Enabling the above define disables all menu animation. For debugging + purpose only. } {vb+} + +uses + Windows, Messages, Classes, SysUtils, Controls, Graphics, ImgList, Forms, + TB2Item, TB2Dock, TB2Toolbar, TB2ToolWindow, TB2Anim, TBXUtils, TBXThemes; + +const + TBXVersion = 2.1; + TBXVersionString = '2.1'; + TBXVersionText = 'TBX version ' + TBXVersionString; + +{ TBX Messages } +const + TBM_THEMECHANGE = WM_USER + 314; + TBM_GETVIEWTYPE = WM_USER + 237; + TBM_GETEFFECTIVECOLOR = WM_USER + 238; + +function GetViewType(View: TTBView): Integer; +function GetWinViewType(Window: TControl): Integer; +function IsFloating(ViewType: Integer): Boolean; + +type + TTextWrapping = (twNone, twEndEllipsis, twPathEllipsis, twWrap); + TTextTruncation = twNone..twPathEllipsis; + TTriState = (tsDefault, tsTrue, tsFalse); + TFontSize = 25..1000; + + TFontSettings = class(TPersistent) + private + FBold: TTriState; + FItalic: TTriState; + FUnderline: TTriState; + FStrikeOut: TTriState; + FSize: TFontSize; + FColor: TColor; + FName: TFontName; + FOnChange: TNotifyEvent; + procedure SetBold(Value: TTriState); + procedure SetColor(Value: TColor); + procedure SetItalic(Value: TTriState); + procedure SetName(const Value: TFontName); + procedure SetSize(Value: TFontSize); + procedure SetStrikeOut(Value: TTriState); + procedure SetUnderline(Value: TTriState); + protected + procedure Modified; + property OnChange: TNotifyEvent read FOnChange write FOnChange; + public + constructor Create; + procedure Apply(Font: TFont); overload; + procedure Apply(var LF: TLogFont; var FontColor: TColor); overload; + procedure Assign(Src: TPersistent); override; + function CreateTransformedFont(Src: HFont; var FontColor: TColor): HFont; + published + property Bold: TTriState read FBold write SetBold default tsDefault; + property Italic: TTriState read FItalic write SetItalic default tsDefault; + property Underline: TTriState read FUnderline write SetUnderline default tsDefault; + property StrikeOut: TTriState read FStrikeOut write SetStrikeOut default tsDefault; + property Size: TFontSize read FSize write SetSize default 100; // percent + property Color: TColor read FColor write SetColor default clNone; + property Name: TFontName read FName write SetName; // default '' + end; + + TTBXPopupPositionInfo = record + Item: TTBCustomItem; // this is a tentative type, it will be changed + ParentView: TTBView; // or removed in future versions + ParentViewer: TTBItemViewer; + PositionAsSubmenu: Boolean; + APopupPoint: TPoint; + Alignment: TTBPopupAlignment; + PopupWindow: TTBPopupWindow; + X, Y: Integer; + ParentItemRect: TRect; + AppFlags: Integer; // reserved for extensions + AppData: Integer; + end; + + TTBXThemeClass = class of TTBXTheme; + +function GetStateFlags(const ItemInfo: TTBXItemInfo): Integer; +function GetTBXTextColor(StateFlags: Integer): TColor; +procedure DrawTBXCaption(Canvas: TCanvas; Rect: TRect; const Text: string; + Format: Cardinal; StateFlags: Integer); +procedure DrawTBXImage(Canvas: TCanvas; Rect: TRect; ImageList: TCustomImageList; + ImageIndex: Integer; StateFlags: Integer); + + +type + { TTBXItem } + + TAdjustFontEvent = procedure(Item: TTBCustomItem; Viewer: TTBItemViewer; + Font: TFont; StateFlags: Integer) of object; // state flags are the combination of ISF_* constants + TDrawImageEvent = procedure(Item: TTBCustomItem; Viewer: TTBItemViewer; + Canvas: TCanvas; ImageRect: TRect; ImageOffset: TPoint; StateFlags: Integer) of object; + + TTBXCustomItem = class(TTBCustomItem) + private + FAlwaysSelectFirst: Boolean; + FFontSettings: TFontSettings; + FLayout: TTBXItemLayout; + FMinHeight: Integer; + FMinWidth: Integer; + FToolBoxPopup: Boolean; + FOnAdjustFont: TAdjustFontEvent; + FOnDrawImage: TDrawImageEvent; + procedure FontSettingsChanged(Sender: TObject); + function GetStretch: Boolean; + procedure SetFontSettings(Value: TFontSettings); + procedure SetLayout(Value: TTBXItemLayout); + procedure SetMinHeight(Value: Integer); + procedure SetMinWidth(Value: Integer); + procedure SetStretch(Value: Boolean); + protected + function CreatePopup(const ParentView: TTBView; const ParentViewer: TTBItemViewer; + const PositionAsSubmenu, SelectFirstItem, Customizing: Boolean; + const APopupPoint: TPoint; const Alignment: TTBPopupAlignment): TTBPopupWindow; override; + function GetItemViewerClass(AView: TTBView): TTBItemViewerClass; override; + procedure GetPopupPosition(ParentView: TTBView; PopupWindow: TTBPopupWindow; + var PopupPositionRec: TTBPopupPositionRec); override; + function GetPopupWindowClass: TTBPopupWindowClass; override; + property ToolBoxPopup: Boolean read FToolBoxPopup write FToolBoxPopup default False; + property OnAdjustFont: TAdjustFontEvent read FOnAdjustFont write FOnAdjustFont; + property OnDrawImage: TDrawImageEvent read FOnDrawImage write FOnDrawImage; + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + procedure Invalidate; + property AlwaysSelectFirst: Boolean read FAlwaysSelectFirst write FAlwaysSelectFirst default False; + property FontSettings: TFontSettings read FFontSettings write SetFontSettings; + property Layout: TTBXItemLayout read FLayout write SetLayout default tbxlAuto; + property MinHeight: Integer read FMinHeight write SetMinHeight default 0; + property MinWidth: Integer read FMinWidth write SetMinWidth default 0; + property Stretch: Boolean read GetStretch write SetStretch default False; + end; + + TTBXItem = class (TTBXCustomItem) + property Action; + property AutoCheck; + property Caption; + property Checked; + property DisplayMode; + property Enabled; + property FontSettings; + property GroupIndex; + property HelpContext; + property Hint; + property ImageIndex; + property Images; + property InheritOptions; + property Layout; + property MaskOptions; + property MinHeight; + property MinWidth; + property Options; + property RadioItem; + property ShortCut; + property Stretch; + property Visible; + property OnAdjustFont; + property OnDrawImage; + property OnClick; + property OnSelect; + end; + + TTBXItemViewer = class(TTBItemViewer) + private + FWide: Boolean; + protected + procedure DoPaintCaption(Canvas: TCanvas; const ClientAreaRect: TRect; + var CaptionRect: TRect; IsTextRotated: Boolean; var PaintDefault: Boolean); virtual; + function GetAccRole: Integer; override; + function GetImageSize: TSize; dynamic; + function GetItemType: Integer; virtual; + function GetTextFlags: Cardinal; dynamic; + function GetTextSize(Canvas: TCanvas; const Text: string; TextFlags: Cardinal; Rotated: Boolean; StateFlags: Integer): TSize; dynamic; + function IsToolbarSize: Boolean; override; + procedure CalcSize(const Canvas: TCanvas; var AWidth, AHeight: Integer); override; + procedure DrawItemImage(Canvas: TCanvas; ARect: TRect; ItemInfo: TTBXItemInfo); virtual; + procedure DoAdjustFont(AFont: TFont; StateFlags: Integer); virtual; + function GetImageShown: Boolean; virtual; + function IsPtInButtonPart(X, Y: Integer): Boolean; override; + procedure MouseUp(X, Y: Integer; MouseWasDownOnMenu: Boolean); override; + procedure Paint(const Canvas: TCanvas; const ClientAreaRect: TRect; IsHoverItem, IsPushed, UseDisabledShadow: Boolean); override; + property Wide: Boolean read FWide write FWide default True; + public + constructor Create(AView: TTBView; AItem: TTBCustomItem; AGroupLevel: Integer); override; + function IsToolbarStyle: Boolean; override; + end; + + { TTBXSubmenuItem } + + TTBXSubmenuItem = class(TTBXCustomItem) + private + function GetDropdownCombo: Boolean; + procedure SetDropdownCombo(Value: Boolean); + public + constructor Create(AOwner: TComponent); override; + published + property Action; + property AlwaysSelectFirst; + property AutoCheck; + property Caption; + property Checked; + property DisplayMode; + property DropdownCombo: Boolean read GetDropdownCombo write SetDropdownCombo default False; + property Enabled; + property FontSettings; + property GroupIndex; + property HelpContext; + property Hint; + property ImageIndex; + property Images; + property InheritOptions; + property Layout; + property LinkSubitems; + property MaskOptions; + property MinHeight; + property MinWidth; + property Options; + property RadioItem; + property ShortCut; + property Stretch; + property SubMenuImages; + property ToolBoxPopup; + property Visible; + property OnAdjustFont; + property OnDrawImage; + property OnClick; + property OnPopup; + property OnSelect; + end; + + { TTBXSeparatorItem } + + TTBXSeparatorItem = class(TTBSeparatorItem) + private + FSize: Integer; + procedure SetSize(Value: Integer); + public + constructor Create(AOwner: TComponent); override; + function GetItemViewerClass(AView: TTBView): TTBItemViewerClass; override; + published + property Size: Integer read FSize write SetSize default -1; + property MaskOptions; + property Options; + end; + + TTBXSeparatorItemViewer = class(TTBSeparatorItemViewer) + protected + procedure CalcSize(const Canvas: TCanvas; var AWidth, AHeight: Integer); override; + procedure Paint(const Canvas: TCanvas; const ClientAreaRect: TRect; + IsHoverItem, IsPushed, UseDisabledShadow: Boolean); override; + function IsToolbarSize: Boolean; override; + public + function IsToolbarStyle: Boolean; override; + end; + + TTBXVisibilityToggleItem = class(TTBXCustomItem) + private + FControl: TControl; + procedure SetControl (Value: TControl); + procedure UpdateProps; + protected + procedure Notification (AComponent: TComponent; Operation: TOperation); override; + public + procedure Click; override; + procedure InitiateAction; override; + published + property Caption; + property Control: TControl read FControl write SetControl; + property DisplayMode; + property Enabled; + property FontSettings; + property HelpContext; + property Hint; + property ImageIndex; + property Images; + property InheritOptions; + property Layout; + property MaskOptions; + property MinHeight; + property MinWidth; + property Options; + property ShortCut; + property Stretch; + property Visible; + property OnAdjustFont; + property OnClick; + property OnSelect; + end; + + { TTBXPopupWindow } + + TTBXPopupWindow = class(TTBPopupWindow) + private + FControlRect: TRect; + FShadows: TShadows; + procedure CMHintShow(var Message: TCMHintShow); message CM_HINTSHOW; + procedure CMShowingChanged(var Message: TMessage); message CM_SHOWINGCHANGED; {vb+} + procedure TBMGetViewType(var Message: TMessage); message TBM_GETVIEWTYPE; + procedure WMNCCalcSize(var Message: TWMNCCalcSize); message WM_NCCALCSIZE; + procedure WMNCPaint(var Message: TMessage); message WM_NCPAINT; + procedure WMPrint(var Message: TMessage); message WM_PRINT; + procedure WMEraseBkgnd(var Message: TWMEraseBkgnd); message WM_ERASEBKGND; + procedure WMWindowPosChanged(var Message: TWMWindowPosChanged); message WM_WINDOWPOSCHANGED; + procedure WMTB2kPopupShowing(var Message: TMessage); message WM_TB2K_POPUPSHOWING; + protected + procedure CreateParams(var Params: TCreateParams); override; + procedure CreateShadow; virtual; + procedure DestroyShadow; virtual; + function GetNCSize: TPoint; override; + function GetShowShadow: Boolean; virtual; + function GetViewClass: TTBViewClass; override; + procedure PaintScrollArrows; override; {vb+} + public + destructor Destroy; override; + function GetFillColor: TColor; + end; + + TTBXPopupView = class(TTBPopupView); + + { TTBXToolbarView } + + TTBXToolbarView = class(TTBToolbarView) + protected + procedure GetMargins(AOrientation: TTBViewOrientation; var Margins: TRect); override; + end; + + { TTBXToolbar } + TTBXItemTransparency = (itAuto, itEnable, itDisable); + + TTBXToolbar = class(TTBCustomToolbar) + private + FEffectiveColor: TColor; + FItemTransparency: TTBXItemTransparency; + FSnapDistance: Integer; + procedure CMColorChanged(var Message: TMessage); message CM_COLORCHANGED; + procedure CMControlChange(var Message: TCMControlChange); message CM_CONTROLCHANGE; + procedure CMParentColorChanged(var Message: TMessage); message CM_PARENTCOLORCHANGED; + procedure SetItemTransparency(const Value: TTBXItemTransparency); + procedure SetSnapDistance(Value: Integer); + procedure TBMGetViewType(var Message: TMessage); message TBM_GETVIEWTYPE; + procedure TBMGetEffectiveColor(var Message: TMessage); message TBM_GETEFFECTIVECOLOR; + procedure TBMThemeChange(var Message: TMessage); message TBM_THEMECHANGE; + procedure WMEraseBkgnd(var Message: TWMEraseBkgnd); message WM_ERASEBKGND; + procedure WMSize(var Message: TWMSize); message WM_SIZE; + protected + procedure DrawNCArea(const DrawToDC: Boolean; const ADC: HDC; const Clip: HRGN); override; + function GetChevronItemClass: TTBChevronItemClass; override; + function GetFloatingWindowParentClass: TTBFloatingWindowParentClass; override; + procedure GetToolbarInfo(out ToolbarInfo: TTBXToolbarInfo); virtual; + function GetViewClass: TTBToolbarViewClass; override; + procedure Loaded; override; {vb+} + procedure SetParent(AParent: TWinControl); override; + procedure UpdateEffectiveColor; + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + function Embedded: Boolean; + function GetFloatingBorderSize: TPoint; override; + procedure UpdateChildColors; + property EffectiveColor: TColor read FEffectiveColor; + published + property ActivateParent; + property Align; + property AutoResize; + property BorderStyle; + property Caption; + property ChevronHint; + property ChevronMoveItems; + property ChevronPriorityForNewItems; + property CloseButton; + property CloseButtonWhenDocked; + property CurrentDock; + property DblClickUndock default False; + property DefaultDock; + property DockableTo; + property DockMode; + property DockPos; + property DockRow; + property DragHandleStyle; + property FloatingMode; + property Font; + property FullSize; + property HideWhenInactive; + property Images; + property Items; + property ItemTransparency: TTBXItemTransparency read FItemTransparency write SetItemTransparency default itAuto; + property LastDock; + property LinkSubitems; + property MenuBar; + property Options; + property ParentFont; + property ParentShowHint; + property PopupMenu; + property ProcessShortCuts; + property Resizable; + property ShowCaption; + property ShowHint; + property ShrinkMode; + property SmoothDrag; + property SnapDistance: Integer read FSnapDistance write SetSnapDistance default 0; + property Stretch; + property SystemFont; + property TabOrder; + property TabStop; + property UpdateActions; + property UseLastDock; + property Visible; + property Color default clNone; + property OnClose; + property OnCloseQuery; + {$IFDEF JR_D5} + property OnContextPopup; + {$ENDIF} + property OnDragDrop; + property OnDragOver; + property OnMouseDown; + property OnMouseMove; + property OnMouseUp; + property OnMove; + property OnRecreated; + property OnRecreating; + property OnDockChanged; + property OnDockChanging; + property OnDockChangingHidden; + property OnResize; + property OnShortCut; + property OnVisibleChanged; + end; + + { TTBXChevronItem } + + TTBXChevronItem = class(TTBChevronItem) + public + procedure GetPopupPosition(ParentView: TTBView; + PopupWindow: TTBPopupWindow; var PopupPositionRec: TTBPopupPositionRec); override; + function GetPopupWindowClass: TTBPopupWindowClass; override; + function GetItemViewerClass(AView: TTBView): TTBItemViewerClass; override; + end; + + TTBXChevronItemViewer = class(TTBItemViewer) + protected + procedure Paint(const Canvas: TCanvas; const ClientAreaRect: TRect; + IsHoverItem, IsPushed, UseDisabledShadow: Boolean); override; + end; + + TTBXChevronPopupWindow = class(TTBXPopupWindow); + + { TTBXPopupMenu } + + TTBXRootItem = class(TTBRootItem) + private + FPopupControlRect: TRect; + protected + function CreatePopupEx(SelectFirstItem: Boolean; const AControlRect: TRect; + Alignment: TTBPopupAlignment): TTBPopupWindow; virtual; + function GetPopupWindowClass: TTBPopupWindowClass; override; + procedure GetPopupPosition(ParentView: TTBView; PopupWindow: TTBPopupWindow; + var PopupPositionRec: TTBPopupPositionRec); override; + function OpenPopupEx(const SelectFirstItem, TrackRightButton: Boolean; + const ControlRect: TRect; const Alignment: TTBPopupAlignment; + const ReturnClickedItemOnly: Boolean): TTBCustomItem; + function PopupEx(const ControlRect: TRect; TrackRightButton: Boolean; + Alignment: TTBPopupAlignment = tbpaLeft; + ReturnClickedItemOnly: Boolean = False): TTBCustomItem; + end; + + TTBXPopupMenu = class(TTBPopupMenu) + private + FToolBoxPopup: Boolean; + procedure TBMGetViewType(var Message: TMessage); message TBM_GETVIEWTYPE; + protected + function GetRootItemClass: TTBRootItemClass; override; + public + function PopupEx(const ControlRect: TRect; + ReturnClickedItemOnly: Boolean = False): TTBCustomItem; + property ToolBoxPopup: Boolean read FToolBoxPopup write FToolBoxPopup default False; + end; + + TTBXFloatingWindowParent = class(TTBFloatingWindowParent) + private + FCloseButtonHover: Boolean; + FSnapDistance: Integer; + procedure CMMouseLeave(var Message: TMessage); message CM_MOUSELEAVE; + procedure WMEraseBkgnd(var Message: TMessage); message WM_ERASEBKGND; + procedure WMNCMouseLeave(var Message: TMessage); message $2A2 {WM_NCMOUSELEAVE}; + procedure WMNCMouseMove(var Message: TWMNCMouseMove); message WM_NCMOUSEMOVE; + procedure WMWindowPosChanging(var Message: TWMWindowPosChanging); message WM_WINDOWPOSCHANGING; + protected + procedure CancelNCHover; + procedure DrawNCArea(const DrawToDC: Boolean; const ADC: HDC; + const Clip: HRGN; RedrawWhat: TTBToolWindowNCRedrawWhat); override; + property CloseButtonHover: Boolean read FCloseButtonHover; + public + property SnapDistance: Integer read FSnapDistance write FSnapDistance default 0; + end; + + TTBXToolWindow = class(TTBToolWindow) + private + FEffectiveColor: TColor; + FSnapDistance: Integer; + procedure CMColorChanged(var Message: TMessage); message CM_COLORCHANGED; + procedure CMControlChange(var Message: TCMControlChange); message CM_CONTROLCHANGE; + procedure CMTextChanged(var Message: TMessage); message CM_TEXTCHANGED; + procedure SetSnapDistance(Value: Integer); + procedure TBMGetEffectiveColor(var Message: TMessage); message TBM_GETEFFECTIVECOLOR; + procedure TBMGetViewType(var Message: TMessage); message TBM_GETVIEWTYPE; + procedure TBMThemeChange(var Message: TMessage); message TBM_THEMECHANGE; + procedure WMEraseBkgnd(var Message: TWmEraseBkgnd); message WM_ERASEBKGND; + protected + procedure DrawNCArea(const DrawToDC: Boolean; const ADC: HDC; const Clip: HRGN); override; + function GetFloatingWindowParentClass: TTBFloatingWindowParentClass; override; + procedure GetToolbarInfo(out ToolbarInfo: TTBXToolbarInfo); virtual; + procedure SetParent(AParent: TWinControl); override; + procedure UpdateEffectiveColor; + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + function GetFloatingBorderSize: TPoint; override; + procedure UpdateChildColors; + property EffectiveColor: TColor read FEffectiveColor; + published + property Color default clNone; + property DblClickUndock default False; + property SnapDistance: Integer read FSnapDistance write SetSnapDistance default 0; + end; + + TTBXDock = class(TTBDock) + private + FMoving: Boolean; + FResizing: Boolean; + FUseParentBackground: Boolean; + procedure CMColorChanged(var Message: TMessage); message CM_COLORCHANGED; + procedure TBMGetEffectiveColor(var Message: TMessage); message TBM_GETEFFECTIVECOLOR; + procedure TBMThemeChange(var Message: TMessage); message TBM_THEMECHANGE; + procedure WMEraseBkgnd(var Message: TWMEraseBkgnd); message WM_ERASEBKGND; + procedure WMMove(var Message: TWMMove); message WM_MOVE; + procedure WMSize(var Message: TWMSize); message WM_SIZE; + protected + function ThemedBackground: Boolean; virtual; + procedure DrawBackground(DC: HDC; const DrawRect: TRect); override; + procedure Resize; override; + procedure SetUseParentBackground(Value: Boolean); + function UsingBackground: Boolean; override; + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + published + property Color default clNone; + property UseParentBackground: Boolean read FUseParentBackground write SetUseParentBackground default False; + end; + + { TTBXMenuAnimation } {vb+} + + TMenuAnimation = (maNone, maUnfold, maSlide, maFade); + TAnimationMode = (amNone, amSysDefault, amRandom, amUnfold, amSlide, amFade); + TAnimationModes = set of TAnimationMode; + + TTBXMenuAnimation = class + private + FAnimationMode: TAnimationMode; + function SysParamEnabled(Param: Cardinal): Boolean; + function GetAvailableModes: TAnimationModes; + function GetMenuAnimation: TMenuAnimation; + procedure SetAnimationMode(Value: TAnimationMode); + property MenuAnimation: TMenuAnimation read GetMenuAnimation; + public + constructor Create(AAnimationMode: TAnimationMode = amSysDefault); + property AnimationMode: TAnimationMode read FAnimationMode write SetAnimationMode; + property AvailableModes: TAnimationModes read GetAvailableModes; + end; + +var + CurrentTheme: TTBXTheme; + TBXMenuAnimation: TTBXMenuAnimation; { vb+ } + +{$IFNDEF JR_D6} +var + clMoneyGreen: TColor = TColor($C0DCC0); + clSkyBlue: TColor = TColor($F0CAA6); + clCream: TColor = TColor($F0FBFF); + clMedGray: TColor = TColor($A4A0A0); +{$ENDIF} + +procedure TBXSetTheme(const AThemeName: string); +function TBXCurrentTheme: string; + +procedure AddThemeNotification(AObject: TObject); +procedure RemoveThemeNotification(AObject: TObject); + +{ Additional system colors } +procedure AddTBXColor(var AColor: TColor; const AName: string); +function TBXIdentToColor(const Ident: string; var Color: Longint): Boolean; +function TBXColorToString(Color: TColor): string; +function TBXStringToColor(S: string): TColor; +procedure TBXGetColorValues(Proc: TGetStrProc); + +{ Internal routines - do not use } +function GetPopupMargin(ItemViewer: TTBItemViewer): Integer; +function GetEffectiveColor(C: TControl): TColor; +procedure DrawParentBackground(Control: TControl; DC: HDC; R: TRect); +procedure AddToList(var List: TList; Item: Pointer); +procedure RemoveFromList(var List: TList; Item: Pointer); + +implementation + +{$R tbx_glyphs.res} + +uses + TBXExtItems, TBXLists, TB2Common, TBXUxThemes, MultiMon, TBXDefaultTheme, + {ComCtrls, Menus;} {vb-} + ComCtrls, Menus, MMSystem; {vb+} + +type + TTBItemAccess = class(TTBCustomItem); + TTBViewAccess = class(TTBView); + TTBItemViewerAccess = class(TTBItemViewer); + TTBFloatingWindowParentAccess = class(TTBFloatingWindowParent); + TTBCustomDockableWindowAccess = class(TTBCustomDockableWindow); + TTBXToolbarAccess = class(TTBXToolbar); + TTBBackgroundAccess = class(TTBBackground); + TControlAccess = class(TControl); + TTBXThemeAccess = class(TTBXTheme); + TDockAccess = class(TTBDock); + TTBPopupWindowAccess = class(TTBPopupWindow); {vb+} + + { TTBNexus } + TTBXNexus = class + private + FNotifies: TList; + procedure TBXSysCommand(var Message: TMessage); message TBX_SYSCOMMAND; + protected + procedure Broadcast(Msg: Cardinal; WParam, LParam: Integer); + public + constructor Create(const DefaultTheme: string); + destructor Destroy; override; + procedure SetTheme(const AThemeName: string); + function GetTheme: string; + procedure AddNotifie(AObject: TObject); + procedure RemoveNotifie(AObject: TObject); + end; + +var + TBXNexus: TTBXNexus; + +procedure AddThemeNotification(AObject: TObject); +begin + TBXNexus.AddNotifie(AObject); +end; + +procedure RemoveThemeNotification(AObject: TObject); +begin + TBXNexus.RemoveNotifie(AObject); +end; + +function GetEffectiveColor(C: TControl): TColor; +var + Message: TMessage; +begin + if C = nil then Result := clBtnFace + else + begin + Message.Msg := TBM_GETEFFECTIVECOLOR; + Message.WParam := 0; + Message.LParam := 0; + Message.Result := 0; + C.Dispatch(Message); + if Message.Result <> 0 then Result := Message.WParam + else if (C is TForm) and (TForm(C).FormStyle = fsMDIForm) then + Result := clBtnFace + else + Result := TControlAccess(C).Color; + end; +end; + +procedure DrawParentBackground(Control: TControl; DC: HDC; R: TRect); +var + Parent: TWinControl; + Theme: HTHEME; + R2: TRect; + Shift: TPoint; + UsingThemes: Boolean; + Msg: TMessage; +begin + Parent := Control.Parent; + if Parent = nil then FillRectEx(DC, R, clBtnFace) + else + begin + Shift.X := 0; Shift.Y := 0; + Shift := Parent.ScreenToClient(Control.ClientToScreen(Shift)); + SaveDC(DC); + try + SetWindowOrgEx(DC, Shift.X, Shift.Y, nil); + Msg.Msg := WM_ERASEBKGND; + Msg.WParam := Integer(DC); {vb+} + Msg.LParam := Integer(DC); {vb+} + Msg.Result := 0; + Parent.Dispatch(Msg); + finally + RestoreDC(DC, -1); + end; + + if Msg.Result <> 0 then Exit; + + UsingThemes := USE_THEMES and not (csDesigning in Control.ComponentState); + if Parent is TTBDock then + begin + SaveDC(DC); + SetWindowOrgEx(DC, Control.Left, Control.Top, nil); + TDockAccess(Parent).DrawBackground(DC, R); + RestoreDC(DC, -1); + end + else if not UsingThemes then + FillRectEx(DC, R, GetEffectiveColor(Parent)) + else + begin + { Unfortunately, DrawThemeParentBackground does seem to have some problems + with the back buffer. Therefore some sort of workaround is used which + will work for tab sheets } + // if Control is TWinControl then + // DrawThemeParentBackground(TWinControl(Control).Handle, DC, @R); + + if Parent is TTabSheet then + begin + Theme := OpenThemeData(Parent.Handle, 'TAB'); + R2 := Parent.ClientRect; + R2.TopLeft := Control.ScreenToClient(Parent.ClientToScreen(R2.TopLeft)); + R2.BottomRight := Control.ScreenToClient(Parent.ClientToScreen(R2.BottomRight)); + DrawThemeBackground(Theme, DC, TABP_BODY, 0, R2, @R); + CloseThemeData(Theme); + end + else FillRectEx(DC, R, GetEffectiveColor(Parent)); + end; + end; +end; + +function GetViewType(View: TTBView): Integer; +var + Message: TMessage; +begin + Result := VT_UNKNOWN; + if (View <> nil) and (View.Owner <> nil) then + begin + Message.Msg := TBM_GETVIEWTYPE; + Message.WParam := 0; + Message.LParam := 0; + Message.Result := VT_UNKNOWN; + View.Window.Dispatch(Message); + Result := Message.Result; + end; +end; + +function GetWinViewType(Window: TControl): Integer; +var + Message: TMessage; +begin + Result := VT_UNKNOWN; + if Window <> nil then + begin + Message.Msg := TBM_GETVIEWTYPE; + Message.WParam := 0; + Message.LParam := 0; + Message.Result := VT_UNKNOWN; + Window.Dispatch(Message); + Result := Message.Result; + end; +end; + +function IsFloating(ViewType: Integer): Boolean; +begin + Result := ViewType and TVT_FLOATING <> 0; +end; + +procedure UpdateNCArea(Control: TWinControl; ViewType: Integer); +begin + with Control do + begin + ClientWidth := ClientWidth; + ClientHeight := ClientHeight; + end; + SetWindowPos(Control.Handle, 0, 0, 0, 0, 0, + SWP_FRAMECHANGED or SWP_NOACTIVATE or SWP_NOZORDER or SWP_NOMOVE or SWP_NOSIZE); + Control.Invalidate; +end; + +function GetPopupMargin(ItemViewer: TTBItemViewer): Integer; +var + ImgList: TCustomImageList; + Sz: TSize; + TextMetric: TTextMetric; + H, M2: Integer; + Margins: TTBXMargins; +begin + Sz.Cx := 0; + Sz.Cy := 0; + if ItemViewer is TTBXItemViewer then + Sz := TTBXItemViewer(ItemViewer).GetImageSize; + if (Sz.Cx = 0) or (Sz.Cy = 0) then + begin + ImgList := TTBItemViewerAccess(ItemViewer).GetImageList; + if ImgList <> nil then + begin + Sz.Cx := ImgList.Width; + Sz.Cy := ImgList.Height; + end; + if (Sz.Cx = 0) or (Sz.Cy = 0) then + begin + Sz.Cx := 16; + Sz.Cy := 16; + end; + end; + StockBitmap1.Canvas.Font := TTBViewAccess(ItemViewer.View).GetFont; + GetTextMetrics(StockBitmap1.Canvas.Handle, TextMetric); + + CurrentTheme.GetMargins(MID_MENUITEM, Margins); + M2 := Margins.TopHeight + Margins.BottomHeight; + Result := TextMetric.tmHeight + TextMetric.tmExternalLeading + M2; + H := Sz.CY + M2; + if H > Result then Result := H; + Result := (Sz.Cx + M2) * Result div H; +end; + +procedure GetOfficeXPPopupPosition1(var PopupPositionRec: TTBPopupPositionRec); +begin + with PopupPositionRec do + begin + if not PositionAsSubmenu then + begin + NCSizeX := 0; + NCSizeY := 0; + Dec(ParentItemRect.Right); + if X = ParentItemRect.Right + 1 then Dec(X); + if X + W <= ParentItemRect.Left then Inc(X); + Dec(ParentItemRect.Bottom); + if Y = ParentItemRect.Bottom + 1 then Dec(Y); + if Y + H <= ParentItemRect.Top then Inc(Y); + Dec(W); + Dec(H); + end + else + begin + Inc(X, NCSizeX); + Inc(Y, NCSizeY); + NCSizeX := 0; + NCSizeY := 0; + end; + end; +end; + +procedure GetOfficeXPPopupPosition2(var PopupPositionRec: TTBPopupPositionRec); +begin + with PopupPositionRec do if not PositionAsSubmenu then + begin + Inc(W); + Inc(H); + end; +end; + +procedure AddToList(var List: TList; Item: Pointer); +begin + if List = nil then List := TList.Create; + List.Add(Item) +end; + + +procedure RemoveFromList(var List: TList; Item: Pointer); +begin + if List <> nil then + begin + List.Remove(Item); + if List.Count = 0 then + begin + List.Free; + List := nil; + end; + end; +end; + +//============================================================================// + +{ Misc. Routines } + +procedure InvalidateAll(const Ctl: TWinControl); +begin + if Ctl.HandleAllocated then + RedrawWindow(Ctl.Handle, nil, 0, RDW_FRAME or RDW_INVALIDATE or + RDW_ERASE); +end; + +function GetStateFlags(const ItemInfo: TTBXItemInfo): Integer; +const + CEnabledStates: array [Boolean] of Integer = (ISF_DISABLED, 0); + CHotStates: array [Boolean] of Integer = (0, ISF_HOT); + CPushedStates: array [Boolean] of Integer = (0, ISF_PUSHED); + CSelectedStates: array [Boolean] of Integer = (0, ISF_SELECTED); +begin + with ItemInfo do + Result := CEnabledStates[ItemInfo.Enabled] or CPushedStates[ItemInfo.Pushed] or + CHotStates[ItemInfo.HoverKind = hkMouseHover] or CSelectedStates[ItemInfo.Selected]; +end; + +function GetTBXTextColor(StateFlags: Integer): TColor; +const + HoverKinds: array [Boolean] of TTBXHoverKind = (hkNone, hkMouseHover); +var + ItemInfo: TTBXItemInfo; +begin + FillChar(ItemInfo, SizeOf(ItemInfo), 0); + case StateFlags and ISF_LOCATIONMASK of + ISF_TOOLBARCOLOR: + begin + ItemInfo.ViewType := VT_TOOLBAR; + ItemInfo.ItemOptions := IO_TOOLBARSTYLE; + end; + ISF_MENUCOLOR: + begin + ItemInfo.ViewType := VT_DOCKPANEL; + end; + ISF_STATUSCOLOR: + begin + ItemInfo.ViewType := VT_STATUSBAR; + end; + else + ItemInfo.ViewType := VT_UNKNOWN; + end; + ItemInfo.Enabled := StateFlags and ISF_DISABLED = 0; + ItemInfo.Pushed := StateFlags and ISF_PUSHED <> 0; + ItemInfo.HoverKind := HoverKinds[StateFlags and ISF_HOT <> 0]; + ItemInfo.Selected := StateFlags and ISF_SELECTED <> 0; + Result := CurrentTheme.GetItemTextColor(ItemInfo); +end; + +procedure DrawTBXCaption(Canvas: TCanvas; Rect: TRect; const Text: string; Format: Cardinal; StateFlags: Integer); +const + HoverKinds: array [Boolean] of TTBXHoverKind = (hkNone, hkMouseHover); +var + ItemInfo: TTBXItemInfo; +begin + FillChar(ItemInfo, SizeOf(ItemInfo), 0); + case StateFlags and ISF_LOCATIONMASK of + ISF_TOOLBARCOLOR: + begin + ItemInfo.ViewType := VT_TOOLBAR; + ItemInfo.ItemOptions := IO_TOOLBARSTYLE; + end; + ISF_MENUCOLOR: + begin + ItemInfo.ViewType := VT_DOCKPANEL; + end; + ISF_STATUSCOLOR: + begin + ItemInfo.ViewType := VT_STATUSBAR; + end; + end; + ItemInfo.Enabled := StateFlags and ISF_DISABLED = 0; + ItemInfo.Pushed := StateFlags and ISF_PUSHED <> 0; + ItemInfo.HoverKind := HoverKinds[StateFlags and ISF_HOT <> 0]; + ItemInfo.Selected := StateFlags and ISF_SELECTED <> 0; + CurrentTheme.PaintCaption(Canvas, Rect, ItemInfo, Text, Format, False); +end; + +procedure DrawTBXImage(Canvas: TCanvas; Rect: TRect; ImageList: TCustomImageList; + ImageIndex: Integer; StateFlags: Integer); +const + HoverKinds: array [Boolean] of TTBXHoverKind = (hkNone, hkMouseHover); +var + ItemInfo: TTBXItemInfo; +begin + FillChar(ItemInfo, SizeOf(ItemInfo), 0); + case StateFlags and ISF_LOCATIONMASK of + ISF_TOOLBARCOLOR: + begin + ItemInfo.ViewType := VT_TOOLBAR; + ItemInfo.ItemOptions := IO_TOOLBARSTYLE; + end; + ISF_MENUCOLOR: + begin + ItemInfo.ViewType := VT_DOCKPANEL; + end; + ISF_STATUSCOLOR: + begin + ItemInfo.ViewType := VT_STATUSBAR; + end; + end; + ItemInfo.Enabled := not Boolean(StateFlags and ISF_DISABLED); + ItemInfo.Pushed := Boolean(StateFlags and ISF_PUSHED); + ItemInfo.HoverKind := HoverKinds[Boolean(StateFlags and ISF_HOT)]; + ItemInfo.Selected := Boolean(StateFlags and ISF_SELECTED); + CurrentTheme.PaintImage(Canvas, Rect, ItemInfo, ImageList, ImageIndex); +end; + +//============================================================================// + +{ TFontSettings } + +procedure TFontSettings.Apply(Font: TFont); +var + FS: TFontStyles; +begin + if Size <> 100 then Font.Size := (Font.Size * FSize + 50) div 100; + if Color <> clNone then Font.Color := Color; + if Name <> '' then Font.Name := Name; + FS := Font.Style; + if Bold = tsTrue then Include(FS, fsBold) + else if Bold = tsFalse then Exclude(FS, fsBold); + if Italic = tsTrue then Include(FS, fsItalic) + else if Italic = tsFalse then Exclude(FS, fsItalic); + if Underline = tsTrue then Include(FS, fsUnderline) + else if Underline = tsFalse then Exclude(FS, fsUnderline); + if StrikeOut = tsTrue then Include(FS, fsStrikeOut) + else if StrikeOut = tsFalse then Exclude(FS, fsStrikeOut); + Font.Style := FS; +end; + +procedure TFontSettings.Apply(var LF: TLogFont; var FontColor: TColor); +begin + if Size <> 100 then LF.lfHeight := (LF.lfHeight * Size + 50) div 100; + if Color <> clNone then FontColor := Color; + if Name <> '' then StrPLCopy(LF.lfFaceName, Name, 31); + if Bold = tsTrue then LF.lfWeight := FW_BOLD + else if Bold = tsFalse then LF.lfWeight := FW_NORMAL; + if Italic = tsTrue then LF.lfItalic := 1 + else if Italic = tsFalse then LF.lfItalic := 0; + if Underline = tsTrue then LF.lfUnderline := 1 + else if Underline = tsFalse then LF.lfUnderline := 0; + if StrikeOut = tsTrue then LF.lfStrikeOut := 1 + else if StrikeOut = tsFalse then LF.lfStrikeOut := 0; +end; + +procedure TFontSettings.Assign(Src: TPersistent); +var + F: TFontSettings; +begin + if Src is TPersistent then + begin + F := TFontSettings(Src); + if (FBold <> F.Bold) or (FItalic <> F.Italic) or (FUnderline <> F.Underline) or + (FStrikeOut <> F.StrikeOut) or (FSize <> F.Size) or (FColor <> F.Color) or + (FName <> F.Name) then + begin + FBold := F.Bold; + FItalic := F.Italic; + FUnderline := F.Underline; + FStrikeOut := F.StrikeOut; + FSize := F.Size; + FColor := F.Color; + FName := F.Name; + Modified; + end; + end + else inherited; +end; + +constructor TFontSettings.Create; +begin + FSize := 100; + FColor := clNone; +end; + +function TFontSettings.CreateTransformedFont(Src: HFont; var FontColor: TColor): HFont; +var + LF: TLogFont; +begin + GetObject(Src, SizeOf(LF), @LF); + Apply(LF, FontColor); + Result := CreateFontIndirect(LF); +end; + +procedure TFontSettings.Modified; +begin + if Assigned(FOnChange) then FOnChange(Self); +end; + +procedure TFontSettings.SetBold(Value: TTriState); +begin + if FBold <> Value then + begin + FBold := Value; + Modified; + end; +end; + +procedure TFontSettings.SetColor(Value: TColor); +begin + if FColor <> Value then + begin + FColor := Value; + Modified; + end; +end; + +procedure TFontSettings.SetItalic(Value: TTriState); +begin + if FItalic <> Value then + begin + FItalic := Value; + Modified; + end; +end; + +procedure TFontSettings.SetName(const Value: TFontName); +begin + if FName <> Value then + begin + FName := Value; + Modified; + end; +end; + +procedure TFontSettings.SetSize(Value: TFontSize); +begin + if FSize <> Value then + begin + FSize := Value; + Modified; + end; +end; + +procedure TFontSettings.SetStrikeOut(Value: TTriState); +begin + if FStrikeOut <> Value then + begin + FStrikeOut := Value; + Modified; + end; +end; + +procedure TFontSettings.SetUnderline(Value: TTriState); +begin + if FUnderline <> Value then + begin + FUnderline := Value; + Modified; + end; +end; + +//============================================================================// + +{ TTBXCustomItem } + +constructor TTBXCustomItem.Create(AOwner: TComponent); +begin + inherited; + FFontSettings := TFontSettings.Create; + FFontSettings.OnChange := FontSettingsChanged; +end; + +function TTBXCustomItem.CreatePopup(const ParentView: TTBView; + const ParentViewer: TTBItemViewer; const PositionAsSubmenu, + SelectFirstItem, Customizing: Boolean; const APopupPoint: TPoint; + const Alignment: TTBPopupAlignment): TTBPopupWindow; +var + DoSelectFirstItem: Boolean; +begin + if AlwaysSelectFirst then DoSelectFirstItem := True + else DoSelectFirstItem := SelectFirstItem; + Result := inherited CreatePopup(ParentView, ParentViewer, PositionAsSubmenu, + DoSelectFirstItem, Customizing, APopupPoint, Alignment); +end; + +destructor TTBXCustomItem.Destroy; +begin + FFontSettings.Free; + inherited; +end; + +procedure TTBXCustomItem.FontSettingsChanged(Sender: TObject); +begin + Change(True); +end; + +function TTBXCustomItem.GetItemViewerClass(AView: TTBView): TTBItemViewerClass; +begin + Result := TTBXItemViewer; +end; + +procedure TTBXCustomItem.GetPopupPosition(ParentView: TTBView; + PopupWindow: TTBPopupWindow; var PopupPositionRec: TTBPopupPositionRec); +var + VT: Integer; +begin + if CurrentTheme.OfficeXPPopupAlignment then with PopupPositionRec do + begin + GetOfficeXPPopupPosition1(PopupPositionRec); + inherited GetPopupPosition(ParentView, PopupWindow, PopupPositionRec); + GetOfficeXPPopupPosition2(PopupPositionRec); + VT := GetWinViewType(PopupWindow); + PopupPositionRec.PlaySound := not (VT and PVT_LISTBOX = PVT_LISTBOX); + end + else inherited; +end; + +function TTBXCustomItem.GetPopupWindowClass: TTBPopupWindowClass; +begin + Result := TTBXPopupWindow; +end; + +function TTBXCustomItem.GetStretch: Boolean; +begin + Result := tbisStretch in ItemStyle; +end; + +procedure TTBXCustomItem.Invalidate; +begin + Change(False); +end; + +procedure TTBXCustomItem.SetFontSettings(Value: TFontSettings); +begin + FFontSettings.Assign(Value); +end; + +procedure TTBXCustomItem.SetLayout(Value: TTBXItemLayout); +begin + if Value <> FLayout then + begin + FLayout := Value; + Change(True); + end; +end; + +procedure TTBXCustomItem.SetMinHeight(Value: Integer); +begin + if Value <> FMinHeight then + begin + FMinHeight := Value; + Change(True); + end; +end; + +procedure TTBXCustomItem.SetMinWidth(Value: Integer); +begin + if Value <> FMinWidth then + begin + FMinWidth := Value; + Change(True); + end; +end; + +procedure TTBXCustomItem.SetStretch(Value: Boolean); +begin + if Value xor (tbisStretch in ItemStyle) then + begin + if Value then ItemStyle := ItemStyle + [tbisStretch] + else ItemStyle := ItemStyle - [tbisStretch]; + Change(True); + end; +end; + + +//============================================================================// + +{ TTBXItemViewer } + +procedure TTBXItemViewer.CalcSize(const Canvas: TCanvas; var AWidth, AHeight: Integer); +const + CMarginIDs: array [Boolean] of Integer = (MID_MENUITEM, MID_TOOLBARITEM); + CStartSize: array [Boolean] of Integer = (0, 6); +var + W, H: Integer; + ImgSize: TSize; + Item: TTBCustomItem; + ItemLayout, SaveLayout: TTBXItemLayout; + IsCaptionShown: Boolean; + IsTextRotated: Boolean; + ToolbarStyle: Boolean; + S: string; + TextFlags: Cardinal; + TextMetric: TTextMetric; + TextSize: TSize; + Margins: TTBXMargins; +begin + Item := TTBCustomItem(Self.Item); + ToolbarStyle := IsToolbarStyle; + ImgSize := GetImageSize; + if (ImgSize.CX <= 0) or (ImgSize.CY <= 0) then + begin + ImgSize.CX := 0; + ImgSize.CY := 0; + end; + + if Item is TTBXCustomItem then ItemLayout := TTBXCustomItem(Item).Layout + else ItemLayout := tbxlAuto; + SaveLayout := ItemLayout; + if ItemLayout = tbxlAuto then + begin + if tboImageAboveCaption in Item.EffectiveOptions then ItemLayout := tbxlGlyphTop + else + begin + if View.Orientation <> tbvoVertical then ItemLayout := tbxlGlyphLeft + else ItemLayout := tbxlGlyphTop; + end; + end; + + { Setup font } + TextFlags := 0; + IsCaptionShown := CaptionShown; + IsTextRotated := (View.Orientation = tbvoVertical) and ToolbarStyle; + if IsCaptionShown then + begin + S := GetCaptionText; + if not (SaveLayout = tbxlAuto) or (tboImageAboveCaption in Item.EffectiveOptions) then IsTextRotated := False; + if IsTextRotated or not ToolbarStyle then TextFlags := DT_SINGLELINE; + TextSize := GetTextSize(Canvas, S, TextFlags, IsTextRotated, 0); + end + else + begin + SetLength(S, 0); + TextSize.CX := 0; + TextSize.CY := 0; + IsTextRotated := False; + end; + + { Measure size } + if ToolbarStyle then + begin + AWidth := 6; + AHeight := 6; + + if CaptionShown then + begin + Inc(AWidth, TextSize.CX); + Inc(AHeight, TextSize.CY); + if not IsTextRotated then Inc(AWidth, 4) + else Inc(AHeight, 4); + end; + + if GetImageShown and (ImgSize.CX > 0) and (ImgSize.CY > 0) then + begin + if ItemLayout = tbxlGlyphLeft then + begin + Inc(AWidth, ImgSize.CX); + if Wide then Inc(AWidth); + if AHeight < ImgSize.CY + 6 then AHeight := ImgSize.CY + 6; + end + else + begin + Inc(AHeight, ImgSize.CY); + if AWidth < ImgSize.CX + 7 then AWidth := ImgSize.CX + 7; + end; + end; + + if tbisSubmenu in TTBItemAccess(Item).ItemStyle then with CurrentTheme do + begin + if tbisCombo in TTBItemAccess(Item).ItemStyle then Inc(AWidth, SplitBtnArrowWidth) + else if tboDropdownArrow in Item.EffectiveOptions then + begin + if (ItemLayout <> tbxlGlyphTop) or (ImgSize.CX = 0) or IsTextRotated then + begin + if View.Orientation <> tbvoVertical then Inc(AWidth, DropdownArrowWidth) + else Inc(AHeight, DropdownArrowWidth); + end + else + begin + if (ItemLayout = tbxlGlyphTop) and (IsTextRotated xor (View.Orientation <> tbvoVertical)) then + begin + W := ImgSize.CX + DropDownArrowWidth + 2; + if W > AWidth - 7 then AWidth := W + 7; + end + else + begin + H := ImgSize.CY + DropDownArrowWidth + 2; + if H > AHeight - 7 then AHeight := H + 7; + end; + end + end; + end; + end + else // Not a ToolbarStyle + with CurrentTheme do + begin + GetTextMetrics(Canvas.Handle, TextMetric); + Inc(TextSize.CY, TextMetric.tmExternalLeading); + + AWidth := TextSize.CX; + AHeight := TextSize.CY; + + if ImgSize.CY = 0 then ImgSize.CY := 16; + if AHeight < ImgSize.CY then AHeight := ImgSize.CY; + + GetMargins(MID_MENUITEM, Margins); + Inc(AWidth, Margins.LeftWidth + Margins.RightWidth); + Inc(AHeight, Margins.TopHeight + Margins.BottomHeight); + + Inc(AWidth, GetPopupMargin(Self) + MenuImageTextSpace + MenuLeftCaptionMargin + MenuRightCaptionMargin); + S := Item.GetShortCutText; + if Length(S) > 0 then Inc(AWidth, (AHeight - 6) + GetTextWidth(Canvas.Handle, S, True)); + Inc(AWidth, AHeight); { Note: maybe this should be controlled by the theme } + end; + + if Item is TTBXCustomItem then with TTBXCustomItem(Item) do + begin + if AWidth < MinWidth then AWidth := MinWidth; + if AHeight < MinHeight then AHeight := MinHeight; + end; +end; + +constructor TTBXItemViewer.Create(AView: TTBView; AItem: TTBCustomItem; AGroupLevel: Integer); +begin + inherited; + FWide := True; +end; + +procedure TTBXItemViewer.DoAdjustFont(AFont: TFont; StateFlags: Integer); +begin + if tboDefault in Item.EffectiveOptions then with AFont do Style := Style + [fsBold]; + if Item is TTBXCustomItem then + with TTBXCustomItem(Item) do + begin + FontSettings.Apply(AFont); + if Assigned(FOnAdjustFont) then FOnAdjustFont(Item, Self, AFont, StateFlags); + end + else if Item is TTBXEditItem then + with TTBXEditItem(Item) do + begin + FontSettings.Apply(AFont); + end; +end; + +procedure TTBXItemViewer.DoPaintCaption(Canvas: TCanvas; const ClientAreaRect: TRect; + var CaptionRect: TRect; IsTextRotated: Boolean; var PaintDefault: Boolean); +begin + // do nothing +end; + +procedure TTBXItemViewer.DrawItemImage(Canvas: TCanvas; ARect: TRect; ItemInfo: TTBXItemInfo); +var + ImgList: TCustomImageList; + I: TTBXCustomItem; +begin + ImgList := GetImageList; + if (ImgList <> nil) and (Item.ImageIndex >= 0) and (Item.ImageIndex < ImgList.Count) then + begin + CurrentTheme.PaintImage(Canvas, ARect, ItemInfo, ImgList, Item.ImageIndex); + if Item is TTBXCustomItem then + begin + I := TTBXCustomItem(Item); + if Assigned(I.FOnDrawImage) then + I.FOnDrawImage(I, Self, Canvas, ARect, + CurrentTheme.GetImageOffset(Canvas, ItemInfo, ImgList), + GetStateFlags(ItemInfo)); + end; + end; +end; + +function TTBXItemViewer.GetAccRole: Integer; +{ Returns the MSAA "role" of the viewer. } +const + { Constants from OleAcc.h } + ROLE_SYSTEM_BUTTONDROPDOWNGRID = $3A; +begin + Result := inherited GetAccRole; + if (Item is TTBXCustomItem) and TTBXCustomItem(Item).ToolBoxPopup and + (tbisSubmenu in TTBXCustomItem(Item).ItemStyle) then + Result := ROLE_SYSTEM_BUTTONDROPDOWNGRID; +end; + +function TTBXItemViewer.GetImageShown: Boolean; +begin + Result := (Item.ImageIndex >= 0) and + ((Item.DisplayMode in [nbdmDefault, nbdmImageAndText]) or + (IsToolbarStyle and (Item.DisplayMode = nbdmTextOnlyInMenus))); +end; + +function TTBXItemViewer.GetImageSize: TSize; +var + ImgList: TCustomImageList; +begin + ImgList := GetImageList; + with Result do if ImgList <> nil then + begin + CX := ImgList.Width; + CY := ImgList.Height; + end + else + begin + CX := 0; + CY := 0; + end; +end; + +function TTBXItemViewer.GetItemType: Integer; +begin + if IsToolbarStyle then Result := IT_TOOLBARBUTTON + else Result := IT_MENUITEM; +end; + +function TTBXItemViewer.GetTextFlags: Cardinal; +begin + Result := 0; + if not AreKeyboardCuesEnabled and (vsUseHiddenAccels in View.Style) and + not (vsShowAccels in View.State) then Result := DT_HIDEPREFIX; +end; + +function TTBXItemViewer.GetTextSize(Canvas: TCanvas; const Text: string; + TextFlags: Cardinal; Rotated: Boolean; StateFlags: Integer): TSize; +var + DC: HDC; + R: TRect; + RotatedFont, SaveFont: HFONT; + TextMetric: TTextMetric; +begin + { note: rotated font size is consistent only for single-line captions! } + if Length(Text) = 0 then with Result do + begin + CX := 0; + CY := 0; + Exit; + end; + + { Select proper font } + Canvas.Font := TTBViewAccess(View).GetFont; + DoAdjustFont(Canvas.Font, StateFlags); + + if not Rotated then with R, Result do + begin + Left := 0; Right := 1; + Top := 0; Bottom := 0; + DrawText(Canvas.Handle, PChar(Text), Length(Text), R, TextFlags or DT_CALCRECT); + CX := Right; + CY := Bottom; + end + else + begin + DC := Canvas.Handle; + RotatedFont := CreateRotatedFont(DC); + SaveFont := SelectObject(DC, RotatedFont); + GetTextMetrics(DC, TextMetric); + Result.CX := TextMetric.tmHeight; + Result.CY := GetTextWidth(DC, Text, True); + SelectObject(DC, SaveFont); + DeleteObject(RotatedFont); + end; +end; + +function TTBXItemViewer.IsPtInButtonPart(X, Y: Integer): Boolean; +var + W: Integer; +begin + Result := not (tbisSubmenu in TTBItemAccess(Item).ItemStyle); + if (tbisCombo in TTBItemAccess(Item).ItemStyle) then + begin + if IsToolbarStyle then W := CurrentTheme.SplitBtnArrowWidth + else W := GetSystemMetrics(SM_CXMENUCHECK); + Result := X < (BoundsRect.Right - BoundsRect.Left) - W; + end; +end; + +function TTBXItemViewer.IsToolbarSize: Boolean; +begin + Result := inherited IsToolbarSize; + Result := Result or ((GetViewType(View) and PVT_TOOLBOX) = PVT_TOOLBOX); +end; + +function TTBXItemViewer.IsToolbarStyle: Boolean; +begin + Result := inherited IsToolbarStyle; + Result := Result or ((GetViewType(View) and PVT_TOOLBOX) = PVT_TOOLBOX); +end; + +procedure TTBXItemViewer.MouseUp(X, Y: Integer; MouseWasDownOnMenu: Boolean); +begin + inherited; + { Force the item to behave as a 'normal' menu item + That is make it respond to mouse as an item with IsToolbarStyle = False } + if Item.Enabled and not ((tbisSubmenu in TTBItemAccess(Item).ItemStyle) and + not IsPtInButtonPart(X, Y)) then + begin + if View.MouseOverSelected then + begin + Execute(True); + end; + end; +end; + +procedure TTBXItemViewer.Paint(const Canvas: TCanvas; + const ClientAreaRect: TRect; IsHoverItem, IsPushed, UseDisabledShadow: Boolean); +const + CToolbarStyle: array [Boolean] of Integer = (0, IO_TOOLBARSTYLE); + CCombo: array [Boolean] of Integer = (0, IO_COMBO); + CSubmenuItem: array [Boolean] of Integer = (0, IO_SUBMENUITEM); + CDesigning: array [Boolean] of Integer = (0, IO_DESIGNING); + CAppActive: array [Boolean] of Integer = (0, IO_APPACTIVE); +var + Item: TTBXCustomItem; + View: TTBViewAccess; + ItemInfo: TTBXItemInfo; + + {M: Integer;} {vb-} + R: TRect; + ComboRect: TRect; + CaptionRect: TRect; + ImageRect: TRect; + C: TColor; + + ToolbarStyle: Boolean; + HasArrow: Boolean; + IsSplit: Boolean; + ImageIsShown: Boolean; + ImageOrCheckShown: Boolean; + ImgAndArrowWidth: Integer; + ImgSize: TSize; + IsComboPushed: Boolean; + IsCaptionShown: Boolean; + IsTextRotated: Boolean; + ItemLayout: TTBXItemLayout; + PaintDefault: Boolean; + S: string; + StateFlags: Integer; + IsSpecialDropDown: Boolean; + TextFlags: Cardinal; + TextMetrics: TTextMetric; + TextSize: TSize; + Margins: TTBXMargins; +begin + Item := TTBXCustomItem(Self.Item); + View := TTBViewAccess(Self.View); + + ToolbarStyle := IsToolbarStyle; + IsSplit := tbisCombo in Item.ItemStyle; + IsComboPushed := IsSplit and IsPushed and not View.Capture; + if IsComboPushed then IsPushed := False; + + if GetImageShown then + begin + ImgSize := GetImageSize; + with ImgSize do if (CX <= 0) or (CY <= 0) then + begin + CX := 0; + CY := 0; + ImageIsShown := False; + end + else ImageIsShown := True; + end + else + begin + ImgSize.CX := 0; + ImgSize.CY := 0; + ImageIsShown := False; + end; + IsSplit := tbisCombo in Item.ItemStyle; + + FillChar(ItemInfo, SizeOf(ItemInfo), 0); + ItemInfo.ViewType := GetViewType(View); + ItemInfo.ItemOptions := CToolbarStyle[ToolbarStyle] or CCombo[IsSplit] or + CDesigning[csDesigning in Item.ComponentState] or CSubmenuItem[tbisSubmenu in Item.ItemStyle] or + CAppActive[Application.Active]; + ItemInfo.Enabled := Item.Enabled or View.Customizing; + ItemInfo.Pushed := IsPushed; + ItemInfo.Selected := Item.Checked; + ItemInfo.ImageShown := ImageIsShown; + ItemInfo.ImageWidth := ImgSize.CX; + ItemInfo.ImageHeight := ImgSize.CY; + if IsHoverItem then + begin + if not ItemInfo.Enabled and not View.MouseOverSelected then ItemInfo.HoverKind := hkKeyboardHover + else if ItemInfo.Enabled then ItemInfo.HoverKind := hkMouseHover; + end + else ItemInfo.HoverKind := hkNone; + ItemInfo.IsPopupParent := ToolbarStyle and + (((vsModal in View.State) and Assigned(View.OpenViewer)) or (tbisSubmenu in Item.ItemStyle)) and + ((IsSplit and IsComboPushed) or (not IsSplit and IsPushed)); + ItemInfo.IsVertical := (View.Orientation = tbvoVertical) and not IsSplit; + ItemInfo.PopupMargin := GetPopupMargin(Self); + + ItemLayout := Item.Layout; + if ItemLayout = tbxlAuto then + begin + if tboImageAboveCaption in Item.EffectiveOptions then ItemLayout := tbxlGlyphTop + else if View.Orientation <> tbvoVertical then ItemLayout := tbxlGlyphLeft + else ItemLayout := tbxlGlyphTop; + end; + + HasArrow := (tbisSubmenu in Item.ItemStyle) and + ((tbisCombo in Item.ItemStyle) or (tboDropdownArrow in Item.EffectiveOptions)); + + if GetImageShown then + begin + ImgSize := GetImageSize; + with ImgSize do if (CX <= 0) or (CY <= 0) then + begin + CX := 0; + CY := 0; + ImageIsShown := False; + end + else ImageIsShown := True; + end + else + begin + ImgSize.CX := 0; + ImgSize.CY := 0; + ImageIsShown := False; + end; + ImageOrCheckShown := ImageIsShown or (not ToolbarStyle and Item.Checked); + + StateFlags := GetStateFlags(ItemInfo); + + Canvas.Font := TTBViewAccess(View).GetFont; + Canvas.Font.Color := CurrentTheme.GetItemTextColor(ItemInfo); + DoAdjustFont(Canvas.Font, StateFlags); + C := Canvas.Font.Color; + + { Setup font } + TextFlags := GetTextFlags; + IsCaptionShown := CaptionShown; + IsTextRotated := (View.Orientation = tbvoVertical) and ToolbarStyle; + if IsCaptionShown then + begin + S := GetCaptionText; + if (Item.Layout <> tbxlAuto) or (tboImageAboveCaption in Item.EffectiveOptions) then + IsTextRotated := False; + if IsTextRotated or not ToolbarStyle then TextFlags := TextFlags or DT_SINGLELINE; + TextSize := GetTextSize(Canvas, S, TextFlags, IsTextRotated, StateFlags); + end + else + begin + StateFlags := 0; + SetLength(S, 0); + IsTextRotated := False; + TextSize.CX := 0; + TextSize.CY := 0; + end; + + IsSpecialDropDown := HasArrow and not IsSplit and ToolbarStyle and + ((Item.Layout = tbxlGlyphTop) or (Item.Layout = tbxlAuto) and (tboImageAboveCaption in Item.EffectiveOptions)) and + (ImgSize.CX > 0) and not (IsTextRotated) and (TextSize.CX > 0); + + { Border & Arrows } + R := ClientAreaRect; + with CurrentTheme do if ToolbarStyle then + begin + GetMargins(MID_TOOLBARITEM, Margins); + if HasArrow then with R do + begin + ItemInfo.ComboPart := cpCombo; + if IsSplit then + begin + ItemInfo.ComboPart := cpSplitLeft; + ComboRect := R; + Dec(Right, SplitBtnArrowWidth); + ComboRect.Left := Right; + end + else if not IsSpecialDropDown then + begin + if View.Orientation <> tbvoVertical then + ComboRect := Rect(Right - DropdownArrowWidth - DropdownArrowMargin, 0, + Right - DropdownArrowMargin, Bottom) + else + ComboRect := Rect(0, Bottom - DropdownArrowWidth - DropdownArrowMargin, + Right, Bottom - DropdownArrowMargin); + end + else + begin + ImgAndArrowWidth := ImgSize.CX + DropdownArrowWidth + 2; + ComboRect.Right := (R.Left + R.Right + ImgAndArrowWidth + 2) div 2; + ComboRect.Left := ComboRect.Right - DropdownArrowWidth; + ComboRect.Top := (R.Top + R.Bottom - ImgSize.cy - 2 - TextSize.CY) div 2; + ComboRect.Bottom := ComboRect.Top + ImgSize.CY; + end; + end + else SetRectEmpty(ComboRect); + + if not IsSplit then + begin + PaintButton(Canvas, R, ItemInfo); + if HasArrow then + begin + PaintDropDownArrow(Canvas, ComboRect, ItemInfo); + if not IsSpecialDropDown then + begin + if View.Orientation <> tbvoVertical then Dec(R.Right, DropdownArrowWidth) + else Dec(R.Bottom, DropdownArrowWidth); + end; + end; + end + else // IsSplit + begin + CurrentTheme.PaintButton(Canvas, R, ItemInfo); + ItemInfo.Pushed := IsComboPushed; + ItemInfo.Selected := False; + ItemInfo.ComboPart := cpSplitRight; + CurrentTheme.PaintButton(Canvas, ComboRect, ItemInfo); + ItemInfo.ComboPart := cpSplitLeft; + ItemInfo.Pushed := IsPushed; + ItemInfo.Selected := Item.Checked; + end; + InflateRect(R, -2, -2); + end + else // not toolbar style + begin + GetMargins(MID_MENUITEM, Margins); + PaintMenuItem(Canvas, R, ItemInfo); + Inc(R.Left, Margins.LeftWidth); + Dec(R.Right, Margins.RightWidth); + Inc(R.Top, Margins.TopHeight); + Dec(R.Bottom, Margins.BottomHeight); + end; + + { Caption } + if IsCaptionShown then + begin + if ToolbarStyle then + begin + CaptionRect := R; + TextFlags := TextFlags or DT_CENTER or DT_VCENTER; + if ImageIsShown then with CaptionRect do + case ItemLayout of + tbxlGlyphLeft: + begin + Inc(Left, ImgSize.CX + 3); + Top := (Top + Bottom - TextSize.CY) div 2; + Bottom := Top + TextSize.CY; + Left := (Left + Right - TextSize.CX) div 2; + Right := Left + TextSize.CX; + TextFlags := TextFlags and not DT_CENTER; + end; + tbxlGlyphTop: + begin + Inc(Top, ImgSize.CY + 1); + if IsTextRotated then Inc(CaptionRect.Top, 3); + Top := (Top + Bottom - TextSize.CY) div 2; + Bottom := Top + TextSize.CY; + Left := (Left + Right - TextSize.CX) div 2; + Right := Left + TextSize.CX; + TextFlags := TextFlags and not DT_VCENTER; + end; + end + else + begin + with CaptionRect, TextSize do + begin + Left := (Left + R.Right - CX) div 2; + Top := (Top + R.Bottom - CY) div 2; + Right := Left + CX; + Bottom := Top + CY; + end; + end; + + Canvas.Font.Color := C; + PaintDefault := True; + DoPaintCaption(Canvas, ClientAreaRect, CaptionRect, IsTextRotated, PaintDefault); + if PaintDefault then + CurrentTheme.PaintCaption(Canvas, CaptionRect, ItemInfo, S, TextFlags, IsTextRotated); + end + else with CurrentTheme do + begin + TextFlags := DT_LEFT or DT_VCENTER or TextFlags; + TextSize := GetTextSize(Canvas, S, TextFlags, False, StateFlags); { TODO : Check if this line is required } + GetTextMetrics(Canvas.Handle, TextMetrics); + + CaptionRect := R; + Inc(CaptionRect.Left, ItemInfo.PopupMargin + MenuImageTextSpace + MenuLeftCaptionMargin); + with TextMetrics, CaptionRect do + if (Bottom - Top) - (tmHeight + tmExternalLeading) = Margins.BottomHeight then Dec(Bottom); + Inc(CaptionRect.Top, TextMetrics.tmExternalLeading); + + CaptionRect.Right := CaptionRect.Left + TextSize.CX; + + Canvas.Font.Color := C; + PaintDefault := True; + DoPaintCaption(Canvas, ClientAreaRect, CaptionRect, IsTextRotated, PaintDefault); + if PaintDefault then + CurrentTheme.PaintCaption(Canvas, CaptionRect, ItemInfo, S, TextFlags, IsTextRotated); + end; + end; + + { Shortcut and/or submenu arrow (menus only) } + if not ToolbarStyle then + begin + S := Item.GetShortCutText; + if Length(S) > 0 then + begin + CaptionRect := R; + with CaptionRect, TextMetrics do + begin + Left := Right - (Bottom - Top) - GetTextWidth(Canvas.Handle, S, True); + if (Bottom - Top) - (tmHeight + tmExternalLeading) = Margins.BottomHeight then Dec(Bottom); + Inc(Top, TextMetrics.tmExternalLeading); + end; + Canvas.Font.Color := C; + PaintDefault := True; + DoPaintCaption(Canvas, ClientAreaRect, CaptionRect, IsTextRotated, PaintDefault); + if PaintDefault then + CurrentTheme.PaintCaption(Canvas, CaptionRect, ItemInfo, S, TextFlags, False); + end; + end; + + { Image, or check box } + if ImageOrCheckShown then + begin + ImageRect := R; + + if ToolBarStyle then + begin + if IsSpecialDropDown then OffsetRect(ImageRect, (-CurrentTheme.DropdownArrowWidth + 1) div 2, 0); + if ItemLayout = tbxlGlyphLeft then ImageRect.Right := ImageRect.Left + ImgSize.CX + 2 + else + begin + ImageRect.Top := (ImageRect.Top + ImageRect.Bottom - ImgSize.cy - 2 - TextSize.cy) div 2; + ImageRect.Bottom := ImageRect.Top + ImgSize.CY; + end; + end + else ImageRect.Right := ImageRect.Left + ClientAreaRect.Bottom - ClientAreaRect.Top; + + if ImageIsShown then with ImageRect, ImgSize do + begin + Left := Left + ((Right - Left) - CX) div 2; + ImageRect.Top := Top + ((Bottom - Top) - CY) div 2; + Right := Left + CX; + Bottom := Top + CY; + DrawItemImage(Canvas, ImageRect, ItemInfo); + end + {else if not ToolbarStyle and Item.Checked then + CurrentTheme.PaintCheckMark(Canvas, ImageRect, ItemInfo);} {vb-} + else {vb+} + if not ToolbarStyle and Item.Checked then + begin + if Item.RadioItem then + with ItemInfo do ItemOptions := ItemOptions or IO_RADIO; + CurrentTheme.PaintCheckMark(Canvas, ImageRect, ItemInfo); + end; + end; +end; + + +//============================================================================// + +{ TTBXSubmenuItem } + +constructor TTBXSubmenuItem.Create(AOwner: TComponent); +begin + inherited; + ItemStyle := ItemStyle + [tbisSubMenu, tbisSubitemsEditable]; +end; + +function TTBXSubmenuItem.GetDropdownCombo: Boolean; +begin + Result := tbisCombo in ItemStyle; +end; + +procedure TTBXSubmenuItem.SetDropdownCombo(Value: Boolean); +begin + if (tbisCombo in ItemStyle) <> Value then begin + if Value then ItemStyle := ItemStyle + [tbisCombo] + else ItemStyle := ItemStyle - [tbisCombo]; + Change (True); + end; +end; + + + +//============================================================================// + +{ TTBXSeparatorItem } + +constructor TTBXSeparatorItem.Create(AOwner: TComponent); +begin + inherited; + FSize := -1; // use default from as in TTBSeparatorItem +end; + +function TTBXSeparatorItem.GetItemViewerClass(AView: TTBView): TTBItemViewerClass; +begin + Result := TTBXSeparatorItemViewer; +end; + +procedure TTBXSeparatorItem.SetSize(Value: Integer); +begin + if Value < -1 then Value := -1; + if Value <> FSize then + begin + FSize := Value; + Change(True); + end; +end; + + +//============================================================================// + +{ TTBXSeparatorItemViewer } + +procedure TTBXSeparatorItemViewer.CalcSize(const Canvas: TCanvas; + var AWidth, AHeight: Integer); +var + SZ: Integer; +begin + SZ := TTBXSeparatorItem(Item).Size; + if SZ < 0 then + begin + if not IsToolbarStyle then SZ := CurrentTheme.MenuSeparatorSize + else SZ := CurrentTheme.TlbrSeparatorSize; + if SZ < 0 then inherited CalcSize(Canvas, AWidth, AHeight) + else + begin + AWidth := SZ; + AHeight := SZ; + end; + end + else if not IsToolbarStyle then + begin + AHeight := SZ; + AWidth := 0; + end + else + begin + AWidth := SZ; + AHeight := SZ; + end; +end; + +function TTBXSeparatorItemViewer.IsToolbarSize: Boolean; +begin + Result := inherited IsToolbarSize; + Result := Result or ((GetViewType(View) and PVT_TOOLBOX) = PVT_TOOLBOX); +end; + +function TTBXSeparatorItemViewer.IsToolbarStyle: Boolean; +begin + Result := inherited IsToolbarStyle; + Result := Result or ((GetViewType(View) and PVT_TOOLBOX) = PVT_TOOLBOX); +end; + +procedure TTBXSeparatorItemViewer.Paint(const Canvas: TCanvas; + const ClientAreaRect: TRect; IsHoverItem, IsPushed, UseDisabledShadow: Boolean); +const + CToolbarStyle: array [Boolean] of Integer = (0, IO_TOOLBARSTYLE); + CDesigning: array [Boolean] of Integer = (0, IO_DESIGNING); +var + Item: TTBXSeparatorItem; + ItemInfo: TTBXItemInfo; + R: TRect; + LineSep, HorzLine: Boolean; +begin + Item := TTBXSeparatorItem(Self.Item); + if Item.Size = 0 then Exit; + + FillChar(ItemInfo, SizeOf(TTBXItemInfo), 0); + ItemInfo.ViewType := GetViewType(View); + ItemInfo.ItemOptions := CToolbarStyle[IsToolbarStyle] or + CDesigning[csDesigning in Item.ComponentState]; + ItemInfo.Enabled := not Item.Blank; + ItemInfo.Pushed := IsPushed; + ItemInfo.Selected := False; + ItemInfo.ImageShown := False; + ItemInfo.ImageWidth := 0; + ItemInfo.ImageHeight := 0; + ItemInfo.IsVertical := View.Orientation = tbvoVertical; + if not IsToolbarStyle then ItemInfo.PopupMargin := GetPopupMargin(Self); + + R := ClientAreaRect; + LineSep := tbisLineSep in State; + with ItemInfo do + begin + HorzLine := (IsVertical xor LineSep) or View.IsPopup; + if (((ViewType and VT_POPUP) = VT_POPUP) and + ((ViewType and PVT_CHEVRONMENU) = PVT_CHEVRONMENU)) then + HorzLine := (HorzLine and LineSep); + end; + CurrentTheme.PaintSeparator(Canvas, R, ItemInfo, HorzLine, LineSep); +end; + +//============================================================================// + +{ TTBXVisibilityToggleItem } + +procedure TTBXVisibilityToggleItem.Click; +begin + if Assigned(FControl) then FControl.Visible := not FControl.Visible; + inherited; +end; + +procedure TTBXVisibilityToggleItem.InitiateAction; +begin + UpdateProps; +end; + +procedure TTBXVisibilityToggleItem.Notification(AComponent: TComponent; Operation: TOperation); +begin + inherited; + if (Operation = opRemove) and (AComponent = FControl) then Control := nil; +end; + +procedure TTBXVisibilityToggleItem.SetControl(Value: TControl); +begin + if FControl <> Value then + begin + FControl := Value; + if Assigned(Value) then + begin + Value.FreeNotification(Self); + if (Length(Caption) = 0) and not (csLoading in ComponentState) then + Caption := TControlAccess(Value).Caption; + end; + UpdateProps; + end; +end; + +procedure TTBXVisibilityToggleItem.UpdateProps; +begin + if (ComponentState * [csDesigning, csLoading, csDestroying] = []) then + Checked := Assigned(FControl) and FControl.Visible; +end; + +//============================================================================// + +{ TTBXPopupWindow } + +procedure TTBXPopupWindow.CMHintShow(var Message: TCMHintShow); +begin + with Message.HintInfo^ do + begin + HintStr := ''; + if Assigned(View.Selected) then + begin + CursorRect := View.Selected.BoundsRect; + HintStr := View.Selected.GetHintText; + View.Selected.Dispatch(Message); + end; + end; +end; + +procedure TTBXPopupWindow.CMShowingChanged(var Message: TMessage); {vb+} +const + ShowFlags: array[Boolean] of UINT = ( + SWP_NOSIZE or SWP_NOMOVE or SWP_NOZORDER or SWP_NOACTIVATE or SWP_HIDEWINDOW, + SWP_NOSIZE or SWP_NOMOVE or SWP_NOZORDER or SWP_NOACTIVATE or SWP_SHOWWINDOW); +var + MenuAni: TMenuAnimation; + AniDir: TTBAnimationDirection; +begin + { Must override TCustomForm/TForm's CM_SHOWINGCHANGED handler so that the + form doesn't get activated when Visible is set to True. } + + { Handle animation. NOTE: I do not recommend trying to enable animation on + Windows 95 and NT 4.0 because there's a difference in the way the + SetWindowPos works on those versions. See the comment in the + TBStartAnimation function of TB2Anim.pas. } + {$IFNDEF TBX_NO_ANIMATION} + if ((View.ParentView = nil) or not(vsNoAnimation in View.ParentView.State)) and + Showing and (View.Selected = nil) and not IsWindowVisible(WindowHandle) and + (TBXMenuAnimation.AnimationMode <> amNone) then + begin + { Start animation only if WM_TB2K_POPUPSHOWING returns zero (or not handled) } + if SendMessage(WindowHandle, WM_TB2K_POPUPSHOWING, TPS_ANIMSTART, 0) = 0 then + begin + MenuAni := TBXMenuAnimation.MenuAnimation; + AniDir := TTBPopupWindowAccess(Self).AnimationDirection; + if MenuAni = maUnfold then + if [tbadDown, tbadUp] * AniDir <> [] + then Include(AniDir, tbadRight) + else Include(AniDir, tbadDown); + TBStartAnimation(WindowHandle, MenuAni = maFade, AniDir); + Exit; + end; + end; + {$ENDIF} + + { No animation... } + if not Showing then begin + { Call TBEndAnimation to ensure WS_EX_LAYERED style is removed before + hiding, otherwise windows under the popup window aren't repainted + properly. } + TBEndAnimation(WindowHandle); + end; + SetWindowPos(WindowHandle, 0, 0, 0, 0, 0, ShowFlags[Showing]); + if Showing then SendNotifyMessage(WindowHandle, WM_TB2K_POPUPSHOWING, TPS_NOANIM, 0); +end; + +procedure TTBXPopupWindow.CreateParams(var Params: TCreateParams); +const + CS_DROPSHADOW = $00020000; +begin + inherited CreateParams(Params); + with Params do + begin + WindowClass.Style := WindowClass.Style and not (CS_DROPSHADOW or CS_DBLCLKS); + if GetShowShadow and (CurrentTheme.GetPopupShadowType = PST_WINDOWSXP) and IsWindowsXP then + begin + WindowClass.Style := WindowClass.Style or CS_DROPSHADOW; + StrPCopy(WinClassName, ClassName + 'S'); + end; + end; +end; + +procedure TTBXPopupWindow.CreateShadow; +var + PR: TRect; + ParentViewer: TTBItemViewer; + VT: Integer; + ChevronParent: Boolean; +begin + if (CurrentTheme.GetPopupShadowType = PST_WINDOWS2K) and not + ((Win32Platform = VER_PLATFORM_WIN32_NT) and (Win32MajorVersion >= 5)) then Exit; + + PR := Rect(0, 0, 0, 0); + if CurrentTheme.GetPopupShadowType = PST_OFFICEXP then + begin + if (View <> nil) and (View.ParentView <> nil) then + begin + ParentViewer := TTBViewAccess(View.ParentView).OpenViewer; + ChevronParent := Self is TTBXChevronPopupWindow; + if ((ParentViewer is TTBXItemViewer) or ChevronParent) then + begin + VT := GetViewType(ParentViewer.View); + if ((VT and PVT_POPUPMENU) <> PVT_POPUPMENU) or ChevronParent then + begin + PR := ParentViewer.BoundsRect; + PR.TopLeft := View.ParentView.Window.ClientToScreen(PR.TopLeft); + PR.BottomRight := View.ParentView.Window.ClientToScreen(PR.BottomRight); + end; + end; + end + else if not IsRectEmpty(FControlRect) then + begin + PR := FControlRect; + end; + end; + FShadows := TShadows.Create(PR, BoundsRect, 4, 61, TBXLoColor); + FShadows.Show(Handle); +end; + +destructor TTBXPopupWindow.Destroy; +begin + DestroyShadow; + inherited; +end; + +procedure TTBXPopupWindow.DestroyShadow; +var + SaveShadows: TObject; +begin + SaveShadows := FShadows; + FShadows := nil; + SaveShadows.Free; +end; + +function TTBXPopupWindow.GetFillColor: TColor; +begin + Result := CurrentTheme.GetViewColor(GetViewType(View)); + View.BackgroundColor := Result; +end; + +function TTBXPopupWindow.GetNCSize: TPoint; +begin + Result := inherited GetNCSize; + CurrentTheme.GetViewBorder(GetViewType(View), Result); +end; + +function TTBXPopupWindow.GetShowShadow: Boolean; +begin + Result := ((GetViewType(View) and PVT_LISTBOX) <> PVT_LISTBOX ); +end; + +function TTBXPopupWindow.GetViewClass: TTBViewClass; +begin + Result := TTBXPopupView; +end; + +procedure TTBXPopupWindow.PaintScrollArrows; {vb+} + + function _GetPopupMargin: Integer; + begin + if View.ParentView <> nil then + Result := GetPopupMargin(TTBViewAccess(View.ParentView).OpenViewer) + else if View.ViewerCount > 0 then + Result := GetPopupMargin(View.Viewers[0]) + else Result := -1; + end; + + procedure DrawArrows; + var + ItemInfo: TTBXItemInfo; + Index: Integer; + begin + FillChar(ItemInfo, SizeOf(ItemInfo), 0); + ItemInfo.ViewType := PVT_POPUPMENU; + ItemInfo.Enabled := True; + ItemInfo.PopupMargin := _GetPopupMargin; + if ItemInfo.PopupMargin > 0 then + begin + if TTBViewAccess(View).ShowUpArrow then + for Index := 0 to View.ViewerCount- 1 do + if View.Viewers[Index].Show then + begin + CurrentTheme.PaintMenuItemFrame(Canvas, Rect(0, 0, ClientWidth, + View.Viewers[Index].BoundsRect.Top), ItemInfo); + Break; + end; + if TTBViewAccess(View).ShowDownArrow then + for Index := View.ViewerCount- 1 downto 0 do + if View.Viewers[Index].Show then + begin + CurrentTheme.PaintMenuItemFrame(Canvas, Rect(0, + View.Viewers[Index].BoundsRect.Bottom, ClientWidth, + ClientHeight), ItemInfo); + Break; + end; + end; + end; + +begin + with TTBViewAccess(View) do + if ShowUpArrow or ShowDownArrow then + DrawArrows; + inherited; +end; + +procedure TTBXPopupWindow.TBMGetViewType(var Message: TMessage); +var + PI: TTBCustomItem; +begin + Message.Result := PVT_POPUPMENU; + if View <> nil then + if Self is TTBXChevronPopupWindow then + Message.Result := PVT_CHEVRONMENU + else + begin + PI := View.ParentItem; + if PI <> nil then + begin + if (PI.Count = 1) and (PI.Items[0] is TTBXCustomList) then + Message.Result := PVT_LISTBOX + else if PI is TTBXEditItem then + begin + Message.Result := PVT_TOOLBOX; + end + else if (PI is TTBXCustomItem) and (TTBXCustomItem(PI).ToolBoxPopup) then + Message.Result := PVT_TOOLBOX + end; + end; +end; + +procedure TTBXPopupWindow.WMEraseBkgnd(var Message: TWmEraseBkgnd); +var + Canvas: TCanvas; + R: TRect; +begin + TBEndAnimation(WindowHandle); + Canvas := TCanvas.Create; + Canvas.Handle := Message.DC; + R := ClientRect; + CurrentTheme.PaintBackgnd(Canvas, R, R, R, GetFillColor, False, GetViewType(View)); + Canvas.Handle := 0; + Canvas.Free; + Message.Result := 1; +end; + +procedure TTBXPopupWindow.WMNCCalcSize(var Message: TWMNCCalcSize); +var + Sz: TPoint; +begin + CurrentTheme.GetViewBorder(GetViewType(View), Sz); + with Message.CalcSize_Params^.rgrc[0], Sz do + begin + Inc(Left, X); + Inc(Top, Y); + Dec(Right, X); + Dec(Bottom, Y); + end; + Message.Result := 1; +end; + +procedure TBXPopupNCPaintProc(Wnd: HWND; DC: HDC; AppData: Longint); +var + R, R2: TRect; + Canvas: TCanvas; + View: TTBPopupView; + PopupInfo: TTBXPopupInfo; + ParentViewer: TTBItemViewer; +begin + Assert(DC <> 0, 'TBXPopupNCPaintProc'); + Canvas := TCanvas.Create; + try + Canvas.Handle := DC; + FillChar(PopupInfo, SizeOf(PopupInfo), 0); + View := TTBPopupView(AppData); + PopupInfo.WindowHandle := View.Window.Handle; + PopupInfo.ViewType := GetViewType(View); + if View.ParentView <> nil then + begin + ParentViewer := TTBViewAccess(View.ParentView).OpenViewer; + if ((ParentViewer is TTBXItemViewer) or (View.Window is TTBXChevronPopupWindow)) + and TTBItemViewerAccess(ParentViewer).IsToolbarStyle then + begin + R := ParentViewer.BoundsRect; + R.TopLeft := View.ParentView.Window.ClientToScreen(R.TopLeft); + R.BottomRight := View.ParentView.Window.ClientToScreen(R.BottomRight); + GetWindowRect(Wnd, R2); + OffsetRect(R, -R2.Left, -R2.Top); + PopupInfo.ParentRect := R; + end; + end + else if View.ParentItem is TTBXRootItem then + begin + R := TTBXRootItem(View.ParentItem).FPopupControlRect; + if not IsRectEmpty(R) then + begin + GetWindowRect(Wnd, R2); + OffsetRect(R, -R2.Left, -R2.Top); + PopupInfo.ParentRect := R; + end; + end; + GetWindowRect(Wnd, R); + OffsetRect(R, -R.Left, -R.Top); + CurrentTheme.GetViewBorder(PopupInfo.ViewType, PopupInfo.BorderSize); + R2 := R; + with PopupInfo.BorderSize do InflateRect(R2, -X, -Y); + with R2 do ExcludeClipRect(Canvas.Handle, Left, Top, Right, Bottom); + CurrentTheme.PaintPopupNCArea(Canvas, R, PopupInfo); + finally + Canvas.Handle := 0; + Canvas.Free; + end; +end; + +procedure TTBXPopupWindow.WMNCPaint(var Message: TMessage); +var + DC: HDC; +begin + DC := GetWindowDC(Handle); + try + Assert(DC <> 0, 'TTBXPopupWindow.WMNCPaint'); + SelectNCUpdateRgn(Handle, DC, HRGN(Message.WParam)); + TBXPopupNCPaintProc(Handle, DC, LongInt(Self.View)); + finally + ReleaseDC(Handle, DC); + end; +end; + +procedure TTBXPopupWindow.WMPrint(var Message: TMessage); +begin + HandleWMPrint(Handle, Message, TBXPopupNCPaintProc, LongInt(Self.View)); +end; + +procedure TTBXPopupWindow.WMTB2kPopupShowing(var Message: TMessage); +begin + if Message.WParam in [TPS_ANIMFINISHED, TPS_NOANIM] then + begin + if not (csDestroying in ComponentState) and GetShowShadow and + (CurrentTheme.GetPopupShadowType in [PST_OFFICEXP, PST_WINDOWS2K]) then CreateShadow; + end; +end; + +procedure TTBXPopupWindow.WMWindowPosChanged(var Message: TWMWindowPosChanged); +begin + inherited; + with Message.WindowPos^ do + if ((flags and SWP_SHOWWINDOW) = 0) and ((flags and SWP_HIDEWINDOW) = 0) then + begin + if FShadows <> nil then + begin + DestroyShadow; + CreateShadow; + end; + end; +end; + + +//============================================================================// + +{ TTBXToolbarView } + +procedure TTBXToolbarView.GetMargins(AOrientation: TTBViewOrientation; var Margins: TRect); +var + VT: Integer; + M: TTBXMargins; +begin + VT := GetWinViewType(TTBXToolbar(Owner)); + if (VT and VT_TOOLBAR) = VT_TOOLBAR then + begin + if AOrientation = tbvoFloating then VT := VT or TVT_FLOATING + else VT := VT and not TVT_FLOATING + end + else if (VT and VT_DOCKPANEL) = VT_DOCKPANEL then + begin + if AOrientation = tbvoFloating then VT := VT or DPVT_FLOATING + else VT := VT and not DPVT_FLOATING + end; + CurrentTheme.GetViewMargins(VT, M); + Margins.Left := M.LeftWidth; + Margins.Top := M.TopHeight; + Margins.Right := M.RightWidth; + Margins.Bottom := M.BottomHeight; +end; + + +//============================================================================// + +{ TTBXToolbar } + +procedure TTBXToolbar.CMColorChanged(var Message: TMessage); +begin + UpdateEffectiveColor; + if Docked and HandleAllocated then + begin + RedrawWindow(Handle, nil, 0, RDW_FRAME or RDW_INVALIDATE or + RDW_ERASE or RDW_UPDATENOW or RDW_ALLCHILDREN); + end; + UpdateChildColors; + Invalidate; +end; + +procedure TTBXToolbar.CMControlChange(var Message: TCMControlChange); +begin + inherited; + if Message.Inserting and (Color = clNone) then + Message.Control.Perform(CM_PARENTCOLORCHANGED, 1, EffectiveColor); +end; + +procedure TTBXToolbar.CMParentColorChanged(var Message: TMessage); +begin + if Embedded and (Color = clNone) then + begin + UpdateEffectiveColor; + if (Message.WParam = 0) then + begin + Message.WParam := 1; + Message.LParam := EffectiveColor; + end; + end; + inherited; + Invalidate; +end; + +constructor TTBXToolbar.Create(AOwner: TComponent); +begin + inherited; + AddThemeNotification(Self); + FEffectiveColor := Color; + Color := clNone; + ControlStyle := ControlStyle - [csOpaque]; + DblClickUndock := False; +end; + +destructor TTBXToolbar.Destroy; +begin + RemoveThemeNotification(Self); + inherited; +end; + +procedure TTBXToolbar.DrawNCArea(const DrawToDC: Boolean; const ADC: HDC; const Clip: HRGN); +var + DC: HDC; + R, CR, R2: TRect; + ACanvas: TCanvas; + ToolbarInfo: TTBXToolbarInfo; + UsingBackground: Boolean; +begin + if not Docked or not HandleAllocated then Exit; + + if not DrawToDC then DC := GetWindowDC(Handle) + else DC := ADC; + + UsingBackground := TDockAccess(CurrentDock).UsingBackground; + + try + GetToolbarInfo(ToolbarInfo); + GetWindowRect(Handle, R); + OffsetRect(R, -R.Left, -R.Top); + if not DrawToDC then + begin + SelectNCUpdateRgn(Handle, DC, Clip); + CR := R; + with ToolbarInfo.BorderSize, CR do + begin + InflateRect(CR, -X, -Y); + if ToolbarInfo.IsVertical then Inc(Top, GetTBXDragHandleSize(ToolbarInfo)) + else Inc(Left, GetTBXDragHandleSize(ToolbarInfo)); + ExcludeClipRect(DC, Left, Top, Right, Bottom); + end; + end; + + ACanvas := TCanvas.Create; + try + ACanvas.Handle := DC; + if CurrentTheme.SolidToolbarNCArea then + begin + ACanvas.Brush.Color := EffectiveColor; + ACanvas.Brush.Style := bsSolid; + end + else if UsingBackground then + begin + ACanvas.Brush.Color := EffectiveColor; + R2 := CurrentDock.ClientRect; + OffsetRect(R2, -Left, -Top); + TDockAccess(CurrentDock).DrawBackground(DC, R2); + if (Color = clNone) and CurrentDock.BackgroundOnToolbars then + ACanvas.Brush.Style := bsClear; + end + else + begin + ACanvas.Brush.Color := GetEffectiveColor(CurrentDock); + ACanvas.FillRect(R); + ACanvas.Brush.Color := EffectiveColor; + ACanvas.Brush.Style := bsSolid; + end; + + CurrentTheme.PaintToolbarNCArea(ACanvas, R, ToolbarInfo); + finally + ACanvas.Handle := 0; + ACanvas.Free; + end; + finally + if not DrawToDC then ReleaseDC(Handle, DC); + end; +end; + +function TTBXToolbar.Embedded: Boolean; +begin + Result := not (Floating or Docked); +end; + +function TTBXToolbar.GetChevronItemClass: TTBChevronItemClass; +begin + Result := TTBXChevronItem; +end; + +function TTBXToolbar.GetFloatingBorderSize: TPoint; +begin + CurrentTheme.GetViewBorder(GetViewType(View) or TVT_FLOATING, Result); +end; + +function TTBXToolbar.GetFloatingWindowParentClass: TTBFloatingWindowParentClass; +begin + Result := TTBXFloatingWindowParent; +end; + +procedure TTBXToolbar.GetToolbarInfo(out ToolbarInfo: TTBXToolbarInfo); +begin + FillChar(ToolbarInfo, SizeOf(ToolbarInfo), 0); + ToolbarInfo.WindowHandle := Handle; + ToolbarInfo.ViewType := GetWinViewType(Self); + if CurrentDock <> nil then + ToolbarInfo.IsVertical := CurrentDock.Position in [dpLeft,dpRight]; + ToolbarInfo.AllowDrag := CurrentDock.AllowDrag; + ToolbarInfo.DragHandleStyle := Ord(DragHandleStyle); + ToolbarInfo.ClientWidth := ClientWidth; + ToolbarInfo.ClientHeight := ClientHeight; + if ToolbarInfo.AllowDrag and CloseButtonWhenDocked then + begin + ToolbarInfo.CloseButtonState := CDBS_VISIBLE; + if CloseButtonDown then ToolbarInfo.CloseButtonState := ToolbarInfo.CloseButtonState or CDBS_PRESSED + else if CloseButtonHover then ToolbarInfo.CloseButtonState := ToolbarInfo.CloseButtonState or CDBS_HOT; + end; + ToolbarInfo.BorderStyle := BorderStyle; + CurrentTheme.GetViewBorder(ToolbarInfo.ViewType, ToolbarInfo.BorderSize); + ToolbarInfo.EffectiveColor := EffectiveColor; +end; + +function TTBXToolbar.GetViewClass: TTBToolbarViewClass; +begin + Result := TTBXToolbarView; +end; + +procedure TTBXToolbar.SetItemTransparency(const Value: TTBXItemTransparency); +begin + FItemTransparency := Value; + Invalidate; +end; + +procedure TTBXToolbar.Loaded; {vb+} +begin + inherited; + UpdateEffectiveColor; +end; + +procedure TTBXToolbar.SetParent(AParent: TWinControl); +begin + inherited; + if AParent is TTBXFloatingWindowParent then + TTBXFloatingWindowParent(AParent).SnapDistance := SnapDistance; +end; + +procedure TTBXToolbar.SetSnapDistance(Value: Integer); +begin + if Value < 0 then Value := 0; + FSnapDistance := Value; + if (Parent <> nil) and (Parent is TTBXFloatingWindowParent) then + TTBXFloatingWindowParent(Parent).SnapDistance := Value; +end; + +procedure TTBXToolbar.TBMGetEffectiveColor(var Message: TMessage); +begin + Message.WParam := EffectiveColor; + Message.Result := 1; +end; + +procedure TTBXToolbar.TBMGetViewType(var Message: TMessage); +begin + if MenuBar then Message.Result := TVT_MENUBAR + else Message.Result := TVT_NORMALTOOLBAR; + if Floating then Message.Result := Message.Result or TVT_FLOATING; + if Resizable then Message.Result := Message.Result or TVT_RESIZABLE; + case ItemTransparency of + itAuto: + if not (Floating or Docked) then Message.Result := Message.Result or TVT_EMBEDDED; + itDisable: + Message.Result := Message.Result or TVT_EMBEDDED; + end; +end; + +procedure TTBXToolbar.TBMThemeChange(var Message: TMessage); +begin + case Message.WParam of + TSC_BEFOREVIEWCHANGE: BeginUpdate; + TSC_AFTERVIEWCHANGE: + begin + EndUpdate; + UpdateEffectiveColor; + if Floating then UpdateNCArea(TTBXFloatingWindowParent(Parent), GetWinViewType(Self)) + else UpdateNCArea(Self, GetWinViewType(Self)); + Invalidate; + Arrange; + UpdateChildColors; + end; + TSC_APPACTIVATE, TSC_APPDEACTIVATE: + if MenuBar then Invalidate; + end; +end; + +procedure TTBXToolbar.UpdateChildColors; +var + M: TMessage; +begin + M.Msg := CM_PARENTCOLORCHANGED; + M.WParam := 1; + M.LParam := EffectiveColor; + M.Result := 0; + Broadcast(M); +end; + +procedure TTBXToolbar.UpdateEffectiveColor; +begin + if Color = clNone then + begin + if Embedded and (Parent <> nil) then + FEffectiveColor := GetEffectiveColor(Parent) + else + FEffectiveColor := CurrentTheme.GetViewColor(GetViewType(View)); + end + else FEffectiveColor := Color; +end; + +procedure TTBXToolbar.WMEraseBkgnd(var Message: TWmEraseBkgnd); +var + Canvas: TCanvas; + R, CR: TRect; + Transparent: Boolean; +begin + Transparent := False; + CR := ClientRect; + if Color = clNone then + if Docked and (TDockAccess(CurrentDock).UsingBackground) and CurrentDock.BackgroundOnToolbars + and not CurrentTheme.SolidToolbarClientArea then + begin + R := CurrentDock.ClientRect; + R.TopLeft := ScreenToClient(CurrentDock.ClientToScreen(R.TopLeft)); + R.BottomRight := ScreenToClient(CurrentDock.ClientToScreen(R.BottomRight)); + TDockAccess(CurrentDock).DrawBackground(Message.DC, R); + Message.Result := 1; + Transparent := True; + end + else if Embedded then + begin + Transparent := True; + DrawParentBackground(Self, Message.DC, CR); + end; + + Canvas := TCanvas.Create; + Canvas.Handle := Message.DC; + try + if Docked then + begin + R := CurrentDock.ClientRect; + R.TopLeft := ScreenToClient(CurrentDock.ClientToScreen(R.TopLeft)); + R.BottomRight := ScreenToClient(CurrentDock.ClientToScreen(R.BottomRight)); + end + else R := Rect(0, 0, 0, 0); + CurrentTheme.PaintBackgnd(Canvas, R, CR, CR, EffectiveColor, Transparent, GetWinViewType(Self)); + Message.Result := 1; + finally + Canvas.Handle := 0; + Canvas.Free; + end; +end; + +procedure TTBXToolbar.WMSize(var Message: TWMSize); +var + I: Integer; + V: TTBItemViewer; + R: TRect; +begin + inherited; + if Docked and TDockAccess(CurrentDock).UsingBackground and + TDockAccess(CurrentDock).BackgroundOnToolbars and + ((CurrentDock is TTBXDock) and not TTBXDock(CurrentDock).FResizing) then + begin + for I := 0 to View.ViewerCount - 1 do + begin + V := View.Viewers[I]; + if V.Show and not IsRectEmpty(V.BoundsRect) and not (V.Item is TTBControlItem) + then View.Invalidate(V); + end; + Self.Update; + InvalidateRect(Handle, nil, True); + for I := 0 to View.ViewerCount - 1 do + begin + V := View.Viewers[I]; + if V.Show and not IsRectEmpty(V.BoundsRect) and not (V.Item is TTBControlItem) + then + begin + R := V.BoundsRect; + ValidateRect(Handle, @R); + end; + end; + end; +end; + + +//============================================================================// + +{ TTBXChevronItem } + +function TTBXChevronItem.GetItemViewerClass(AView: TTBView): TTBItemViewerClass; +begin + Result := TTBXChevronItemViewer; +end; + +procedure TTBXChevronItem.GetPopupPosition(ParentView: TTBView; + PopupWindow: TTBPopupWindow; var PopupPositionRec: TTBPopupPositionRec); +begin + if CurrentTheme.OfficeXPPopupAlignment then with PopupPositionRec do + begin + GetOfficeXPPopupPosition1(PopupPositionRec); + inherited GetPopupPosition(ParentView, PopupWindow, PopupPositionRec); + GetOfficeXPPopupPosition2(PopupPositionRec); + end + else inherited; +end; + +function TTBXChevronItem.GetPopupWindowClass: TTBPopupWindowClass; +begin + Result := TTBXChevronPopupWindow; +end; + + +//============================================================================// + +{ TTBXChevronItemViewer } + +procedure TTBXChevronItemViewer.Paint(const Canvas: TCanvas; + const ClientAreaRect: TRect; IsHoverItem, IsPushed, UseDisabledShadow: Boolean); +const + CDesigning: array [Boolean] of Integer = (0, IO_DESIGNING); +var + ItemInfo: TTBXItemInfo; +begin + FillChar(ItemInfo, SizeOf(TTBXItemInfo), 0); + ItemInfo.ViewType := GetViewType(View); + ItemInfo.ItemOptions := IO_TOOLBARSTYLE or CDesigning[csDesigning in Item.ComponentState]; + ItemInfo.Enabled := Item.Enabled or View.Customizing; + ItemInfo.Pushed := IsPushed; + ItemInfo.Selected := False; + ItemInfo.ImageShown := False; + ItemInfo.ImageWidth := 0; + ItemInfo.ImageHeight := 0; + ItemInfo.IsPopupParent := IsPushed; + if IsHoverItem then + begin + if not ItemInfo.Enabled and not TTBViewAccess(View).MouseOverSelected then ItemInfo.HoverKind := hkKeyboardHover + else if ItemInfo.Enabled then ItemInfo.HoverKind := hkMouseHover; + end + else ItemInfo.HoverKind := hkNone; + ItemInfo.IsVertical := View.Orientation = tbvoVertical; + CurrentTheme.PaintChevron(Canvas, ClientAreaRect, ItemInfo); +end; + + +//============================================================================// + +{ TTBXRootItem } + +function TTBXRootItem.CreatePopupEx(SelectFirstItem: Boolean; + const AControlRect: TRect; Alignment: TTBPopupAlignment): TTBPopupWindow; +var + SavePopupRect: TRect; + Pt: TPoint; +begin + SavePopupRect := FPopupControlRect; + try + FPopupControlRect := AControlRect; + Pt.X := AControlRect.Left; + Pt.Y := AControlRect.Bottom; + Result := inherited CreatePopup(nil, nil, False, SelectFirstItem, False, Pt, Alignment); + if Result is TTBXPopupWindow then TTBXPopupWindow(Result).FControlRect := FPopupControlRect; + finally + FPopupControlRect := SavePopupRect; + end; +end; + +procedure TTBXRootItem.GetPopupPosition(ParentView: TTBView; + PopupWindow: TTBPopupWindow; var PopupPositionRec: TTBPopupPositionRec); +var + Y2: Integer; + VT: Integer; +begin + if IsRectEmpty(FPopupControlRect) then inherited + else with PopupPositionRec do + begin + ParentItemRect := FPopupControlRect; + if Y + H > MonitorRect.Bottom then + begin + Y2 := FPopupControlRect.Top - H; + if Y2 >= MonitorRect.Top then Y := Y2; + end; + if Y < MonitorRect.Top then Y := MonitorRect.Top + else if Y + H > MonitorRect.Bottom then Y := MonitorRect.Bottom - H; + + if Alignment = tbpaRight then X := FPopupControlRect.Right - W; + + if X + W > MonitorRect.Right then X := MonitorRect.Right - W; + if X < MonitorRect.Left then X := MonitorRect.Left; + end; + if CurrentTheme.OfficeXPPopupAlignment then with PopupPositionRec do + begin + GetOfficeXPPopupPosition1(PopupPositionRec); + inherited GetPopupPosition(ParentView, PopupWindow, PopupPositionRec); + GetOfficeXPPopupPosition2(PopupPositionRec); + VT := GetWinViewType(PopupWindow); + PopupPositionRec.PlaySound := not (VT and PVT_LISTBOX = PVT_LISTBOX); + end + else inherited; +end; + +function TTBXRootItem.GetPopupWindowClass: TTBPopupWindowClass; +begin + Result := TTBXPopupWindow; +end; + +function TTBXRootItem.OpenPopupEx(const SelectFirstItem, TrackRightButton: Boolean; + const ControlRect: TRect; const Alignment: TTBPopupAlignment; + const ReturnClickedItemOnly: Boolean): TTBCustomItem; +var + ModalHandler: TTBModalHandler; + Popup: TTBPopupWindow; + DoneActionData: TTBDoneActionData; + State: TTBViewState; +begin + ModalHandler := TTBModalHandler.Create(0); + try + Popup := CreatePopupEx(SelectFirstItem, ControlRect, Alignment); + try + State := Popup.View.State; + Include(State, vsIgnoreFirstMouseUp); + TTBViewAccess(Popup.View).SetState(State); + ModalHandler.Loop(Popup.View, False, False, False, TrackRightButton); + DoneActionData := TTBViewAccess(Popup.View).DoneActionData; + finally + { Remove vsModal state from the root view before any TTBView.Destroy + methods get called, so that NotifyFocusEvent becomes a no-op } + State := Popup.View.State; + Exclude(State, vsModal); + TTBViewAccess(Popup.View).SetState(State); + Popup.Free; + end; + finally + ModalHandler.Free; + end; + Result := ProcessDoneAction(DoneActionData, ReturnClickedItemOnly); +end; + +function TTBXRootItem.PopupEx(const ControlRect: TRect; + TrackRightButton: Boolean; Alignment: TTBPopupAlignment = tbpaLeft; + ReturnClickedItemOnly: Boolean = False): TTBCustomItem; +begin + Result := OpenPopupEx(False, TrackRightButton, ControlRect, + Alignment, ReturnClickedItemOnly); +end; + + +//============================================================================// + +{ TTBXPopupMenu } + +function TTBXPopupMenu.GetRootItemClass: TTBRootItemClass; +begin + Result := TTBXRootItem; +end; + +function TTBXPopupMenu.PopupEx(const ControlRect: TRect; + ReturnClickedItemOnly: Boolean = False): TTBCustomItem; +begin + {$IFDEF JR_D5} + {$IFDEF JR_D9} + SetPopupPoint(Point(ControlRect.Left, ControlRect.Bottom)); + {$ELSE} + PPoint(@PopupPoint)^ := Point(ControlRect.Left, ControlRect.Bottom); + {$ENDIF} + {$ENDIF} + Result := TTBXRootItem(Items).PopupEx(ControlRect, TrackButton = tbRightButton, + TTBPopupAlignment(Alignment), ReturnClickedItemOnly); +end; + +procedure TTBXPopupMenu.TBMGetViewType(var Message: TMessage); +begin + Message.Result := PVT_POPUPMENU; +end; + + +//============================================================================// + +{ TTBXFloatingWindowParent } + +procedure TTBXFloatingWindowParent.CancelNCHover; +begin + if FCloseButtonHover then + begin + FCloseButtonHover := False; + if HandleAllocated and IsWindowVisible(Handle) then + DrawNCArea(False, 0, 0, [twrdCloseButton]); + end; +end; + +procedure TTBXFloatingWindowParent.CMMouseLeave(var Message: TMessage); +begin + inherited; + CancelNCHover; +end; + +procedure TTBXFloatingWindowParent.DrawNCArea(const DrawToDC: Boolean; + const ADC: HDC; const Clip: HRGN; RedrawWhat: TTBToolWindowNCRedrawWhat); +const + CDown: array [Boolean] of Integer = (0, CDBS_PRESSED); + CHover: array [Boolean] of Integer = (0, CDBS_HOT); + CBord: array [Boolean] of Integer = (0, WRP_BORDER); + CCapt: array [Boolean] of Integer = (0, WRP_CAPTION); + CBtn: array [Boolean] of Integer = (0, WRP_CLOSEBTN); +var + DC: HDC; + R: TRect; + Canvas: TCanvas; + WindowInfo: TTBXWindowInfo; + DockWindow: TTBCustomDockableWindowAccess; +begin + if not HandleAllocated then Exit; + if not DrawToDC then DC := GetWindowDC(Handle) + else DC := ADC; + try + if not DrawToDC then SelectNCUpdateRgn(Handle, DC, Clip); + GetWindowRect(Handle, R); + OffsetRect(R, -R.Left, -R.Top); + with R do IntersectClipRect(DC, Left, Top, Right, Bottom); + Canvas := TCanvas.Create; + try + Canvas.Handle := DC; + GetWindowRect(Handle, R); + OffsetRect(R, -R.Left, -R.Top); + DockWindow := TTBCustomDockableWindowAccess(DockableWindow); + + FillChar(WindowInfo, SizeOf(WindowInfo), 0); + WindowInfo.ParentHandle := Handle; + WindowInfo.WindowHandle := DockWindow.Handle; + WindowInfo.ViewType := GetWinViewType(DockWindow); + WindowInfo.ClientWidth := ClientWidth; + WindowInfo.ClientHeight := ClientHeight; + WindowInfo.ShowCaption := DockWindow.ShowCaption; + WindowInfo.FloatingBorderSize := DockWindow.GetFloatingBorderSize; + if DockWindow.CloseButton and DockWindow.ShowCaption then + begin + WindowInfo.CloseButtonState := CDBS_VISIBLE; + if CloseButtonDown then WindowInfo.CloseButtonState := WindowInfo.CloseButtonState or CDBS_PRESSED + else if CloseButtonHover then WindowInfo.CloseButtonState := WindowInfo.CloseButtonState or CDBS_HOT; + end; + WindowInfo.RedrawPart := + CBord[twrdBorder in RedrawWhat] or + CCapt[twrdCaption in RedrawWhat] or + CBtn[twrdCloseButton in RedrawWhat]; + WindowInfo.Caption := PChar(Caption); + WindowInfo.EffectiveColor := GetEffectiveColor(DockWindow); + WindowInfo.Active := not DockWindow.InactiveCaption; + Canvas.Brush.Color := WindowInfo.EffectiveColor; + CurrentTheme.PaintFloatingBorder(Canvas, R, WindowInfo); + finally + Canvas.Handle := 0; + Canvas.Free; + end; + finally + if not DrawToDC then ReleaseDC(Handle, DC); + end; +end; + +procedure TTBXFloatingWindowParent.WMEraseBkgnd(var Message: TMessage); +begin + Message.Result := 1; +end; + +procedure TTBXFloatingWindowParent.WMNCMouseLeave(var Message: TMessage); +begin + if not MouseCapture then CancelNCHover; + inherited; +end; + +procedure TTBXFloatingWindowParent.WMNCMouseMove(var Message: TWMNCMouseMove); +var + InArea: Boolean; +begin + inherited; + { Note: TME_NONCLIENT was introduced in Windows 98 and 2000 } + if (Win32MajorVersion >= 5) or + (Win32MajorVersion = 4) and (Win32MinorVersion >= 10) then + CallTrackMouseEvent (Handle, TME_LEAVE or $10 {TME_NONCLIENT}); + InArea := Message.HitTest = 2001; {HT_TB2k_Close} + if FCloseButtonHover <> InArea then + begin + FCloseButtonHover := InArea; + if HandleAllocated and IsWindowVisible(Handle) then + DrawNCArea(False, 0, 0, [twrdCloseButton]); + end; +end; + +procedure TTBXFloatingWindowParent.WMWindowPosChanging(var Message: TWMWindowPosChanging); +var + R: TRect; + MonInfo: TMonitorInfo; +begin + if SnapDistance > 0 then with Message.WindowPos^ do + begin + if (cx = Width) and (cy = Height) then + begin + MonInfo.cbSize := SizeOf(MonInfo); + GetMonitorInfo(Monitor.Handle, @MonInfo); + R := MonInfo.rcWork; + if Abs(x + Width - R.Right) < SnapDistance then x := R.Right - Width; + if Abs(y + Height - R.Bottom) < SnapDistance then y := R.Bottom - Height; + if Abs(x - R.Left) < SnapDistance then x := R.Left; + if Abs(y - R.Top) < SnapDistance then y := R.Top; + end; + end; + inherited; +end; + + +//============================================================================// + +{ TTBXToolWindow } + +procedure TTBXToolWindow.CMColorChanged(var Message: TMessage); +begin + UpdateEffectiveColor; + if Docked and HandleAllocated then + RedrawWindow(Handle, nil, 0, RDW_FRAME or RDW_INVALIDATE or + RDW_ERASE or RDW_UPDATENOW or RDW_ALLCHILDREN); + UpdateChildColors; + Invalidate; +end; + +procedure TTBXToolWindow.CMControlChange(var Message: TCMControlChange); +begin + inherited; + if Message.Inserting and (Color = clNone) then + Message.Control.Perform(CM_PARENTCOLORCHANGED, 1, EffectiveColor); +end; + +procedure TTBXToolWindow.CMTextChanged(var Message: TMessage); +begin + inherited; + if HandleAllocated then + begin + if Docked then RedrawWindow(Handle, nil, 0, RDW_FRAME or RDW_INVALIDATE) + else RedrawWindow(TTBXFloatingWindowParent(Parent).Handle, nil, 0, RDW_FRAME or RDW_INVALIDATE); + end; +end; + +constructor TTBXToolWindow.Create(AOwner: TComponent); +begin + inherited; + AddThemeNotification(Self); + DblClickUndock := False; + FEffectiveColor := Color; + Color := clNone; +end; + +destructor TTBXToolWindow.Destroy; +begin + RemoveThemeNotification(Self); + inherited; +end; + +procedure TTBXToolWindow.DrawNCArea(const DrawToDC: Boolean; + const ADC: HDC; const Clip: HRGN); +var + DC: HDC; + R, CR, R2: TRect; + ACanvas: TCanvas; + ToolbarInfo: TTBXToolbarInfo; + UsingBackground: Boolean; +begin + if not Docked or not HandleAllocated then Exit; + + if not DrawToDC then DC := GetWindowDC(Handle) + else DC := ADC; + + UsingBackground := TDockAccess(CurrentDock).UsingBackground; + + try + GetToolbarInfo(ToolbarInfo); + GetWindowRect(Handle, R); + OffsetRect(R, -R.Left, -R.Top); + if not DrawToDC then + begin + SelectNCUpdateRgn(Handle, DC, Clip); + CR := R; + with ToolbarInfo.BorderSize, CR do + begin + InflateRect(CR, -X, -Y); + if ToolbarInfo.IsVertical then Inc(Top, GetTBXDragHandleSize(ToolbarInfo)) + else Inc(Left, GetTBXDragHandleSize(ToolbarInfo)); + ExcludeClipRect(DC, Left, Top, Right, Bottom); + end; + end; + ACanvas := TCanvas.Create; + try + ACanvas.Handle := DC; + ACanvas.Brush.Color := EffectiveColor; + if CurrentTheme.SolidToolbarNCArea then + begin + ACanvas.Brush.Color := EffectiveColor; + ACanvas.Brush.Style := bsSolid; + end + else if UsingBackground then + begin + ACanvas.Brush.Color := EffectiveColor; + R2 := CurrentDock.ClientRect; + OffsetRect(R2, -Left, -Top); + TDockAccess(CurrentDock).DrawBackground(DC, R2); + if (Color = clNone) and CurrentDock.BackgroundOnToolbars then + ACanvas.Brush.Style := bsClear; + end + else + begin + ACanvas.Brush.Color := GetEffectiveColor(CurrentDock); + ACanvas.FillRect(R); + ACanvas.Brush.Color := EffectiveColor; + ACanvas.Brush.Style := bsSolid; + end; + + CurrentTheme.PaintToolbarNCArea(ACanvas, R, ToolbarInfo); + finally + ACanvas.Handle := 0; + ACanvas.Free; + end; + finally + if not DrawToDC then ReleaseDC(Handle, DC); + end; +end; + +function TTBXToolWindow.GetFloatingBorderSize: TPoint; +begin + CurrentTheme.GetViewBorder(GetWinViewType(Self) or TVT_FLOATING, Result); +end; + +function TTBXToolWindow.GetFloatingWindowParentClass: TTBFloatingWindowParentClass; +begin + Result := TTBXFloatingWindowParent; +end; + +procedure TTBXToolWindow.GetToolbarInfo(out ToolbarInfo: TTBXToolbarInfo); +begin + FillChar(ToolbarInfo, SizeOf(ToolbarInfo), 0); + ToolbarInfo.WindowHandle := WindowHandle; + ToolbarInfo.ViewType := GetWinViewType(Self); + if CurrentDock <> nil then + ToolbarInfo.IsVertical := CurrentDock.Position in [dpLeft,dpRight]; + ToolbarInfo.AllowDrag := CurrentDock.AllowDrag; + ToolbarInfo.DragHandleStyle := Ord(DragHandleStyle); + ToolbarInfo.ClientWidth := ClientWidth; + ToolbarInfo.ClientHeight := ClientHeight; + if ToolbarInfo.AllowDrag and CloseButtonWhenDocked then + begin + ToolbarInfo.CloseButtonState := CDBS_VISIBLE; + if CloseButtonDown then ToolbarInfo.CloseButtonState := ToolbarInfo.CloseButtonState or CDBS_PRESSED; + if CloseButtonHover then ToolbarInfo.CloseButtonState := ToolbarInfo.CloseButtonState or CDBS_HOT; + end; + ToolbarInfo.BorderStyle := BorderStyle; + ToolbarInfo.EffectiveColor := EffectiveColor; + CurrentTheme.GetViewBorder(ToolbarInfo.ViewType, ToolbarInfo.BorderSize); +end; + +procedure TTBXToolWindow.SetParent(AParent: TWinControl); +begin + inherited; + if AParent is TTBXFloatingWindowParent then + TTBXFloatingWindowParent(AParent).SnapDistance := SnapDistance; +end; + +procedure TTBXToolWindow.SetSnapDistance(Value: Integer); +begin + if Value < 0 then Value := 0; + FSnapDistance := Value; + if (Parent <> nil) and (Parent is TTBXFloatingWindowParent) then + TTBXFloatingWindowParent(Parent).SnapDistance := Value; +end; + +procedure TTBXToolWindow.TBMGetEffectiveColor(var Message: TMessage); +begin + Message.WParam := EffectiveColor; + Message.Result := 1; +end; + +procedure TTBXToolWindow.TBMGetViewType(var Message: TMessage); +begin + Message.Result := TVT_TOOLWINDOW; + if Floating then Message.Result := Message.Result or TVT_FLOATING; + if Resizable then Message.Result := Message.Result or TVT_RESIZABLE; +end; + +procedure TTBXToolWindow.TBMThemeChange(var Message: TMessage); +begin + case Message.WParam of + TSC_BEFOREVIEWCHANGE: BeginUpdate; + TSC_AFTERVIEWCHANGE: + begin + EndUpdate; + UpdateEffectiveColor; + if HandleAllocated and not (csDestroying in ComponentState) then + if Parent is TTBXFloatingWindowParent then + UpdateNCArea(TTBXFloatingWindowParent(Parent), GetWinViewType(Self)) + else + UpdateNCArea(Self, GetWinViewType(Self)); + UpdateChildColors; + Invalidate; + end; + end; +end; + +procedure TTBXToolWindow.UpdateChildColors; +var + M: TMessage; +begin + M.Msg := CM_PARENTCOLORCHANGED; + M.WParam := 1; + M.LParam := EffectiveColor; + M.Result := 0; + Broadcast(M); +end; + +procedure TTBXToolWindow.UpdateEffectiveColor; +begin + if Color = clNone then FEffectiveColor := CurrentTheme.GetViewColor(GetWinViewType(Self)) + else FEffectiveColor := Color; +end; + +procedure TTBXToolWindow.WMEraseBkgnd(var Message: TWmEraseBkgnd); +var + Canvas: TCanvas; + R, CR: TRect; + Transparent: Boolean; +begin + Transparent := False; + CR := ClientRect; + if Color = clNone then + if Docked and (TDockAccess(CurrentDock).UsingBackground) and CurrentDock.BackgroundOnToolbars + and not CurrentTheme.SolidToolbarClientArea then + begin + R := CurrentDock.ClientRect; + R.TopLeft := ScreenToClient(CurrentDock.ClientToScreen(R.TopLeft)); + R.BottomRight := ScreenToClient(CurrentDock.ClientToScreen(R.BottomRight)); + SaveDC(Message.DC); + with CR do IntersectClipRect(Message.DC, Left, Top, Right, Bottom); + TDockAccess(CurrentDock).DrawBackground(Message.DC, R); + RestoreDC(Message.DC, -1); + Message.Result := 1; + Transparent := True; + end; + + Canvas := TCanvas.Create; + Canvas.Handle := Message.DC; + try + if Docked then + begin + R := CurrentDock.ClientRect; + R.TopLeft := ScreenToClient(CurrentDock.ClientToScreen(R.TopLeft)); + R.BottomRight := ScreenToClient(CurrentDock.ClientToScreen(R.BottomRight)); + end + else R := Rect(0, 0, 0, 0); + CurrentTheme.PaintBackgnd(Canvas, R, CR, CR, EffectiveColor, Transparent, GetWinViewType(Self)); + Message.Result := 1; + finally + Canvas.Handle := 0; + Canvas.Free; + end; +end; + +//============================================================================// + +{ Additional system colors } + +type + TColorEntry = packed record + ColorPtr: ^TColor; + Name: string; + end; + +var + ColorRegistry: array of TColorEntry; + +procedure AddTBXColor(var AColor: TColor; const AName: string); +var + L: Integer; +begin + L := Length(ColorRegistry); + SetLength(ColorRegistry, L + 1); + with ColorRegistry[L] do + begin + ColorPtr := @AColor; + Name := AName; + end; +end; + +function TBXColorToString(Color: TColor): string; +var + I: Integer; +begin + if not ColorToIdent(Color, Result) then + begin + for I := 0 to Length(ColorRegistry) - 1 do + if ColorRegistry[I].ColorPtr^ = Color then + begin + Result := ColorRegistry[I].Name; + Exit; + end; + FmtStr(Result, '%s%.8x', [HexDisplayPrefix, Color]); + end; +end; + +function TBXIdentToColor(const Ident: string; var Color: Longint): Boolean; +var + I: Integer; +begin + for I := 0 to Length(ColorRegistry) - 1 do + if CompareText(ColorRegistry[I].Name, Ident) = 0 then + begin + Color := ColorRegistry[I].ColorPtr^; + Result := True; + Exit; + end; + Result := IdentToColor(Ident, Color); +end; + +function TBXStringToColor(S: string): TColor; +begin + if not TBXIdentToColor(S, Longint(Result)) then Result := StringToColor(S); +end; + +procedure TBXGetColorValues(Proc: TGetStrProc); +var + I: Integer; +begin + GetColorValues(Proc); + for I := 0 to Length(ColorRegistry) - 1 do Proc(ColorRegistry[I].Name); +end; + +procedure TBXSetTheme(const AThemeName: string); +begin + TBXNexus.SetTheme(AThemeName); +end; + +function TBXCurrentTheme: string; +begin + Result := TBXNexus.GetTheme; +end; + + +//============================================================================// + + +{ TTBXNexus } + +procedure TTBXNexus.AddNotifie(AObject: TObject); +begin + if FNotifies.IndexOf(AObject) < 0 then FNotifies.Add(AObject); + Exit; asm db 0,'TBX (C) 2001-2003 Alex Denisov',0 end; +end; + +procedure TTBXNexus.Broadcast(Msg: Cardinal; WParam, LParam: Integer); +var + M: TMessage; + I: Integer; +begin + if FNotifies.Count > 0 then + begin + M.Msg := Msg; + M.WParam := WParam; + M.LParam := LParam; + M.Result := 0; + for I := 0 to FNotifies.Count - 1 do TObject(FNotifies[I]).Dispatch(M); + end; +end; + +constructor TTBXNexus.Create(const DefaultTheme: string); +begin + FNotifies := TList.Create; + CurrentTheme := GetTBXTheme(DefaultTheme); + AddTBXSysChangeNotification(Self); +end; + +destructor TTBXNexus.Destroy; +begin + RemoveTBXSysChangeNotification(Self); + ReleaseTBXTheme(CurrentTheme); + FNotifies.Free; + inherited; +end; + +function TTBXNexus.GetTheme: string; +begin + Result := CurrentTheme.Name; +end; + +procedure TTBXNexus.RemoveNotifie(AObject: TObject); +begin + FNotifies.Remove(AObject); +end; + +procedure TTBXNexus.SetTheme(const AThemeName: string); +begin + if IsTBXThemeAvailable(AThemeName) then + begin + ReleaseTBXTheme(CurrentTheme); + CurrentTheme := GetTBXTheme(AThemeName); + Broadcast(TBM_THEMECHANGE, TSC_BEFOREVIEWCHANGE, 1); + Broadcast(TBM_THEMECHANGE, TSC_VIEWCHANGE, 1); + Broadcast(TBM_THEMECHANGE, TSC_AFTERVIEWCHANGE, 1); + end; +end; + +procedure TTBXNexus.TBXSysCommand(var Message: TMessage); +begin + { Retranslate TBX_SYSCOMMAND to TBM_THEMECHANGE } + if Message.Msg = TBX_SYSCOMMAND then + Broadcast(TBM_THEMECHANGE, Message.WParam, 0); +end; + +procedure InitAdditionalSysColors; +begin +{$IFNDEF JR_D7} {vb+} + AddTBXColor(clHotLight, 'clHotLight'); +{$ENDIF} {vb+} +{$IFNDEF JR_D6} + AddTBXColor(clMoneyGreen, 'clMoneyGreen'); + AddTBXColor(clSkyBlue, 'clSkyBlue'); + AddTBXColor(clCream, 'clCream'); + AddTBXColor(clMedGray, 'clMedGray'); +{$ENDIF} +end; + +{ TTBXDock } + +procedure TTBXDock.CMColorChanged(var Message: TMessage); +var + I: Integer; +begin + inherited; + for I := 0 to Self.ControlCount - 1 do + if Controls[I] is TWinControl then + InvalidateAll(TWinControl(Controls[I])); +end; + +constructor TTBXDock.Create(AOwner: TComponent); +begin + inherited; + Color := clNone; + AddThemeNotification(Self); +end; + +destructor TTBXDock.Destroy; +begin + RemoveThemeNotification(Self); + inherited; +end; + +procedure TTBXDock.DrawBackground(DC: HDC; const DrawRect: TRect); +const + DOCK_POSITIONS: array [TTBDockPosition] of Integer = (DP_TOP, DP_BOTTOM, DP_LEFT, DP_RIGHT); +var + Canvas: TCanvas; +begin + if UseParentBackground then DrawParentBackground(Self, DC, ClientRect) + else if ThemedBackground then + begin + Canvas := TCanvas.Create; + Canvas.Handle := DC; + CurrentTheme.PaintDock(Canvas, ClientRect, DrawRect, DOCK_POSITIONS[Position]); + Canvas.Handle := 0; + Canvas.Free; + end + else inherited; +end; + +procedure TTBXDock.Resize; +var + I, J: Integer; + V: TTBItemViewer; + R: TRect; +begin + inherited Resize; + if UsingBackground then + begin + for J := 0 to ToolbarCount - 1 do + begin + Invalidate; + if Toolbars[J] is TTBXToolbar then with TTBXToolbar(Toolbars[J]) do + begin + for I := 0 to View.ViewerCount - 1 do + begin + V := View.Viewers[I]; + if V.Show and not IsRectEmpty(V.BoundsRect) and not (V.Item is TTBControlItem) + then View.Invalidate(V); + end; + Update; + if HandleAllocated then + RedrawWindow(Handle, nil, 0, RDW_FRAME or RDW_INVALIDATE or RDW_ERASE); + for I := 0 to View.ViewerCount - 1 do + begin + V := View.Viewers[I]; + if V.Show and not IsRectEmpty(V.BoundsRect) and not (V.Item is TTBControlItem) + then + begin + R := V.BoundsRect; + ValidateRect(Handle, @R); + end; + end; + end + else if Toolbars[J] is TTBXToolWindow then with TTBXToolWindow(Toolbars[J]) do + begin + if HandleAllocated then + RedrawWindow(Handle, nil, 0, RDW_FRAME or RDW_INVALIDATE or RDW_ERASE); + end; + end; + end; +end; + +procedure TTBXDock.SetUseParentBackground(Value: Boolean); +begin + if Value <> FUseParentBackground then + begin + FUseParentBackground := Value; + if HandleAllocated then + RedrawWindow(Handle, nil, 0, RDW_FRAME or RDW_INVALIDATE or + RDW_ERASE or RDW_ALLCHILDREN); + end; +end; + +procedure TTBXDock.TBMGetEffectiveColor(var Message: TMessage); +begin + if Color <> clNone then Message.WParam := Color + else if Parent <> nil then Message.WParam := GetEffectiveColor(Parent) + else Message.WParam := clBtnFace; + Message.Result := 1; +end; + +procedure TTBXDock.TBMThemeChange(var Message: TMessage); +begin + case Message.WParam of + TSC_AFTERVIEWCHANGE: + begin + Invalidate; + end; + end; +end; + +function TTBXDock.ThemedBackground: Boolean; +begin + Result := (Background = nil) and (Color = clNone) and CurrentTheme.PaintDockBackground; +end; + +function TTBXDock.UsingBackground: Boolean; +begin + Result := UseParentBackground or (ThemedBackground and not FMoving) or + inherited UsingBackground; +end; + +procedure TTBXDock.WMEraseBkgnd(var Message: TWMEraseBkgnd); +var + R: TRect; + C: TColor; +begin + R := Self.ClientRect; + if UsingBackground then + begin + DrawBackground(Message.DC, R); + Message.Result := 1; + end + else + begin + C := Color; + if C = clNone then C := GetEffectiveColor(Parent); + FillRectEx(Message.DC, R, C); + Message.Result := 1; + end; +end; + +procedure TTBXDock.WMMove(var Message: TWMMove); +begin + FMoving := True; + inherited; + FMoving := False; +end; + +procedure TTBXDock.WMSize(var Message: TWMSize); +begin + FResizing := True; + inherited; + FResizing := False; +end; + +{ TTBXMenuAnimation } {vb+} + +constructor TTBXMenuAnimation.Create(AAnimationMode: TAnimationMode = amSysDefault); +begin + AnimationMode := AAnimationMode; +end; + +function TTBXMenuAnimation.GetAvailableModes: TAnimationModes; +var IsWindows2K: Boolean; +begin + Result := [amNone]; + IsWindows2K := (Win32Platform = VER_PLATFORM_WIN32_NT) and + CheckWin32Version(5); + if IsWindows2K or ((Win32Platform = VER_PLATFORM_WIN32_WINDOWS) and + CheckWin32Version(4, 10){Win98}) then + Result := Result+ [amSysDefault, amRandom, amUnfold, amSlide]; + if IsWindows2K then + Include(Result, amFade); +end; + +function TTBXMenuAnimation.GetMenuAnimation: TMenuAnimation; + + function GetSysDefault: TMenuAnimation; + const + SPI_GETMENUFADE = $1012; + SysDefAni: array[Boolean] of TMenuAnimation = (maSlide, maFade); + begin + if SysParamEnabled(SPI_GETMENUANIMATION) + then Result := SysDefAni[SysParamEnabled(SPI_GETMENUFADE)] + else Result := maNone; + end; + + function GetRandom: TMenuAnimation; + var Max: Integer; + begin + Max := Ord(High(TMenuAnimation)); + if not (amFade in AvailableModes) then + Dec(Max); + Result := Succ(TMenuAnimation(Random(Max))); + end; + +begin + case AnimationMode of + amSysDefault: Result := GetSysDefault; + amRandom: Result := GetRandom; + amUnfold: Result := maUnfold; + amSlide: Result := maSlide; + amFade: Result := maFade; + else + Result := maNone; + end; +end; + +procedure TTBXMenuAnimation.SetAnimationMode(Value: TAnimationMode); +var AvailModes: TAnimationModes; +begin + AvailModes := AvailableModes; + while not (Value in AvailModes) do + Value := Pred(Value); + FAnimationMode := Value; +end; + +function TTBXMenuAnimation.SysParamEnabled(Param: Cardinal): Boolean; +var B: BOOL; +begin + Result := SystemParametersInfo(Param, 0, @B, 0) and B; +end; + +{ Work around delayed menu showing in Windows 2000+ } {vb+} +var + FixPlaySoundThreadHandle: Cardinal; + +function FixPlaySoundThreadFunc(Param: Pointer): Integer; stdcall; +begin + Sleep(250); + PlaySound(nil, 0, 0); + CloseHandle(FixPlaySoundThreadHandle); { Harakiri :~| } + Result := $4E494150; { :) } +end; + +procedure FixPlaySoundDelay; +var ThreadId: Cardinal; +begin + if (Win32Platform = VER_PLATFORM_WIN32_NT) and CheckWin32Version(5) and + (FixPlaySoundThreadHandle = 0) then + FixPlaySoundThreadHandle := CreateThread(nil, $1000, + @FixPlaySoundThreadFunc, nil, 0, ThreadId); +end; + +initialization + FixPlaySoundDelay; {vb+} + {CurrentTheme := nil;} {vb-} + RegisterTBXTheme('Default', TTBXDefaultTheme); + TBXNexus := TTBXNexus.Create('Default'); + TBXMenuAnimation := TTBXMenuAnimation.Create; {vb+} + {$IFNDEF JR_D7} {vb+} + InitAdditionalSysColors; + {$ENDIF} {vb+} + +finalization + TBXNexus.Free; + FreeAndNil(TBXMenuAnimation); {vb+} + ColorRegistry := nil; + +end. diff --git a/official/2.1.6+2.1.beta1/TBX/TBX.pas.orig b/official/2.1.6+2.1.beta1/TBX/TBX.pas.orig new file mode 100644 index 0000000..9a7d850 --- /dev/null +++ b/official/2.1.6+2.1.beta1/TBX/TBX.pas.orig @@ -0,0 +1,3588 @@ +unit TBX; + +// TBX Package +// Copyright 2001-2004 Alex A. Denisov. All Rights Reserved +// See TBX.chm for license and installation instructions +// +// $Id: TBX.pas 21 2004-05-29 22:16:01Z Alex@ZEISS $ + +interface + +{$I TB2Ver.inc} +{$I TBX.inc} + +uses + Windows, Messages, Classes, SysUtils, Controls, Graphics, ImgList, Forms, + TB2Item, TB2Dock, TB2Toolbar, TB2ToolWindow, TB2Anim, TBXUtils, TBXThemes; + +const + TBXVersion = 2.1; + TBXVersionString = '2.1'; + TBXVersionText = 'TBX version ' + TBXVersionString; + +{ TBX Messages } +const + TBM_THEMECHANGE = WM_USER + 314; + TBM_GETVIEWTYPE = WM_USER + 237; + TBM_GETEFFECTIVECOLOR = WM_USER + 238; + +function GetViewType(View: TTBView): Integer; +function GetWinViewType(Window: TControl): Integer; +function IsFloating(ViewType: Integer): Boolean; + +type + TTextWrapping = (twNone, twEndEllipsis, twPathEllipsis, twWrap); + TTextTruncation = twNone..twPathEllipsis; + TTriState = (tsDefault, tsTrue, tsFalse); + TFontSize = 25..1000; + + TFontSettings = class(TPersistent) + private + FBold: TTriState; + FItalic: TTriState; + FUnderline: TTriState; + FStrikeOut: TTriState; + FSize: TFontSize; + FColor: TColor; + FName: TFontName; + FOnChange: TNotifyEvent; + procedure SetBold(Value: TTriState); + procedure SetColor(Value: TColor); + procedure SetItalic(Value: TTriState); + procedure SetName(const Value: TFontName); + procedure SetSize(Value: TFontSize); + procedure SetStrikeOut(Value: TTriState); + procedure SetUnderline(Value: TTriState); + protected + procedure Modified; + property OnChange: TNotifyEvent read FOnChange write FOnChange; + public + constructor Create; + procedure Apply(Font: TFont); overload; + procedure Apply(var LF: TLogFont; var FontColor: TColor); overload; + procedure Assign(Src: TPersistent); override; + function CreateTransformedFont(Src: HFont; var FontColor: TColor): HFont; + published + property Bold: TTriState read FBold write SetBold default tsDefault; + property Italic: TTriState read FItalic write SetItalic default tsDefault; + property Underline: TTriState read FUnderline write SetUnderline default tsDefault; + property StrikeOut: TTriState read FStrikeOut write SetStrikeOut default tsDefault; + property Size: TFontSize read FSize write SetSize default 100; // percent + property Color: TColor read FColor write SetColor default clNone; + property Name: TFontName read FName write SetName; // default '' + end; + + TTBXPopupPositionInfo = record + Item: TTBCustomItem; // this is a tentative type, it will be changed + ParentView: TTBView; // or removed in future versions + ParentViewer: TTBItemViewer; + PositionAsSubmenu: Boolean; + APopupPoint: TPoint; + Alignment: TTBPopupAlignment; + PopupWindow: TTBPopupWindow; + X, Y: Integer; + ParentItemRect: TRect; + AppFlags: Integer; // reserved for extensions + AppData: Integer; + end; + + TTBXThemeClass = class of TTBXTheme; + +function GetStateFlags(const ItemInfo: TTBXItemInfo): Integer; +function GetTBXTextColor(StateFlags: Integer): TColor; +procedure DrawTBXCaption(Canvas: TCanvas; Rect: TRect; const Text: string; + Format: Cardinal; StateFlags: Integer); +procedure DrawTBXImage(Canvas: TCanvas; Rect: TRect; ImageList: TCustomImageList; + ImageIndex: Integer; StateFlags: Integer); + + +type + { TTBXItem } + + TAdjustFontEvent = procedure(Item: TTBCustomItem; Viewer: TTBItemViewer; + Font: TFont; StateFlags: Integer) of object; // state flags are the combination of ISF_* constants + TDrawImageEvent = procedure(Item: TTBCustomItem; Viewer: TTBItemViewer; + Canvas: TCanvas; ImageRect: TRect; ImageOffset: TPoint; StateFlags: Integer) of object; + + TTBXCustomItem = class(TTBCustomItem) + private + FAlwaysSelectFirst: Boolean; + FFontSettings: TFontSettings; + FLayout: TTBXItemLayout; + FMinHeight: Integer; + FMinWidth: Integer; + FToolBoxPopup: Boolean; + FOnAdjustFont: TAdjustFontEvent; + FOnDrawImage: TDrawImageEvent; + procedure FontSettingsChanged(Sender: TObject); + function GetStretch: Boolean; + procedure SetFontSettings(Value: TFontSettings); + procedure SetLayout(Value: TTBXItemLayout); + procedure SetMinHeight(Value: Integer); + procedure SetMinWidth(Value: Integer); + procedure SetStretch(Value: Boolean); + protected + function CreatePopup(const ParentView: TTBView; const ParentViewer: TTBItemViewer; + const PositionAsSubmenu, SelectFirstItem, Customizing: Boolean; + const APopupPoint: TPoint; const Alignment: TTBPopupAlignment): TTBPopupWindow; override; + function GetItemViewerClass(AView: TTBView): TTBItemViewerClass; override; + procedure GetPopupPosition(ParentView: TTBView; PopupWindow: TTBPopupWindow; + var PopupPositionRec: TTBPopupPositionRec); override; + function GetPopupWindowClass: TTBPopupWindowClass; override; + property ToolBoxPopup: Boolean read FToolBoxPopup write FToolBoxPopup default False; + property OnAdjustFont: TAdjustFontEvent read FOnAdjustFont write FOnAdjustFont; + property OnDrawImage: TDrawImageEvent read FOnDrawImage write FOnDrawImage; + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + procedure Invalidate; + property AlwaysSelectFirst: Boolean read FAlwaysSelectFirst write FAlwaysSelectFirst default False; + property FontSettings: TFontSettings read FFontSettings write SetFontSettings; + property Layout: TTBXItemLayout read FLayout write SetLayout default tbxlAuto; + property MinHeight: Integer read FMinHeight write SetMinHeight default 0; + property MinWidth: Integer read FMinWidth write SetMinWidth default 0; + property Stretch: Boolean read GetStretch write SetStretch default False; + end; + + TTBXItem = class (TTBXCustomItem) + property Action; + property AutoCheck; + property Caption; + property Checked; + property DisplayMode; + property Enabled; + property FontSettings; + property GroupIndex; + property HelpContext; + property Hint; + property ImageIndex; + property Images; + property InheritOptions; + property Layout; + property MaskOptions; + property MinHeight; + property MinWidth; + property Options; + property ShortCut; + property Stretch; + property Visible; + property OnAdjustFont; + property OnDrawImage; + property OnClick; + property OnSelect; + end; + + TTBXItemViewer = class(TTBItemViewer) + private + FWide: Boolean; + protected + procedure DoPaintCaption(Canvas: TCanvas; const ClientAreaRect: TRect; + var CaptionRect: TRect; IsTextRotated: Boolean; var PaintDefault: Boolean); virtual; + function GetAccRole: Integer; override; + function GetImageSize: TSize; dynamic; + function GetItemType: Integer; virtual; + function GetTextFlags: Cardinal; dynamic; + function GetTextSize(Canvas: TCanvas; const Text: string; TextFlags: Cardinal; Rotated: Boolean; StateFlags: Integer): TSize; dynamic; + function IsToolbarSize: Boolean; override; + procedure CalcSize(const Canvas: TCanvas; var AWidth, AHeight: Integer); override; + procedure DrawItemImage(Canvas: TCanvas; ARect: TRect; ItemInfo: TTBXItemInfo); virtual; + procedure DoAdjustFont(AFont: TFont; StateFlags: Integer); virtual; + function GetImageShown: Boolean; virtual; + function IsPtInButtonPart(X, Y: Integer): Boolean; override; + procedure MouseUp(X, Y: Integer; MouseWasDownOnMenu: Boolean); override; + procedure Paint(const Canvas: TCanvas; const ClientAreaRect: TRect; IsHoverItem, IsPushed, UseDisabledShadow: Boolean); override; + property Wide: Boolean read FWide write FWide default True; + public + constructor Create(AView: TTBView; AItem: TTBCustomItem; AGroupLevel: Integer); override; + function IsToolbarStyle: Boolean; override; + end; + + { TTBXSubmenuItem } + + TTBXSubmenuItem = class(TTBXCustomItem) + private + function GetDropdownCombo: Boolean; + procedure SetDropdownCombo(Value: Boolean); + public + constructor Create(AOwner: TComponent); override; + published + property Action; + property AlwaysSelectFirst; + property AutoCheck; + property Caption; + property Checked; + property DisplayMode; + property DropdownCombo: Boolean read GetDropdownCombo write SetDropdownCombo default False; + property Enabled; + property FontSettings; + property GroupIndex; + property HelpContext; + property Hint; + property ImageIndex; + property Images; + property InheritOptions; + property Layout; + property LinkSubitems; + property MaskOptions; + property MinHeight; + property MinWidth; + property Options; + property ShortCut; + property Stretch; + property SubMenuImages; + property ToolBoxPopup; + property Visible; + property OnAdjustFont; + property OnDrawImage; + property OnClick; + property OnPopup; + property OnSelect; + end; + + { TTBXSeparatorItem } + + TTBXSeparatorItem = class(TTBSeparatorItem) + private + FSize: Integer; + procedure SetSize(Value: Integer); + public + constructor Create(AOwner: TComponent); override; + function GetItemViewerClass(AView: TTBView): TTBItemViewerClass; override; + published + property Size: Integer read FSize write SetSize default -1; + property MaskOptions; + property Options; + end; + + TTBXSeparatorItemViewer = class(TTBSeparatorItemViewer) + protected + procedure CalcSize(const Canvas: TCanvas; var AWidth, AHeight: Integer); override; + procedure Paint(const Canvas: TCanvas; const ClientAreaRect: TRect; + IsHoverItem, IsPushed, UseDisabledShadow: Boolean); override; + function IsToolbarSize: Boolean; override; + public + function IsToolbarStyle: Boolean; override; + end; + + TTBXVisibilityToggleItem = class(TTBXCustomItem) + private + FControl: TControl; + procedure SetControl (Value: TControl); + procedure UpdateProps; + protected + procedure Notification (AComponent: TComponent; Operation: TOperation); override; + public + procedure Click; override; + procedure InitiateAction; override; + published + property Caption; + property Control: TControl read FControl write SetControl; + property DisplayMode; + property Enabled; + property FontSettings; + property HelpContext; + property Hint; + property ImageIndex; + property Images; + property InheritOptions; + property Layout; + property MaskOptions; + property MinHeight; + property MinWidth; + property Options; + property ShortCut; + property Stretch; + property Visible; + property OnAdjustFont; + property OnClick; + property OnSelect; + end; + + { TTBXPopupWindow } + + TTBXPopupWindow = class(TTBPopupWindow) + private + FControlRect: TRect; + FShadows: TShadows; + procedure CMHintShow(var Message: TCMHintShow); message CM_HINTSHOW; + procedure TBMGetViewType(var Message: TMessage); message TBM_GETVIEWTYPE; + procedure WMNCCalcSize(var Message: TWMNCCalcSize); message WM_NCCALCSIZE; + procedure WMNCPaint(var Message: TMessage); message WM_NCPAINT; + procedure WMPrint(var Message: TMessage); message WM_PRINT; + procedure WMEraseBkgnd(var Message: TWMEraseBkgnd); message WM_ERASEBKGND; + procedure WMWindowPosChanged(var Message: TWMWindowPosChanged); message WM_WINDOWPOSCHANGED; + procedure WMTB2kPopupShowing(var Message: TMessage); message WM_TB2K_POPUPSHOWING; + protected + procedure CreateParams(var Params: TCreateParams); override; + procedure CreateShadow; virtual; + procedure DestroyShadow; virtual; + function GetNCSize: TPoint; override; + function GetShowShadow: Boolean; virtual; + function GetViewClass: TTBViewClass; override; + public + destructor Destroy; override; + function GetFillColor: TColor; + end; + + TTBXPopupView = class(TTBPopupView); + + { TTBXToolbarView } + + TTBXToolbarView = class(TTBToolbarView) + protected + procedure GetMargins(AOrientation: TTBViewOrientation; var Margins: TRect); override; + end; + + { TTBXToolbar } + TTBXItemTransparency = (itAuto, itEnable, itDisable); + + TTBXToolbar = class(TTBCustomToolbar) + private + FEffectiveColor: TColor; + FItemTransparency: TTBXItemTransparency; + FSnapDistance: Integer; + procedure CMColorChanged(var Message: TMessage); message CM_COLORCHANGED; + procedure CMControlChange(var Message: TCMControlChange); message CM_CONTROLCHANGE; + procedure CMParentColorChanged(var Message: TMessage); message CM_PARENTCOLORCHANGED; + procedure SetItemTransparency(const Value: TTBXItemTransparency); + procedure SetSnapDistance(Value: Integer); + procedure TBMGetViewType(var Message: TMessage); message TBM_GETVIEWTYPE; + procedure TBMGetEffectiveColor(var Message: TMessage); message TBM_GETEFFECTIVECOLOR; + procedure TBMThemeChange(var Message: TMessage); message TBM_THEMECHANGE; + procedure WMEraseBkgnd(var Message: TWMEraseBkgnd); message WM_ERASEBKGND; + procedure WMSize(var Message: TWMSize); message WM_SIZE; + protected + procedure DrawNCArea(const DrawToDC: Boolean; const ADC: HDC; const Clip: HRGN); override; + function GetChevronItemClass: TTBChevronItemClass; override; + function GetFloatingWindowParentClass: TTBFloatingWindowParentClass; override; + procedure GetToolbarInfo(out ToolbarInfo: TTBXToolbarInfo); virtual; + function GetViewClass: TTBToolbarViewClass; override; + procedure SetParent(AParent: TWinControl); override; + procedure UpdateEffectiveColor; + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + function Embedded: Boolean; + function GetFloatingBorderSize: TPoint; override; + procedure UpdateChildColors; + property EffectiveColor: TColor read FEffectiveColor; + published + property ActivateParent; + property Align; + property AutoResize; + property BorderStyle; + property Caption; + property ChevronHint; + property ChevronMoveItems; + property ChevronPriorityForNewItems; + property CloseButton; + property CloseButtonWhenDocked; + property CurrentDock; + property DblClickUndock default False; + property DefaultDock; + property DockableTo; + property DockMode; + property DockPos; + property DockRow; + property DragHandleStyle; + property FloatingMode; + property Font; + property FullSize; + property HideWhenInactive; + property Images; + property Items; + property ItemTransparency: TTBXItemTransparency read FItemTransparency write SetItemTransparency default itAuto; + property LastDock; + property LinkSubitems; + property MenuBar; + property Options; + property ParentFont; + property ParentShowHint; + property PopupMenu; + property ProcessShortCuts; + property Resizable; + property ShowCaption; + property ShowHint; + property ShrinkMode; + property SmoothDrag; + property SnapDistance: Integer read FSnapDistance write SetSnapDistance default 0; + property Stretch; + property SystemFont; + property TabOrder; + property TabStop; + property UpdateActions; + property UseLastDock; + property Visible; + property Color default clNone; + property OnClose; + property OnCloseQuery; + {$IFDEF JR_D5} + property OnContextPopup; + {$ENDIF} + property OnDragDrop; + property OnDragOver; + property OnMouseDown; + property OnMouseMove; + property OnMouseUp; + property OnMove; + property OnRecreated; + property OnRecreating; + property OnDockChanged; + property OnDockChanging; + property OnDockChangingHidden; + property OnResize; + property OnShortCut; + property OnVisibleChanged; + end; + + { TTBXChevronItem } + + TTBXChevronItem = class(TTBChevronItem) + public + procedure GetPopupPosition(ParentView: TTBView; + PopupWindow: TTBPopupWindow; var PopupPositionRec: TTBPopupPositionRec); override; + function GetPopupWindowClass: TTBPopupWindowClass; override; + function GetItemViewerClass(AView: TTBView): TTBItemViewerClass; override; + end; + + TTBXChevronItemViewer = class(TTBItemViewer) + protected + procedure Paint(const Canvas: TCanvas; const ClientAreaRect: TRect; + IsHoverItem, IsPushed, UseDisabledShadow: Boolean); override; + end; + + TTBXChevronPopupWindow = class(TTBXPopupWindow); + + { TTBXPopupMenu } + + TTBXRootItem = class(TTBRootItem) + private + FPopupControlRect: TRect; + protected + function CreatePopupEx(SelectFirstItem: Boolean; const AControlRect: TRect; + Alignment: TTBPopupAlignment): TTBPopupWindow; virtual; + function GetPopupWindowClass: TTBPopupWindowClass; override; + procedure GetPopupPosition(ParentView: TTBView; PopupWindow: TTBPopupWindow; + var PopupPositionRec: TTBPopupPositionRec); override; + procedure OpenPopupEx(const SelectFirstItem, TrackRightButton: Boolean; + const ControlRect: TRect; const Alignment: TTBPopupAlignment); + procedure PopupEx(const ControlRect: TRect; TrackRightButton: Boolean; + Alignment: TTBPopupAlignment = tbpaLeft); + end; + + TTBXPopupMenu = class(TTBPopupMenu) + private + FToolBoxPopup: Boolean; + procedure TBMGetViewType(var Message: TMessage); message TBM_GETVIEWTYPE; + protected + function GetRootItemClass: TTBRootItemClass; override; + public + procedure PopupEx(const ControlRect: TRect); + property ToolBoxPopup: Boolean read FToolBoxPopup write FToolBoxPopup default False; + end; + + TTBXFloatingWindowParent = class(TTBFloatingWindowParent) + private + FCloseButtonHover: Boolean; + FSnapDistance: Integer; + procedure CMMouseLeave(var Message: TMessage); message CM_MOUSELEAVE; + procedure WMEraseBkgnd(var Message: TMessage); message WM_ERASEBKGND; + procedure WMNCMouseLeave(var Message: TMessage); message $2A2 {WM_NCMOUSELEAVE}; + procedure WMNCMouseMove(var Message: TWMNCMouseMove); message WM_NCMOUSEMOVE; + procedure WMWindowPosChanging(var Message: TWMWindowPosChanging); message WM_WINDOWPOSCHANGING; + protected + procedure CancelNCHover; + procedure DrawNCArea(const DrawToDC: Boolean; const ADC: HDC; + const Clip: HRGN; RedrawWhat: TTBToolWindowNCRedrawWhat); override; + property CloseButtonHover: Boolean read FCloseButtonHover; + public + property SnapDistance: Integer read FSnapDistance write FSnapDistance default 0; + end; + + TTBXToolWindow = class(TTBToolWindow) + private + FEffectiveColor: TColor; + FSnapDistance: Integer; + procedure CMColorChanged(var Message: TMessage); message CM_COLORCHANGED; + procedure CMControlChange(var Message: TCMControlChange); message CM_CONTROLCHANGE; + procedure CMTextChanged(var Message: TMessage); message CM_TEXTCHANGED; + procedure SetSnapDistance(Value: Integer); + procedure TBMGetEffectiveColor(var Message: TMessage); message TBM_GETEFFECTIVECOLOR; + procedure TBMGetViewType(var Message: TMessage); message TBM_GETVIEWTYPE; + procedure TBMThemeChange(var Message: TMessage); message TBM_THEMECHANGE; + procedure WMEraseBkgnd(var Message: TWmEraseBkgnd); message WM_ERASEBKGND; + protected + procedure DrawNCArea(const DrawToDC: Boolean; const ADC: HDC; const Clip: HRGN); override; + function GetFloatingWindowParentClass: TTBFloatingWindowParentClass; override; + procedure GetToolbarInfo(out ToolbarInfo: TTBXToolbarInfo); virtual; + procedure SetParent(AParent: TWinControl); override; + procedure UpdateEffectiveColor; + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + function GetFloatingBorderSize: TPoint; override; + procedure UpdateChildColors; + property EffectiveColor: TColor read FEffectiveColor; + published + property Color default clNone; + property DblClickUndock default False; + property SnapDistance: Integer read FSnapDistance write SetSnapDistance default 0; + end; + + TTBXDock = class(TTBDock) + private + FMoving: Boolean; + FResizing: Boolean; + FUseParentBackground: Boolean; + procedure CMColorChanged(var Message: TMessage); message CM_COLORCHANGED; + procedure TBMGetEffectiveColor(var Message: TMessage); message TBM_GETEFFECTIVECOLOR; + procedure TBMThemeChange(var Message: TMessage); message TBM_THEMECHANGE; + procedure WMEraseBkgnd(var Message: TWMEraseBkgnd); message WM_ERASEBKGND; + procedure WMMove(var Message: TWMMove); message WM_MOVE; + procedure WMSize(var Message: TWMSize); message WM_SIZE; + protected + function ThemedBackground: Boolean; virtual; + procedure DrawBackground(DC: HDC; const DrawRect: TRect); override; + procedure Resize; override; + procedure SetUseParentBackground(Value: Boolean); + function UsingBackground: Boolean; override; + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + published + property Color default clNone; + property UseParentBackground: Boolean read FUseParentBackground write SetUseParentBackground default False; + end; + +var + CurrentTheme: TTBXTheme; + +{$IFNDEF JR_D6} +var + clMoneyGreen: TColor = TColor($C0DCC0); + clSkyBlue: TColor = TColor($F0CAA6); + clCream: TColor = TColor($F0FBFF); + clMedGray: TColor = TColor($A4A0A0); +{$ENDIF} + +procedure TBXSetTheme(const AThemeName: string); +function TBXCurrentTheme: string; + +procedure AddThemeNotification(AObject: TObject); +procedure RemoveThemeNotification(AObject: TObject); + +{ Additional system colors } +procedure AddTBXColor(var AColor: TColor; const AName: string); +function TBXIdentToColor(const Ident: string; var Color: Longint): Boolean; +function TBXColorToString(Color: TColor): string; +function TBXStringToColor(S: string): TColor; +procedure TBXGetColorValues(Proc: TGetStrProc); + +{ Internal routines - do not use } +function GetPopupMargin(ItemViewer: TTBItemViewer): Integer; +function GetEffectiveColor(C: TControl): TColor; +procedure DrawParentBackground(Control: TControl; DC: HDC; R: TRect); +procedure AddToList(var List: TList; Item: Pointer); +procedure RemoveFromList(var List: TList; Item: Pointer); + +implementation + +{$R tbx_glyphs.res} + +uses + TBXExtItems, TBXLists, TB2Common, TBXUxThemes, MultiMon, TBXDefaultTheme, + ComCtrls, Menus; + +type + TTBItemAccess = class(TTBCustomItem); + TTBViewAccess = class(TTBView); + TTBItemViewerAccess = class(TTBItemViewer); + TTBFloatingWindowParentAccess = class(TTBFloatingWindowParent); + TTBCustomDockableWindowAccess = class(TTBCustomDockableWindow); + TTBXToolbarAccess = class(TTBXToolbar); + TTBBackgroundAccess = class(TTBBackground); + TControlAccess = class(TControl); + TTBXThemeAccess = class(TTBXTheme); + TDockAccess = class(TTBDock); + + { TTBNexus } + TTBXNexus = class + private + FNotifies: TList; + procedure TBXSysCommand(var Message: TMessage); message TBX_SYSCOMMAND; + protected + procedure Broadcast(Msg: Cardinal; WParam, LParam: Integer); + public + constructor Create(const DefaultTheme: string); + destructor Destroy; override; + procedure SetTheme(const AThemeName: string); + function GetTheme: string; + procedure AddNotifie(AObject: TObject); + procedure RemoveNotifie(AObject: TObject); + end; + +var + TBXNexus: TTBXNexus; + +procedure AddThemeNotification(AObject: TObject); +begin + TBXNexus.AddNotifie(AObject); +end; + +procedure RemoveThemeNotification(AObject: TObject); +begin + TBXNexus.RemoveNotifie(AObject); +end; + +function GetEffectiveColor(C: TControl): TColor; +var + Message: TMessage; +begin + if C = nil then Result := clBtnFace + else + begin + Message.Msg := TBM_GETEFFECTIVECOLOR; + Message.WParam := 0; + Message.LParam := 0; + Message.Result := 0; + C.Dispatch(Message); + if Message.Result <> 0 then Result := Message.WParam + else if (C is TForm) and (TForm(C).FormStyle = fsMDIForm) then + Result := clBtnFace + else + Result := TControlAccess(C).Color; + end; +end; + +procedure DrawParentBackground(Control: TControl; DC: HDC; R: TRect); +var + Parent: TWinControl; + Theme: HTHEME; + R2: TRect; + Shift: TPoint; + UsingThemes: Boolean; + Msg: TMessage; +begin + Parent := Control.Parent; + if Parent = nil then FillRectEx(DC, R, clBtnFace) + else + begin + Shift.X := 0; Shift.Y := 0; + Shift := Parent.ScreenToClient(Control.ClientToScreen(Shift)); + SaveDC(DC); + try + SetWindowOrgEx(DC, Shift.X, Shift.Y, nil); + Msg.Msg := WM_ERASEBKGND; + Msg.WParam := DC; + Msg.LParam := DC; + Msg.Result := 0; + Parent.Dispatch(Msg); + finally + RestoreDC(DC, -1); + end; + + if Msg.Result <> 0 then Exit; + + UsingThemes := USE_THEMES and not (csDesigning in Control.ComponentState); + if Parent is TTBDock then + begin + SaveDC(DC); + SetWindowOrgEx(DC, Control.Left, Control.Top, nil); + TDockAccess(Parent).DrawBackground(DC, R); + RestoreDC(DC, -1); + end + else if not UsingThemes then + FillRectEx(DC, R, GetEffectiveColor(Parent)) + else + begin + { Unfortunately, DrawThemeParentBackground does seem to have some problems + with the back buffer. Therefore some sort of workaround is used which + will work for tab sheets } + // if Control is TWinControl then + // DrawThemeParentBackground(TWinControl(Control).Handle, DC, @R); + + if Parent is TTabSheet then + begin + Theme := OpenThemeData(Parent.Handle, 'TAB'); + R2 := Parent.ClientRect; + R2.TopLeft := Control.ScreenToClient(Parent.ClientToScreen(R2.TopLeft)); + R2.BottomRight := Control.ScreenToClient(Parent.ClientToScreen(R2.BottomRight)); + DrawThemeBackground(Theme, DC, TABP_BODY, 0, R2, @R); + CloseThemeData(Theme); + end + else FillRectEx(DC, R, GetEffectiveColor(Parent)); + end; + end; +end; + +function GetViewType(View: TTBView): Integer; +var + Message: TMessage; +begin + Result := VT_UNKNOWN; + if (View <> nil) and (View.Owner <> nil) then + begin + Message.Msg := TBM_GETVIEWTYPE; + Message.WParam := 0; + Message.LParam := 0; + Message.Result := VT_UNKNOWN; + View.Window.Dispatch(Message); + Result := Message.Result; + end; +end; + +function GetWinViewType(Window: TControl): Integer; +var + Message: TMessage; +begin + Result := VT_UNKNOWN; + if Window <> nil then + begin + Message.Msg := TBM_GETVIEWTYPE; + Message.WParam := 0; + Message.LParam := 0; + Message.Result := VT_UNKNOWN; + Window.Dispatch(Message); + Result := Message.Result; + end; +end; + +function IsFloating(ViewType: Integer): Boolean; +begin + Result := ViewType and TVT_FLOATING <> 0; +end; + +procedure UpdateNCArea(Control: TWinControl; ViewType: Integer); +begin + with Control do + begin + ClientWidth := ClientWidth; + ClientHeight := ClientHeight; + end; + SetWindowPos(Control.Handle, 0, 0, 0, 0, 0, + SWP_FRAMECHANGED or SWP_NOACTIVATE or SWP_NOZORDER or SWP_NOMOVE or SWP_NOSIZE); + Control.Invalidate; +end; + +function GetPopupMargin(ItemViewer: TTBItemViewer): Integer; +var + ImgList: TCustomImageList; + Sz: TSize; + TextMetric: TTextMetric; + H, M2: Integer; + Margins: TTBXMargins; +begin + Sz.Cx := 0; + Sz.Cy := 0; + if ItemViewer is TTBXItemViewer then + Sz := TTBXItemViewer(ItemViewer).GetImageSize; + if (Sz.Cx = 0) or (Sz.Cy = 0) then + begin + ImgList := TTBItemViewerAccess(ItemViewer).GetImageList; + if ImgList <> nil then + begin + Sz.Cx := ImgList.Width; + Sz.Cy := ImgList.Height; + end; + if (Sz.Cx = 0) or (Sz.Cy = 0) then + begin + Sz.Cx := 16; + Sz.Cy := 16; + end; + end; + StockBitmap1.Canvas.Font := TTBViewAccess(ItemViewer.View).GetFont; + GetTextMetrics(StockBitmap1.Canvas.Handle, TextMetric); + + CurrentTheme.GetMargins(MID_MENUITEM, Margins); + M2 := Margins.TopHeight + Margins.BottomHeight; + Result := TextMetric.tmHeight + TextMetric.tmExternalLeading + M2; + H := Sz.CY + M2; + if H > Result then Result := H; + Result := (Sz.Cx + M2) * Result div H; +end; + +procedure GetOfficeXPPopupPosition1(var PopupPositionRec: TTBPopupPositionRec); +begin + with PopupPositionRec do + begin + if not PositionAsSubmenu then + begin + NCSizeX := 0; + NCSizeY := 0; + Dec(ParentItemRect.Right); + if X = ParentItemRect.Right + 1 then Dec(X); + if X + W <= ParentItemRect.Left then Inc(X); + Dec(ParentItemRect.Bottom); + if Y = ParentItemRect.Bottom + 1 then Dec(Y); + if Y + H <= ParentItemRect.Top then Inc(Y); + Dec(W); + Dec(H); + end + else + begin + Inc(X, NCSizeX); + Inc(Y, NCSizeY); + NCSizeX := 0; + NCSizeY := 0; + end; + end; +end; + +procedure GetOfficeXPPopupPosition2(var PopupPositionRec: TTBPopupPositionRec); +begin + with PopupPositionRec do if not PositionAsSubmenu then + begin + Inc(W); + Inc(H); + end; +end; + +procedure AddToList(var List: TList; Item: Pointer); +begin + if List = nil then List := TList.Create; + List.Add(Item) +end; + + +procedure RemoveFromList(var List: TList; Item: Pointer); +begin + if List <> nil then + begin + List.Remove(Item); + if List.Count = 0 then + begin + List.Free; + List := nil; + end; + end; +end; + +//============================================================================// + +{ Misc. Routines } + +procedure InvalidateAll(const Ctl: TWinControl); +begin + if Ctl.HandleAllocated then + RedrawWindow(Ctl.Handle, nil, 0, RDW_FRAME or RDW_INVALIDATE or + RDW_ERASE); +end; + +function GetStateFlags(const ItemInfo: TTBXItemInfo): Integer; +const + CEnabledStates: array [Boolean] of Integer = (ISF_DISABLED, 0); + CHotStates: array [Boolean] of Integer = (0, ISF_HOT); + CPushedStates: array [Boolean] of Integer = (0, ISF_PUSHED); + CSelectedStates: array [Boolean] of Integer = (0, ISF_SELECTED); +begin + with ItemInfo do + Result := CEnabledStates[ItemInfo.Enabled] or CPushedStates[ItemInfo.Pushed] or + CHotStates[ItemInfo.HoverKind = hkMouseHover] or CSelectedStates[ItemInfo.Selected]; +end; + +function GetTBXTextColor(StateFlags: Integer): TColor; +const + HoverKinds: array [Boolean] of TTBXHoverKind = (hkNone, hkMouseHover); +var + ItemInfo: TTBXItemInfo; +begin + FillChar(ItemInfo, SizeOf(ItemInfo), 0); + case StateFlags and ISF_LOCATIONMASK of + ISF_TOOLBARCOLOR: + begin + ItemInfo.ViewType := VT_TOOLBAR; + ItemInfo.ItemOptions := IO_TOOLBARSTYLE; + end; + ISF_MENUCOLOR: + begin + ItemInfo.ViewType := VT_DOCKPANEL; + end; + ISF_STATUSCOLOR: + begin + ItemInfo.ViewType := VT_STATUSBAR; + end; + else + ItemInfo.ViewType := VT_UNKNOWN; + end; + ItemInfo.Enabled := StateFlags and ISF_DISABLED = 0; + ItemInfo.Pushed := StateFlags and ISF_PUSHED <> 0; + ItemInfo.HoverKind := HoverKinds[StateFlags and ISF_HOT <> 0]; + ItemInfo.Selected := StateFlags and ISF_SELECTED <> 0; + Result := CurrentTheme.GetItemTextColor(ItemInfo); +end; + +procedure DrawTBXCaption(Canvas: TCanvas; Rect: TRect; const Text: string; Format: Cardinal; StateFlags: Integer); +const + HoverKinds: array [Boolean] of TTBXHoverKind = (hkNone, hkMouseHover); +var + ItemInfo: TTBXItemInfo; +begin + FillChar(ItemInfo, SizeOf(ItemInfo), 0); + case StateFlags and ISF_LOCATIONMASK of + ISF_TOOLBARCOLOR: + begin + ItemInfo.ViewType := VT_TOOLBAR; + ItemInfo.ItemOptions := IO_TOOLBARSTYLE; + end; + ISF_MENUCOLOR: + begin + ItemInfo.ViewType := VT_DOCKPANEL; + end; + ISF_STATUSCOLOR: + begin + ItemInfo.ViewType := VT_STATUSBAR; + end; + end; + ItemInfo.Enabled := StateFlags and ISF_DISABLED = 0; + ItemInfo.Pushed := StateFlags and ISF_PUSHED <> 0; + ItemInfo.HoverKind := HoverKinds[StateFlags and ISF_HOT <> 0]; + ItemInfo.Selected := StateFlags and ISF_SELECTED <> 0; + CurrentTheme.PaintCaption(Canvas, Rect, ItemInfo, Text, Format, False); +end; + +procedure DrawTBXImage(Canvas: TCanvas; Rect: TRect; ImageList: TCustomImageList; + ImageIndex: Integer; StateFlags: Integer); +const + HoverKinds: array [Boolean] of TTBXHoverKind = (hkNone, hkMouseHover); +var + ItemInfo: TTBXItemInfo; +begin + FillChar(ItemInfo, SizeOf(ItemInfo), 0); + case StateFlags and ISF_LOCATIONMASK of + ISF_TOOLBARCOLOR: + begin + ItemInfo.ViewType := VT_TOOLBAR; + ItemInfo.ItemOptions := IO_TOOLBARSTYLE; + end; + ISF_MENUCOLOR: + begin + ItemInfo.ViewType := VT_DOCKPANEL; + end; + ISF_STATUSCOLOR: + begin + ItemInfo.ViewType := VT_STATUSBAR; + end; + end; + ItemInfo.Enabled := not Boolean(StateFlags and ISF_DISABLED); + ItemInfo.Pushed := Boolean(StateFlags and ISF_PUSHED); + ItemInfo.HoverKind := HoverKinds[Boolean(StateFlags and ISF_HOT)]; + ItemInfo.Selected := Boolean(StateFlags and ISF_SELECTED); + CurrentTheme.PaintImage(Canvas, Rect, ItemInfo, ImageList, ImageIndex); +end; + +//============================================================================// + +{ TFontSettings } + +procedure TFontSettings.Apply(Font: TFont); +var + FS: TFontStyles; +begin + if Size <> 100 then Font.Size := (Font.Size * FSize + 50) div 100; + if Color <> clNone then Font.Color := Color; + if Name <> '' then Font.Name := Name; + FS := Font.Style; + if Bold = tsTrue then Include(FS, fsBold) + else if Bold = tsFalse then Exclude(FS, fsBold); + if Italic = tsTrue then Include(FS, fsItalic) + else if Italic = tsFalse then Exclude(FS, fsItalic); + if Underline = tsTrue then Include(FS, fsUnderline) + else if Underline = tsFalse then Exclude(FS, fsUnderline); + if StrikeOut = tsTrue then Include(FS, fsStrikeOut) + else if StrikeOut = tsFalse then Exclude(FS, fsStrikeOut); + Font.Style := FS; +end; + +procedure TFontSettings.Apply(var LF: TLogFont; var FontColor: TColor); +begin + if Size <> 100 then LF.lfHeight := (LF.lfHeight * Size + 50) div 100; + if Color <> clNone then FontColor := Color; + if Name <> '' then StrPLCopy(LF.lfFaceName, Name, 31); + if Bold = tsTrue then LF.lfWeight := FW_BOLD + else if Bold = tsFalse then LF.lfWeight := FW_NORMAL; + if Italic = tsTrue then LF.lfItalic := 1 + else if Italic = tsFalse then LF.lfItalic := 0; + if Underline = tsTrue then LF.lfUnderline := 1 + else if Underline = tsFalse then LF.lfUnderline := 0; + if StrikeOut = tsTrue then LF.lfStrikeOut := 1 + else if StrikeOut = tsFalse then LF.lfStrikeOut := 0; +end; + +procedure TFontSettings.Assign(Src: TPersistent); +var + F: TFontSettings; +begin + if Src is TPersistent then + begin + F := TFontSettings(Src); + if (FBold <> F.Bold) or (FItalic <> F.Italic) or (FUnderline <> F.Underline) or + (FStrikeOut <> F.StrikeOut) or (FSize <> F.Size) or (FColor <> F.Color) or + (FName <> F.Name) then + begin + FBold := F.Bold; + FItalic := F.Italic; + FUnderline := F.Underline; + FStrikeOut := F.StrikeOut; + FSize := F.Size; + FColor := F.Color; + FName := F.Name; + Modified; + end; + end + else inherited; +end; + +constructor TFontSettings.Create; +begin + FSize := 100; + FColor := clNone; +end; + +function TFontSettings.CreateTransformedFont(Src: HFont; var FontColor: TColor): HFont; +var + LF: TLogFont; +begin + GetObject(Src, SizeOf(LF), @LF); + Apply(LF, FontColor); + Result := CreateFontIndirect(LF); +end; + +procedure TFontSettings.Modified; +begin + if Assigned(FOnChange) then FOnChange(Self); +end; + +procedure TFontSettings.SetBold(Value: TTriState); +begin + if FBold <> Value then + begin + FBold := Value; + Modified; + end; +end; + +procedure TFontSettings.SetColor(Value: TColor); +begin + if FColor <> Value then + begin + FColor := Value; + Modified; + end; +end; + +procedure TFontSettings.SetItalic(Value: TTriState); +begin + if FItalic <> Value then + begin + FItalic := Value; + Modified; + end; +end; + +procedure TFontSettings.SetName(const Value: TFontName); +begin + if FName <> Value then + begin + FName := Value; + Modified; + end; +end; + +procedure TFontSettings.SetSize(Value: TFontSize); +begin + if FSize <> Value then + begin + FSize := Value; + Modified; + end; +end; + +procedure TFontSettings.SetStrikeOut(Value: TTriState); +begin + if FStrikeOut <> Value then + begin + FStrikeOut := Value; + Modified; + end; +end; + +procedure TFontSettings.SetUnderline(Value: TTriState); +begin + if FUnderline <> Value then + begin + FUnderline := Value; + Modified; + end; +end; + +//============================================================================// + +{ TTBXCustomItem } + +constructor TTBXCustomItem.Create(AOwner: TComponent); +begin + inherited; + FFontSettings := TFontSettings.Create; + FFontSettings.OnChange := FontSettingsChanged; +end; + +function TTBXCustomItem.CreatePopup(const ParentView: TTBView; + const ParentViewer: TTBItemViewer; const PositionAsSubmenu, + SelectFirstItem, Customizing: Boolean; const APopupPoint: TPoint; + const Alignment: TTBPopupAlignment): TTBPopupWindow; +var + DoSelectFirstItem: Boolean; +begin + if AlwaysSelectFirst then DoSelectFirstItem := True + else DoSelectFirstItem := SelectFirstItem; + Result := inherited CreatePopup(ParentView, ParentViewer, PositionAsSubmenu, + DoSelectFirstItem, Customizing, APopupPoint, Alignment); +end; + +destructor TTBXCustomItem.Destroy; +begin + FFontSettings.Free; + inherited; +end; + +procedure TTBXCustomItem.FontSettingsChanged(Sender: TObject); +begin + Change(True); +end; + +function TTBXCustomItem.GetItemViewerClass(AView: TTBView): TTBItemViewerClass; +begin + Result := TTBXItemViewer; +end; + +procedure TTBXCustomItem.GetPopupPosition(ParentView: TTBView; + PopupWindow: TTBPopupWindow; var PopupPositionRec: TTBPopupPositionRec); +var + VT: Integer; +begin + if CurrentTheme.OfficeXPPopupAlignment then with PopupPositionRec do + begin + GetOfficeXPPopupPosition1(PopupPositionRec); + inherited GetPopupPosition(ParentView, PopupWindow, PopupPositionRec); + GetOfficeXPPopupPosition2(PopupPositionRec); + VT := GetWinViewType(PopupWindow); + PopupPositionRec.PlaySound := not (VT and PVT_LISTBOX = PVT_LISTBOX); + end + else inherited; +end; + +function TTBXCustomItem.GetPopupWindowClass: TTBPopupWindowClass; +begin + Result := TTBXPopupWindow; +end; + +function TTBXCustomItem.GetStretch: Boolean; +begin + Result := tbisStretch in ItemStyle; +end; + +procedure TTBXCustomItem.Invalidate; +begin + Change(False); +end; + +procedure TTBXCustomItem.SetFontSettings(Value: TFontSettings); +begin + FFontSettings.Assign(Value); +end; + +procedure TTBXCustomItem.SetLayout(Value: TTBXItemLayout); +begin + if Value <> FLayout then + begin + FLayout := Value; + Change(True); + end; +end; + +procedure TTBXCustomItem.SetMinHeight(Value: Integer); +begin + if Value <> FMinHeight then + begin + FMinHeight := Value; + Change(True); + end; +end; + +procedure TTBXCustomItem.SetMinWidth(Value: Integer); +begin + if Value <> FMinWidth then + begin + FMinWidth := Value; + Change(True); + end; +end; + +procedure TTBXCustomItem.SetStretch(Value: Boolean); +begin + if Value xor (tbisStretch in ItemStyle) then + begin + if Value then ItemStyle := ItemStyle + [tbisStretch] + else ItemStyle := ItemStyle - [tbisStretch]; + Change(True); + end; +end; + + +//============================================================================// + +{ TTBXItemViewer } + +procedure TTBXItemViewer.CalcSize(const Canvas: TCanvas; var AWidth, AHeight: Integer); +const + CMarginIDs: array [Boolean] of Integer = (MID_MENUITEM, MID_TOOLBARITEM); + CStartSize: array [Boolean] of Integer = (0, 6); +var + W, H: Integer; + ImgSize: TSize; + Item: TTBCustomItem; + ItemLayout, SaveLayout: TTBXItemLayout; + IsCaptionShown: Boolean; + IsTextRotated: Boolean; + ToolbarStyle: Boolean; + S: string; + TextFlags: Cardinal; + TextMetric: TTextMetric; + TextSize: TSize; + Margins: TTBXMargins; +begin + Item := TTBCustomItem(Self.Item); + ToolbarStyle := IsToolbarStyle; + ImgSize := GetImageSize; + if (ImgSize.CX <= 0) or (ImgSize.CY <= 0) then + begin + ImgSize.CX := 0; + ImgSize.CY := 0; + end; + + if Item is TTBXCustomItem then ItemLayout := TTBXCustomItem(Item).Layout + else ItemLayout := tbxlAuto; + SaveLayout := ItemLayout; + if ItemLayout = tbxlAuto then + begin + if tboImageAboveCaption in Item.EffectiveOptions then ItemLayout := tbxlGlyphTop + else + begin + if View.Orientation <> tbvoVertical then ItemLayout := tbxlGlyphLeft + else ItemLayout := tbxlGlyphTop; + end; + end; + + { Setup font } + TextFlags := 0; + IsCaptionShown := CaptionShown; + IsTextRotated := (View.Orientation = tbvoVertical) and ToolbarStyle; + if IsCaptionShown then + begin + S := GetCaptionText; + if not (SaveLayout = tbxlAuto) or (tboImageAboveCaption in Item.EffectiveOptions) then IsTextRotated := False; + if IsTextRotated or not ToolbarStyle then TextFlags := DT_SINGLELINE; + TextSize := GetTextSize(Canvas, S, TextFlags, IsTextRotated, 0); + end + else + begin + SetLength(S, 0); + TextSize.CX := 0; + TextSize.CY := 0; + IsTextRotated := False; + end; + + { Measure size } + if ToolbarStyle then + begin + AWidth := 6; + AHeight := 6; + + if CaptionShown then + begin + Inc(AWidth, TextSize.CX); + Inc(AHeight, TextSize.CY); + if not IsTextRotated then Inc(AWidth, 4) + else Inc(AHeight, 4); + end; + + if GetImageShown and (ImgSize.CX > 0) and (ImgSize.CY > 0) then + begin + if ItemLayout = tbxlGlyphLeft then + begin + Inc(AWidth, ImgSize.CX); + if Wide then Inc(AWidth); + if AHeight < ImgSize.CY + 6 then AHeight := ImgSize.CY + 6; + end + else + begin + Inc(AHeight, ImgSize.CY); + if AWidth < ImgSize.CX + 7 then AWidth := ImgSize.CX + 7; + end; + end; + + if tbisSubmenu in TTBItemAccess(Item).ItemStyle then with CurrentTheme do + begin + if tbisCombo in TTBItemAccess(Item).ItemStyle then Inc(AWidth, SplitBtnArrowWidth) + else if tboDropdownArrow in Item.EffectiveOptions then + begin + if (ItemLayout <> tbxlGlyphTop) or (ImgSize.CX = 0) or IsTextRotated then + begin + if View.Orientation <> tbvoVertical then Inc(AWidth, DropdownArrowWidth) + else Inc(AHeight, DropdownArrowWidth); + end + else + begin + if (ItemLayout = tbxlGlyphTop) and (IsTextRotated xor (View.Orientation <> tbvoVertical)) then + begin + W := ImgSize.CX + DropDownArrowWidth + 2; + if W > AWidth - 7 then AWidth := W + 7; + end + else + begin + H := ImgSize.CY + DropDownArrowWidth + 2; + if H > AHeight - 7 then AHeight := H + 7; + end; + end + end; + end; + end + else // Not a ToolbarStyle + with CurrentTheme do + begin + GetTextMetrics(Canvas.Handle, TextMetric); + Inc(TextSize.CY, TextMetric.tmExternalLeading); + + AWidth := TextSize.CX; + AHeight := TextSize.CY; + + if ImgSize.CY = 0 then ImgSize.CY := 16; + if AHeight < ImgSize.CY then AHeight := ImgSize.CY; + + GetMargins(MID_MENUITEM, Margins); + Inc(AWidth, Margins.LeftWidth + Margins.RightWidth); + Inc(AHeight, Margins.TopHeight + Margins.BottomHeight); + + Inc(AWidth, GetPopupMargin(Self) + MenuImageTextSpace + MenuLeftCaptionMargin + MenuRightCaptionMargin); + S := Item.GetShortCutText; + if Length(S) > 0 then Inc(AWidth, (AHeight - 6) + GetTextWidth(Canvas.Handle, S, True)); + Inc(AWidth, AHeight); { Note: maybe this should be controlled by the theme } + end; + + if Item is TTBXCustomItem then with TTBXCustomItem(Item) do + begin + if AWidth < MinWidth then AWidth := MinWidth; + if AHeight < MinHeight then AHeight := MinHeight; + end; +end; + +constructor TTBXItemViewer.Create(AView: TTBView; AItem: TTBCustomItem; AGroupLevel: Integer); +begin + inherited; + FWide := True; +end; + +procedure TTBXItemViewer.DoAdjustFont(AFont: TFont; StateFlags: Integer); +begin + if tboDefault in Item.EffectiveOptions then with AFont do Style := Style + [fsBold]; + if Item is TTBXCustomItem then + with TTBXCustomItem(Item) do + begin + FontSettings.Apply(AFont); + if Assigned(FOnAdjustFont) then FOnAdjustFont(Item, Self, AFont, StateFlags); + end + else if Item is TTBXEditItem then + with TTBXEditItem(Item) do + begin + FontSettings.Apply(AFont); + end; +end; + +procedure TTBXItemViewer.DoPaintCaption(Canvas: TCanvas; const ClientAreaRect: TRect; + var CaptionRect: TRect; IsTextRotated: Boolean; var PaintDefault: Boolean); +begin + // do nothing +end; + +procedure TTBXItemViewer.DrawItemImage(Canvas: TCanvas; ARect: TRect; ItemInfo: TTBXItemInfo); +var + ImgList: TCustomImageList; + I: TTBXCustomItem; +begin + ImgList := GetImageList; + if (ImgList <> nil) and (Item.ImageIndex >= 0) and (Item.ImageIndex < ImgList.Count) then + begin + CurrentTheme.PaintImage(Canvas, ARect, ItemInfo, ImgList, Item.ImageIndex); + if Item is TTBXCustomItem then + begin + I := TTBXCustomItem(Item); + if Assigned(I.FOnDrawImage) then + I.FOnDrawImage(I, Self, Canvas, ARect, + CurrentTheme.GetImageOffset(Canvas, ItemInfo, ImgList), + GetStateFlags(ItemInfo)); + end; + end; +end; + +function TTBXItemViewer.GetAccRole: Integer; +{ Returns the MSAA "role" of the viewer. } +const + { Constants from OleAcc.h } + ROLE_SYSTEM_BUTTONDROPDOWNGRID = $3A; +begin + Result := inherited GetAccRole; + if (Item is TTBXCustomItem) and TTBXCustomItem(Item).ToolBoxPopup and + (tbisSubmenu in TTBXCustomItem(Item).ItemStyle) then + Result := ROLE_SYSTEM_BUTTONDROPDOWNGRID; +end; + +function TTBXItemViewer.GetImageShown: Boolean; +begin + Result := (Item.ImageIndex >= 0) and + ((Item.DisplayMode in [nbdmDefault, nbdmImageAndText]) or + (IsToolbarStyle and (Item.DisplayMode = nbdmTextOnlyInMenus))); +end; + +function TTBXItemViewer.GetImageSize: TSize; +var + ImgList: TCustomImageList; +begin + ImgList := GetImageList; + with Result do if ImgList <> nil then + begin + CX := ImgList.Width; + CY := ImgList.Height; + end + else + begin + CX := 0; + CY := 0; + end; +end; + +function TTBXItemViewer.GetItemType: Integer; +begin + if IsToolbarStyle then Result := IT_TOOLBARBUTTON + else Result := IT_MENUITEM; +end; + +function TTBXItemViewer.GetTextFlags: Cardinal; +begin + Result := 0; + if not AreKeyboardCuesEnabled and (vsUseHiddenAccels in View.Style) and + not (vsShowAccels in View.State) then Result := DT_HIDEPREFIX; +end; + +function TTBXItemViewer.GetTextSize(Canvas: TCanvas; const Text: string; + TextFlags: Cardinal; Rotated: Boolean; StateFlags: Integer): TSize; +var + DC: HDC; + R: TRect; + RotatedFont, SaveFont: HFONT; + TextMetric: TTextMetric; +begin + { note: rotated font size is consistent only for single-line captions! } + if Length(Text) = 0 then with Result do + begin + CX := 0; + CY := 0; + Exit; + end; + + { Select proper font } + Canvas.Font := TTBViewAccess(View).GetFont; + DoAdjustFont(Canvas.Font, StateFlags); + + if not Rotated then with R, Result do + begin + Left := 0; Right := 1; + Top := 0; Bottom := 0; + DrawText(Canvas.Handle, PChar(Text), Length(Text), R, TextFlags or DT_CALCRECT); + CX := Right; + CY := Bottom; + end + else + begin + DC := Canvas.Handle; + RotatedFont := CreateRotatedFont(DC); + SaveFont := SelectObject(DC, RotatedFont); + GetTextMetrics(DC, TextMetric); + Result.CX := TextMetric.tmHeight; + Result.CY := GetTextWidth(DC, Text, True); + SelectObject(DC, SaveFont); + DeleteObject(RotatedFont); + end; +end; + +function TTBXItemViewer.IsPtInButtonPart(X, Y: Integer): Boolean; +var + W: Integer; +begin + Result := not (tbisSubmenu in TTBItemAccess(Item).ItemStyle); + if (tbisCombo in TTBItemAccess(Item).ItemStyle) then + begin + if IsToolbarStyle then W := CurrentTheme.SplitBtnArrowWidth + else W := GetSystemMetrics(SM_CXMENUCHECK); + Result := X < (BoundsRect.Right - BoundsRect.Left) - W; + end; +end; + +function TTBXItemViewer.IsToolbarSize: Boolean; +begin + Result := inherited IsToolbarSize; + Result := Result or ((GetViewType(View) and PVT_TOOLBOX) = PVT_TOOLBOX); +end; + +function TTBXItemViewer.IsToolbarStyle: Boolean; +begin + Result := inherited IsToolbarStyle; + Result := Result or ((GetViewType(View) and PVT_TOOLBOX) = PVT_TOOLBOX); +end; + +procedure TTBXItemViewer.MouseUp(X, Y: Integer; MouseWasDownOnMenu: Boolean); +begin + inherited; + { Force the item to behave as a 'normal' menu item + That is make it respond to mouse as an item with IsToolbarStyle = False } + if Item.Enabled and not ((tbisSubmenu in TTBItemAccess(Item).ItemStyle) and + not IsPtInButtonPart(X, Y)) then + begin + if View.MouseOverSelected then + begin + Execute(True); + end; + end; +end; + +procedure TTBXItemViewer.Paint(const Canvas: TCanvas; + const ClientAreaRect: TRect; IsHoverItem, IsPushed, UseDisabledShadow: Boolean); +const + CToolbarStyle: array [Boolean] of Integer = (0, IO_TOOLBARSTYLE); + CCombo: array [Boolean] of Integer = (0, IO_COMBO); + CSubmenuItem: array [Boolean] of Integer = (0, IO_SUBMENUITEM); + CDesigning: array [Boolean] of Integer = (0, IO_DESIGNING); + CAppActive: array [Boolean] of Integer = (0, IO_APPACTIVE); +var + Item: TTBXCustomItem; + View: TTBViewAccess; + ItemInfo: TTBXItemInfo; + + M: Integer; + R: TRect; + ComboRect: TRect; + CaptionRect: TRect; + ImageRect: TRect; + C: TColor; + + ToolbarStyle: Boolean; + HasArrow: Boolean; + IsSplit: Boolean; + ImageIsShown: Boolean; + ImageOrCheckShown: Boolean; + ImgAndArrowWidth: Integer; + ImgSize: TSize; + IsComboPushed: Boolean; + IsCaptionShown: Boolean; + IsTextRotated: Boolean; + ItemLayout: TTBXItemLayout; + PaintDefault: Boolean; + S: string; + StateFlags: Integer; + IsSpecialDropDown: Boolean; + TextFlags: Cardinal; + TextMetrics: TTextMetric; + TextSize: TSize; + Margins: TTBXMargins; +begin + Item := TTBXCustomItem(Self.Item); + View := TTBViewAccess(Self.View); + + ToolbarStyle := IsToolbarStyle; + IsSplit := tbisCombo in Item.ItemStyle; + IsComboPushed := IsSplit and IsPushed and not View.Capture; + if IsComboPushed then IsPushed := False; + + if GetImageShown then + begin + ImgSize := GetImageSize; + with ImgSize do if (CX <= 0) or (CY <= 0) then + begin + CX := 0; + CY := 0; + ImageIsShown := False; + end + else ImageIsShown := True; + end + else + begin + ImgSize.CX := 0; + ImgSize.CY := 0; + ImageIsShown := False; + end; + IsSplit := tbisCombo in Item.ItemStyle; + + FillChar(ItemInfo, SizeOf(ItemInfo), 0); + ItemInfo.ViewType := GetViewType(View); + ItemInfo.ItemOptions := CToolbarStyle[ToolbarStyle] or CCombo[IsSplit] or + CDesigning[csDesigning in Item.ComponentState] or CSubmenuItem[tbisSubmenu in Item.ItemStyle] or + CAppActive[Application.Active]; + ItemInfo.Enabled := Item.Enabled or View.Customizing; + ItemInfo.Pushed := IsPushed; + ItemInfo.Selected := Item.Checked; + ItemInfo.ImageShown := ImageIsShown; + ItemInfo.ImageWidth := ImgSize.CX; + ItemInfo.ImageHeight := ImgSize.CY; + if IsHoverItem then + begin + if not ItemInfo.Enabled and not View.MouseOverSelected then ItemInfo.HoverKind := hkKeyboardHover + else if ItemInfo.Enabled then ItemInfo.HoverKind := hkMouseHover; + end + else ItemInfo.HoverKind := hkNone; + ItemInfo.IsPopupParent := ToolbarStyle and + (((vsModal in View.State) and Assigned(View.OpenViewer)) or (tbisSubmenu in Item.ItemStyle)) and + ((IsSplit and IsComboPushed) or (not IsSplit and IsPushed)); + ItemInfo.IsVertical := (View.Orientation = tbvoVertical) and not IsSplit; + ItemInfo.PopupMargin := GetPopupMargin(Self); + + ItemLayout := Item.Layout; + if ItemLayout = tbxlAuto then + begin + if tboImageAboveCaption in Item.EffectiveOptions then ItemLayout := tbxlGlyphTop + else if View.Orientation <> tbvoVertical then ItemLayout := tbxlGlyphLeft + else ItemLayout := tbxlGlyphTop; + end; + + HasArrow := (tbisSubmenu in Item.ItemStyle) and + ((tbisCombo in Item.ItemStyle) or (tboDropdownArrow in Item.EffectiveOptions)); + + if GetImageShown then + begin + ImgSize := GetImageSize; + with ImgSize do if (CX <= 0) or (CY <= 0) then + begin + CX := 0; + CY := 0; + ImageIsShown := False; + end + else ImageIsShown := True; + end + else + begin + ImgSize.CX := 0; + ImgSize.CY := 0; + ImageIsShown := False; + end; + ImageOrCheckShown := ImageIsShown or (not ToolbarStyle and Item.Checked); + + StateFlags := GetStateFlags(ItemInfo); + + Canvas.Font := TTBViewAccess(View).GetFont; + Canvas.Font.Color := CurrentTheme.GetItemTextColor(ItemInfo); + DoAdjustFont(Canvas.Font, StateFlags); + C := Canvas.Font.Color; + + { Setup font } + TextFlags := GetTextFlags; + IsCaptionShown := CaptionShown; + IsTextRotated := (View.Orientation = tbvoVertical) and ToolbarStyle; + if IsCaptionShown then + begin + S := GetCaptionText; + if (Item.Layout <> tbxlAuto) or (tboImageAboveCaption in Item.EffectiveOptions) then + IsTextRotated := False; + if IsTextRotated or not ToolbarStyle then TextFlags := TextFlags or DT_SINGLELINE; + TextSize := GetTextSize(Canvas, S, TextFlags, IsTextRotated, StateFlags); + end + else + begin + StateFlags := 0; + SetLength(S, 0); + IsTextRotated := False; + TextSize.CX := 0; + TextSize.CY := 0; + end; + + IsSpecialDropDown := HasArrow and not IsSplit and ToolbarStyle and + ((Item.Layout = tbxlGlyphTop) or (Item.Layout = tbxlAuto) and (tboImageAboveCaption in Item.EffectiveOptions)) and + (ImgSize.CX > 0) and not (IsTextRotated) and (TextSize.CX > 0); + + { Border & Arrows } + R := ClientAreaRect; + with CurrentTheme do if ToolbarStyle then + begin + GetMargins(MID_TOOLBARITEM, Margins); + if HasArrow then with R do + begin + ItemInfo.ComboPart := cpCombo; + if IsSplit then + begin + ItemInfo.ComboPart := cpSplitLeft; + ComboRect := R; + Dec(Right, SplitBtnArrowWidth); + ComboRect.Left := Right; + end + else if not IsSpecialDropDown then + begin + if View.Orientation <> tbvoVertical then + ComboRect := Rect(Right - DropdownArrowWidth - DropdownArrowMargin, 0, + Right - DropdownArrowMargin, Bottom) + else + ComboRect := Rect(0, Bottom - DropdownArrowWidth - DropdownArrowMargin, + Right, Bottom - DropdownArrowMargin); + end + else + begin + ImgAndArrowWidth := ImgSize.CX + DropdownArrowWidth + 2; + ComboRect.Right := (R.Left + R.Right + ImgAndArrowWidth + 2) div 2; + ComboRect.Left := ComboRect.Right - DropdownArrowWidth; + ComboRect.Top := (R.Top + R.Bottom - ImgSize.cy - 2 - TextSize.CY) div 2; + ComboRect.Bottom := ComboRect.Top + ImgSize.CY; + end; + end + else SetRectEmpty(ComboRect); + + if not IsSplit then + begin + PaintButton(Canvas, R, ItemInfo); + if HasArrow then + begin + PaintDropDownArrow(Canvas, ComboRect, ItemInfo); + if not IsSpecialDropDown then + begin + if View.Orientation <> tbvoVertical then Dec(R.Right, DropdownArrowWidth) + else Dec(R.Bottom, DropdownArrowWidth); + end; + end; + end + else // IsSplit + begin + CurrentTheme.PaintButton(Canvas, R, ItemInfo); + ItemInfo.Pushed := IsComboPushed; + ItemInfo.Selected := False; + ItemInfo.ComboPart := cpSplitRight; + CurrentTheme.PaintButton(Canvas, ComboRect, ItemInfo); + ItemInfo.ComboPart := cpSplitLeft; + ItemInfo.Pushed := IsPushed; + ItemInfo.Selected := Item.Checked; + end; + InflateRect(R, -2, -2); + end + else // not toolbar style + begin + GetMargins(MID_MENUITEM, Margins); + PaintMenuItem(Canvas, R, ItemInfo); + Inc(R.Left, Margins.LeftWidth); + Dec(R.Right, Margins.RightWidth); + Inc(R.Top, Margins.TopHeight); + Dec(R.Bottom, Margins.BottomHeight); + end; + + { Caption } + if IsCaptionShown then + begin + if ToolbarStyle then + begin + CaptionRect := R; + TextFlags := TextFlags or DT_CENTER or DT_VCENTER; + if ImageIsShown then with CaptionRect do + case ItemLayout of + tbxlGlyphLeft: + begin + Inc(Left, ImgSize.CX + 3); + Top := (Top + Bottom - TextSize.CY) div 2; + Bottom := Top + TextSize.CY; + Left := (Left + Right - TextSize.CX) div 2; + Right := Left + TextSize.CX; + TextFlags := TextFlags and not DT_CENTER; + end; + tbxlGlyphTop: + begin + Inc(Top, ImgSize.CY + 1); + if IsTextRotated then Inc(CaptionRect.Top, 3); + Top := (Top + Bottom - TextSize.CY) div 2; + Bottom := Top + TextSize.CY; + Left := (Left + Right - TextSize.CX) div 2; + Right := Left + TextSize.CX; + TextFlags := TextFlags and not DT_VCENTER; + end; + end + else + begin + with CaptionRect, TextSize do + begin + Left := (Left + R.Right - CX) div 2; + Top := (Top + R.Bottom - CY) div 2; + Right := Left + CX; + Bottom := Top + CY; + end; + end; + + Canvas.Font.Color := C; + PaintDefault := True; + DoPaintCaption(Canvas, ClientAreaRect, CaptionRect, IsTextRotated, PaintDefault); + if PaintDefault then + CurrentTheme.PaintCaption(Canvas, CaptionRect, ItemInfo, S, TextFlags, IsTextRotated); + end + else with CurrentTheme do + begin + TextFlags := DT_LEFT or DT_VCENTER or TextFlags; + TextSize := GetTextSize(Canvas, S, TextFlags, False, StateFlags); { TODO : Check if this line is required } + GetTextMetrics(Canvas.Handle, TextMetrics); + + CaptionRect := R; + Inc(CaptionRect.Left, ItemInfo.PopupMargin + MenuImageTextSpace + MenuLeftCaptionMargin); + with TextMetrics, CaptionRect do + if (Bottom - Top) - (tmHeight + tmExternalLeading) = Margins.BottomHeight then Dec(Bottom); + Inc(CaptionRect.Top, TextMetrics.tmExternalLeading); + + CaptionRect.Right := CaptionRect.Left + TextSize.CX; + + Canvas.Font.Color := C; + PaintDefault := True; + DoPaintCaption(Canvas, ClientAreaRect, CaptionRect, IsTextRotated, PaintDefault); + if PaintDefault then + CurrentTheme.PaintCaption(Canvas, CaptionRect, ItemInfo, S, TextFlags, IsTextRotated); + end; + end; + + { Shortcut and/or submenu arrow (menus only) } + if not ToolbarStyle then + begin + S := Item.GetShortCutText; + if Length(S) > 0 then + begin + CaptionRect := R; + with CaptionRect, TextMetrics do + begin + Left := Right - (Bottom - Top) - GetTextWidth(Canvas.Handle, S, True); + if (Bottom - Top) - (tmHeight + tmExternalLeading) = Margins.BottomHeight then Dec(Bottom); + Inc(Top, TextMetrics.tmExternalLeading); + end; + Canvas.Font.Color := C; + PaintDefault := True; + DoPaintCaption(Canvas, ClientAreaRect, CaptionRect, IsTextRotated, PaintDefault); + if PaintDefault then + CurrentTheme.PaintCaption(Canvas, CaptionRect, ItemInfo, S, TextFlags, False); + end; + end; + + { Image, or check box } + if ImageOrCheckShown then + begin + ImageRect := R; + + if ToolBarStyle then + begin + if IsSpecialDropDown then OffsetRect(ImageRect, (-CurrentTheme.DropdownArrowWidth + 1) div 2, 0); + if ItemLayout = tbxlGlyphLeft then ImageRect.Right := ImageRect.Left + ImgSize.CX + 2 + else + begin + ImageRect.Top := (ImageRect.Top + ImageRect.Bottom - ImgSize.cy - 2 - TextSize.cy) div 2; + ImageRect.Bottom := ImageRect.Top + ImgSize.CY; + end; + end + else ImageRect.Right := ImageRect.Left + ClientAreaRect.Bottom - ClientAreaRect.Top; + + if ImageIsShown then with ImageRect, ImgSize do + begin + Left := Left + ((Right - Left) - CX) div 2; + ImageRect.Top := Top + ((Bottom - Top) - CY) div 2; + Right := Left + CX; + Bottom := Top + CY; + DrawItemImage(Canvas, ImageRect, ItemInfo); + end + else if not ToolbarStyle and Item.Checked then + CurrentTheme.PaintCheckMark(Canvas, ImageRect, ItemInfo); + end; +end; + + +//============================================================================// + +{ TTBXSubmenuItem } + +constructor TTBXSubmenuItem.Create(AOwner: TComponent); +begin + inherited; + ItemStyle := ItemStyle + [tbisSubMenu, tbisSubitemsEditable]; +end; + +function TTBXSubmenuItem.GetDropdownCombo: Boolean; +begin + Result := tbisCombo in ItemStyle; +end; + +procedure TTBXSubmenuItem.SetDropdownCombo(Value: Boolean); +begin + if (tbisCombo in ItemStyle) <> Value then begin + if Value then ItemStyle := ItemStyle + [tbisCombo] + else ItemStyle := ItemStyle - [tbisCombo]; + Change (True); + end; +end; + + + +//============================================================================// + +{ TTBXSeparatorItem } + +constructor TTBXSeparatorItem.Create(AOwner: TComponent); +begin + inherited; + FSize := -1; // use default from as in TTBSeparatorItem +end; + +function TTBXSeparatorItem.GetItemViewerClass(AView: TTBView): TTBItemViewerClass; +begin + Result := TTBXSeparatorItemViewer; +end; + +procedure TTBXSeparatorItem.SetSize(Value: Integer); +begin + if Value < -1 then Value := -1; + if Value <> FSize then + begin + FSize := Value; + Change(True); + end; +end; + + +//============================================================================// + +{ TTBXSeparatorItemViewer } + +procedure TTBXSeparatorItemViewer.CalcSize(const Canvas: TCanvas; + var AWidth, AHeight: Integer); +var + SZ: Integer; +begin + SZ := TTBXSeparatorItem(Item).Size; + if SZ < 0 then + begin + if not IsToolbarStyle then SZ := CurrentTheme.MenuSeparatorSize + else SZ := CurrentTheme.TlbrSeparatorSize; + if SZ < 0 then inherited CalcSize(Canvas, AWidth, AHeight) + else + begin + AWidth := SZ; + AHeight := SZ; + end; + end + else if not IsToolbarStyle then + begin + AHeight := SZ; + AWidth := 0; + end + else + begin + AWidth := SZ; + AHeight := SZ; + end; +end; + +function TTBXSeparatorItemViewer.IsToolbarSize: Boolean; +begin + Result := inherited IsToolbarSize; + Result := Result or ((GetViewType(View) and PVT_TOOLBOX) = PVT_TOOLBOX); +end; + +function TTBXSeparatorItemViewer.IsToolbarStyle: Boolean; +begin + Result := inherited IsToolbarStyle; + Result := Result or ((GetViewType(View) and PVT_TOOLBOX) = PVT_TOOLBOX); +end; + +procedure TTBXSeparatorItemViewer.Paint(const Canvas: TCanvas; + const ClientAreaRect: TRect; IsHoverItem, IsPushed, UseDisabledShadow: Boolean); +const + CToolbarStyle: array [Boolean] of Integer = (0, IO_TOOLBARSTYLE); + CDesigning: array [Boolean] of Integer = (0, IO_DESIGNING); +var + Item: TTBXSeparatorItem; + ItemInfo: TTBXItemInfo; + R: TRect; + LineSep, HorzLine: Boolean; +begin + Item := TTBXSeparatorItem(Self.Item); + if Item.Size = 0 then Exit; + + FillChar(ItemInfo, SizeOf(TTBXItemInfo), 0); + ItemInfo.ViewType := GetViewType(View); + ItemInfo.ItemOptions := CToolbarStyle[IsToolbarStyle] or + CDesigning[csDesigning in Item.ComponentState]; + ItemInfo.Enabled := not Item.Blank; + ItemInfo.Pushed := IsPushed; + ItemInfo.Selected := False; + ItemInfo.ImageShown := False; + ItemInfo.ImageWidth := 0; + ItemInfo.ImageHeight := 0; + ItemInfo.IsVertical := View.Orientation = tbvoVertical; + if not IsToolbarStyle then ItemInfo.PopupMargin := GetPopupMargin(Self); + + R := ClientAreaRect; + LineSep := tbisLineSep in State; + with ItemInfo do + begin + HorzLine := (IsVertical xor LineSep) or View.IsPopup; + if (((ViewType and VT_POPUP) = VT_POPUP) and + ((ViewType and PVT_CHEVRONMENU) = PVT_CHEVRONMENU)) then + HorzLine := (HorzLine and LineSep); + end; + CurrentTheme.PaintSeparator(Canvas, R, ItemInfo, HorzLine, LineSep); +end; + +//============================================================================// + +{ TTBXVisibilityToggleItem } + +procedure TTBXVisibilityToggleItem.Click; +begin + if Assigned(FControl) then FControl.Visible := not FControl.Visible; + inherited; +end; + +procedure TTBXVisibilityToggleItem.InitiateAction; +begin + UpdateProps; +end; + +procedure TTBXVisibilityToggleItem.Notification(AComponent: TComponent; Operation: TOperation); +begin + inherited; + if (Operation = opRemove) and (AComponent = FControl) then Control := nil; +end; + +procedure TTBXVisibilityToggleItem.SetControl(Value: TControl); +begin + if FControl <> Value then + begin + FControl := Value; + if Assigned(Value) then + begin + Value.FreeNotification(Self); + if (Length(Caption) = 0) and not (csLoading in ComponentState) then + Caption := TControlAccess(Value).Caption; + end; + UpdateProps; + end; +end; + +procedure TTBXVisibilityToggleItem.UpdateProps; +begin + if (ComponentState * [csDesigning, csLoading, csDestroying] = []) then + Checked := Assigned(FControl) and FControl.Visible; +end; + +//============================================================================// + +{ TTBXPopupWindow } + +procedure TTBXPopupWindow.CMHintShow(var Message: TCMHintShow); +begin + with Message.HintInfo^ do + begin + HintStr := ''; + if Assigned(View.Selected) then + begin + CursorRect := View.Selected.BoundsRect; + HintStr := View.Selected.GetHintText; + View.Selected.Dispatch(Message); + end; + end; +end; + +procedure TTBXPopupWindow.CreateParams(var Params: TCreateParams); +const + CS_DROPSHADOW = $00020000; +begin + inherited CreateParams(Params); + with Params do + begin + WindowClass.Style := WindowClass.Style and not (CS_DROPSHADOW or CS_DBLCLKS); + if GetShowShadow and (CurrentTheme.GetPopupShadowType = PST_WINDOWSXP) and IsWindowsXP then + begin + WindowClass.Style := WindowClass.Style or CS_DROPSHADOW; + StrPCopy(WinClassName, ClassName + 'S'); + end; + end; +end; + +procedure TTBXPopupWindow.CreateShadow; +var + PR: TRect; + ParentViewer: TTBItemViewer; + VT: Integer; + ChevronParent: Boolean; +begin + if (CurrentTheme.GetPopupShadowType = PST_WINDOWS2K) and not + ((Win32Platform = VER_PLATFORM_WIN32_NT) and (Win32MajorVersion >= 5)) then Exit; + + PR := Rect(0, 0, 0, 0); + if CurrentTheme.GetPopupShadowType = PST_OFFICEXP then + begin + if (View <> nil) and (View.ParentView <> nil) then + begin + ParentViewer := TTBViewAccess(View.ParentView).OpenViewer; + ChevronParent := Self is TTBXChevronPopupWindow; + if ((ParentViewer is TTBXItemViewer) or ChevronParent) then + begin + VT := GetViewType(ParentViewer.View); + if ((VT and PVT_POPUPMENU) <> PVT_POPUPMENU) or ChevronParent then + begin + PR := ParentViewer.BoundsRect; + PR.TopLeft := View.ParentView.Window.ClientToScreen(PR.TopLeft); + PR.BottomRight := View.ParentView.Window.ClientToScreen(PR.BottomRight); + end; + end; + end + else if not IsRectEmpty(FControlRect) then + begin + PR := FControlRect; + end; + end; + FShadows := TShadows.Create(PR, BoundsRect, 4, 61, TBXLoColor); + FShadows.Show(Handle); +end; + +destructor TTBXPopupWindow.Destroy; +begin + DestroyShadow; + inherited; +end; + +procedure TTBXPopupWindow.DestroyShadow; +var + SaveShadows: TObject; +begin + SaveShadows := FShadows; + FShadows := nil; + SaveShadows.Free; +end; + +function TTBXPopupWindow.GetFillColor: TColor; +begin + Result := CurrentTheme.GetViewColor(GetViewType(View)); + View.BackgroundColor := Result; +end; + +function TTBXPopupWindow.GetNCSize: TPoint; +begin + Result := inherited GetNCSize; + CurrentTheme.GetViewBorder(GetViewType(View), Result); +end; + +function TTBXPopupWindow.GetShowShadow: Boolean; +begin + Result := ((GetViewType(View) and PVT_LISTBOX) <> PVT_LISTBOX ); +end; + +function TTBXPopupWindow.GetViewClass: TTBViewClass; +begin + Result := TTBXPopupView; +end; + +procedure TTBXPopupWindow.TBMGetViewType(var Message: TMessage); +var + PI: TTBCustomItem; +begin + Message.Result := PVT_POPUPMENU; + if View <> nil then + if Self is TTBXChevronPopupWindow then + Message.Result := PVT_CHEVRONMENU + else + begin + PI := View.ParentItem; + if PI <> nil then + begin + if (PI.Count = 1) and (PI.Items[0] is TTBXCustomList) then + Message.Result := PVT_LISTBOX + else if PI is TTBXEditItem then + begin + Message.Result := PVT_TOOLBOX; + end + else if (PI is TTBXCustomItem) and (TTBXCustomItem(PI).ToolBoxPopup) then + Message.Result := PVT_TOOLBOX + end; + end; +end; + +procedure TTBXPopupWindow.WMEraseBkgnd(var Message: TWmEraseBkgnd); +var + Canvas: TCanvas; + R: TRect; +begin + TBEndAnimation(WindowHandle); + Canvas := TCanvas.Create; + Canvas.Handle := Message.DC; + R := ClientRect; + CurrentTheme.PaintBackgnd(Canvas, R, R, R, GetFillColor, False, GetViewType(View)); + Canvas.Handle := 0; + Canvas.Free; + Message.Result := 1; +end; + +procedure TTBXPopupWindow.WMNCCalcSize(var Message: TWMNCCalcSize); +var + Sz: TPoint; +begin + CurrentTheme.GetViewBorder(GetViewType(View), Sz); + with Message.CalcSize_Params^.rgrc[0], Sz do + begin + Inc(Left, X); + Inc(Top, Y); + Dec(Right, X); + Dec(Bottom, Y); + end; + Message.Result := 1; +end; + +procedure TBXPopupNCPaintProc(Wnd: HWND; DC: HDC; AppData: Longint); +var + R, R2: TRect; + Canvas: TCanvas; + View: TTBPopupView; + PopupInfo: TTBXPopupInfo; + ParentViewer: TTBItemViewer; +begin + Assert(DC <> 0, 'TBXPopupNCPaintProc'); + Canvas := TCanvas.Create; + try + Canvas.Handle := DC; + FillChar(PopupInfo, SizeOf(PopupInfo), 0); + View := TTBPopupView(AppData); + PopupInfo.WindowHandle := View.Window.Handle; + PopupInfo.ViewType := GetViewType(View); + if View.ParentView <> nil then + begin + ParentViewer := TTBViewAccess(View.ParentView).OpenViewer; + if ((ParentViewer is TTBXItemViewer) or (View.Window is TTBXChevronPopupWindow)) + and TTBItemViewerAccess(ParentViewer).IsToolbarStyle then + begin + R := ParentViewer.BoundsRect; + R.TopLeft := View.ParentView.Window.ClientToScreen(R.TopLeft); + R.BottomRight := View.ParentView.Window.ClientToScreen(R.BottomRight); + GetWindowRect(Wnd, R2); + OffsetRect(R, -R2.Left, -R2.Top); + PopupInfo.ParentRect := R; + end; + end + else if View.ParentItem is TTBXRootItem then + begin + R := TTBXRootItem(View.ParentItem).FPopupControlRect; + if not IsRectEmpty(R) then + begin + GetWindowRect(Wnd, R2); + OffsetRect(R, -R2.Left, -R2.Top); + PopupInfo.ParentRect := R; + end; + end; + GetWindowRect(Wnd, R); + OffsetRect(R, -R.Left, -R.Top); + CurrentTheme.GetViewBorder(PopupInfo.ViewType, PopupInfo.BorderSize); + R2 := R; + with PopupInfo.BorderSize do InflateRect(R2, -X, -Y); + with R2 do ExcludeClipRect(Canvas.Handle, Left, Top, Right, Bottom); + CurrentTheme.PaintPopupNCArea(Canvas, R, PopupInfo); + finally + Canvas.Handle := 0; + Canvas.Free; + end; +end; + +procedure TTBXPopupWindow.WMNCPaint(var Message: TMessage); +var + DC: HDC; +begin + DC := GetWindowDC(Handle); + try + Assert(DC <> 0, 'TTBXPopupWindow.WMNCPaint'); + SelectNCUpdateRgn(Handle, DC, HRGN(Message.WParam)); + TBXPopupNCPaintProc(Handle, DC, LongInt(Self.View)); + finally + ReleaseDC(Handle, DC); + end; +end; + +procedure TTBXPopupWindow.WMPrint(var Message: TMessage); +begin + HandleWMPrint(Handle, Message, TBXPopupNCPaintProc, LongInt(Self.View)); +end; + +procedure TTBXPopupWindow.WMTB2kPopupShowing(var Message: TMessage); +begin + if Message.WParam in [TPS_ANIMFINISHED, TPS_NOANIM] then + begin + if not (csDestroying in ComponentState) and GetShowShadow and + (CurrentTheme.GetPopupShadowType in [PST_OFFICEXP, PST_WINDOWS2K]) then CreateShadow; + end; +end; + +procedure TTBXPopupWindow.WMWindowPosChanged(var Message: TWMWindowPosChanged); +begin + inherited; + with Message.WindowPos^ do + if ((flags and SWP_SHOWWINDOW) = 0) and ((flags and SWP_HIDEWINDOW) = 0) then + begin + if FShadows <> nil then + begin + DestroyShadow; + CreateShadow; + end; + end; +end; + + +//============================================================================// + +{ TTBXToolbarView } + +procedure TTBXToolbarView.GetMargins(AOrientation: TTBViewOrientation; var Margins: TRect); +var + VT: Integer; + M: TTBXMargins; +begin + VT := GetWinViewType(TTBXToolbar(Owner)); + if (VT and VT_TOOLBAR) = VT_TOOLBAR then + begin + if AOrientation = tbvoFloating then VT := VT or TVT_FLOATING + else VT := VT and not TVT_FLOATING + end + else if (VT and VT_DOCKPANEL) = VT_DOCKPANEL then + begin + if AOrientation = tbvoFloating then VT := VT or DPVT_FLOATING + else VT := VT and not DPVT_FLOATING + end; + CurrentTheme.GetViewMargins(VT, M); + Margins.Left := M.LeftWidth; + Margins.Top := M.TopHeight; + Margins.Right := M.RightWidth; + Margins.Bottom := M.BottomHeight; +end; + + +//============================================================================// + +{ TTBXToolbar } + +procedure TTBXToolbar.CMColorChanged(var Message: TMessage); +begin + UpdateEffectiveColor; + if Docked and HandleAllocated then + begin + RedrawWindow(Handle, nil, 0, RDW_FRAME or RDW_INVALIDATE or + RDW_ERASE or RDW_UPDATENOW or RDW_ALLCHILDREN); + end; + UpdateChildColors; + Invalidate; +end; + +procedure TTBXToolbar.CMControlChange(var Message: TCMControlChange); +begin + inherited; + if Message.Inserting and (Color = clNone) then + Message.Control.Perform(CM_PARENTCOLORCHANGED, 1, EffectiveColor); +end; + +procedure TTBXToolbar.CMParentColorChanged(var Message: TMessage); +begin + if Embedded and (Color = clNone) then + begin + UpdateEffectiveColor; + if (Message.WParam = 0) then + begin + Message.WParam := 1; + Message.LParam := EffectiveColor; + end; + end; + inherited; + Invalidate; +end; + +constructor TTBXToolbar.Create(AOwner: TComponent); +begin + inherited; + AddThemeNotification(Self); + FEffectiveColor := Color; + Color := clNone; + ControlStyle := ControlStyle - [csOpaque]; + DblClickUndock := False; +end; + +destructor TTBXToolbar.Destroy; +begin + RemoveThemeNotification(Self); + inherited; +end; + +procedure TTBXToolbar.DrawNCArea(const DrawToDC: Boolean; const ADC: HDC; const Clip: HRGN); +var + DC: HDC; + R, CR, R2: TRect; + ACanvas: TCanvas; + ToolbarInfo: TTBXToolbarInfo; + UsingBackground: Boolean; +begin + if not Docked or not HandleAllocated then Exit; + + if not DrawToDC then DC := GetWindowDC(Handle) + else DC := ADC; + + UsingBackground := TDockAccess(CurrentDock).UsingBackground; + + try + GetToolbarInfo(ToolbarInfo); + GetWindowRect(Handle, R); + OffsetRect(R, -R.Left, -R.Top); + if not DrawToDC then + begin + SelectNCUpdateRgn(Handle, DC, Clip); + CR := R; + with ToolbarInfo.BorderSize, CR do + begin + InflateRect(CR, -X, -Y); + if ToolbarInfo.IsVertical then Inc(Top, GetTBXDragHandleSize(ToolbarInfo)) + else Inc(Left, GetTBXDragHandleSize(ToolbarInfo)); + ExcludeClipRect(DC, Left, Top, Right, Bottom); + end; + end; + + ACanvas := TCanvas.Create; + try + ACanvas.Handle := DC; + if CurrentTheme.SolidToolbarNCArea then + begin + ACanvas.Brush.Color := EffectiveColor; + ACanvas.Brush.Style := bsSolid; + end + else if UsingBackground then + begin + ACanvas.Brush.Color := EffectiveColor; + R2 := CurrentDock.ClientRect; + OffsetRect(R2, -Left, -Top); + TDockAccess(CurrentDock).DrawBackground(DC, R2); + if (Color = clNone) and CurrentDock.BackgroundOnToolbars then + ACanvas.Brush.Style := bsClear; + end + else + begin + ACanvas.Brush.Color := GetEffectiveColor(CurrentDock); + ACanvas.FillRect(R); + ACanvas.Brush.Color := EffectiveColor; + ACanvas.Brush.Style := bsSolid; + end; + + CurrentTheme.PaintToolbarNCArea(ACanvas, R, ToolbarInfo); + finally + ACanvas.Handle := 0; + ACanvas.Free; + end; + finally + if not DrawToDC then ReleaseDC(Handle, DC); + end; +end; + +function TTBXToolbar.Embedded: Boolean; +begin + Result := not (Floating or Docked); +end; + +function TTBXToolbar.GetChevronItemClass: TTBChevronItemClass; +begin + Result := TTBXChevronItem; +end; + +function TTBXToolbar.GetFloatingBorderSize: TPoint; +begin + CurrentTheme.GetViewBorder(GetViewType(View) or TVT_FLOATING, Result); +end; + +function TTBXToolbar.GetFloatingWindowParentClass: TTBFloatingWindowParentClass; +begin + Result := TTBXFloatingWindowParent; +end; + +procedure TTBXToolbar.GetToolbarInfo(out ToolbarInfo: TTBXToolbarInfo); +begin + FillChar(ToolbarInfo, SizeOf(ToolbarInfo), 0); + ToolbarInfo.WindowHandle := Handle; + ToolbarInfo.ViewType := GetWinViewType(Self); + if CurrentDock <> nil then + ToolbarInfo.IsVertical := CurrentDock.Position in [dpLeft,dpRight]; + ToolbarInfo.AllowDrag := CurrentDock.AllowDrag; + ToolbarInfo.DragHandleStyle := Ord(DragHandleStyle); + ToolbarInfo.ClientWidth := ClientWidth; + ToolbarInfo.ClientHeight := ClientHeight; + if ToolbarInfo.AllowDrag and CloseButtonWhenDocked then + begin + ToolbarInfo.CloseButtonState := CDBS_VISIBLE; + if CloseButtonDown then ToolbarInfo.CloseButtonState := ToolbarInfo.CloseButtonState or CDBS_PRESSED + else if CloseButtonHover then ToolbarInfo.CloseButtonState := ToolbarInfo.CloseButtonState or CDBS_HOT; + end; + ToolbarInfo.BorderStyle := BorderStyle; + CurrentTheme.GetViewBorder(ToolbarInfo.ViewType, ToolbarInfo.BorderSize); + ToolbarInfo.EffectiveColor := EffectiveColor; +end; + +function TTBXToolbar.GetViewClass: TTBToolbarViewClass; +begin + Result := TTBXToolbarView; +end; + +procedure TTBXToolbar.SetItemTransparency(const Value: TTBXItemTransparency); +begin + FItemTransparency := Value; + Invalidate; +end; + +procedure TTBXToolbar.SetParent(AParent: TWinControl); +begin + inherited; + if AParent is TTBXFloatingWindowParent then + TTBXFloatingWindowParent(AParent).SnapDistance := SnapDistance; +end; + +procedure TTBXToolbar.SetSnapDistance(Value: Integer); +begin + if Value < 0 then Value := 0; + FSnapDistance := Value; + if (Parent <> nil) and (Parent is TTBXFloatingWindowParent) then + TTBXFloatingWindowParent(Parent).SnapDistance := Value; +end; + +procedure TTBXToolbar.TBMGetEffectiveColor(var Message: TMessage); +begin + Message.WParam := EffectiveColor; + Message.Result := 1; +end; + +procedure TTBXToolbar.TBMGetViewType(var Message: TMessage); +begin + if MenuBar then Message.Result := TVT_MENUBAR + else Message.Result := TVT_NORMALTOOLBAR; + if Floating then Message.Result := Message.Result or TVT_FLOATING; + if Resizable then Message.Result := Message.Result or TVT_RESIZABLE; + case ItemTransparency of + itAuto: + if not (Floating or Docked) then Message.Result := Message.Result or TVT_EMBEDDED; + itDisable: + Message.Result := Message.Result or TVT_EMBEDDED; + end; +end; + +procedure TTBXToolbar.TBMThemeChange(var Message: TMessage); +begin + case Message.WParam of + TSC_BEFOREVIEWCHANGE: BeginUpdate; + TSC_AFTERVIEWCHANGE: + begin + EndUpdate; + UpdateEffectiveColor; + if Floating then UpdateNCArea(TTBXFloatingWindowParent(Parent), GetWinViewType(Self)) + else UpdateNCArea(Self, GetWinViewType(Self)); + Invalidate; + Arrange; + UpdateChildColors; + end; + TSC_APPACTIVATE, TSC_APPDEACTIVATE: + if MenuBar then Invalidate; + end; +end; + +procedure TTBXToolbar.UpdateChildColors; +var + M: TMessage; +begin + M.Msg := CM_PARENTCOLORCHANGED; + M.WParam := 1; + M.LParam := EffectiveColor; + M.Result := 0; + Broadcast(M); +end; + +procedure TTBXToolbar.UpdateEffectiveColor; +begin + if Color = clNone then + begin + if Embedded and (Parent <> nil) then + FEffectiveColor := GetEffectiveColor(Parent) + else + FEffectiveColor := CurrentTheme.GetViewColor(GetViewType(View)); + end + else FEffectiveColor := Color; +end; + +procedure TTBXToolbar.WMEraseBkgnd(var Message: TWmEraseBkgnd); +var + Canvas: TCanvas; + R, CR: TRect; + Transparent: Boolean; +begin + Transparent := False; + CR := ClientRect; + if Color = clNone then + if Docked and (TDockAccess(CurrentDock).UsingBackground) and CurrentDock.BackgroundOnToolbars + and not CurrentTheme.SolidToolbarClientArea then + begin + R := CurrentDock.ClientRect; + R.TopLeft := ScreenToClient(CurrentDock.ClientToScreen(R.TopLeft)); + R.BottomRight := ScreenToClient(CurrentDock.ClientToScreen(R.BottomRight)); + TDockAccess(CurrentDock).DrawBackground(Message.DC, R); + Message.Result := 1; + Transparent := True; + end + else if Embedded then + begin + Transparent := True; + DrawParentBackground(Self, Message.DC, CR); + end; + + Canvas := TCanvas.Create; + Canvas.Handle := Message.DC; + try + if Docked then + begin + R := CurrentDock.ClientRect; + R.TopLeft := ScreenToClient(CurrentDock.ClientToScreen(R.TopLeft)); + R.BottomRight := ScreenToClient(CurrentDock.ClientToScreen(R.BottomRight)); + end + else R := Rect(0, 0, 0, 0); + CurrentTheme.PaintBackgnd(Canvas, R, CR, CR, EffectiveColor, Transparent, GetWinViewType(Self)); + Message.Result := 1; + finally + Canvas.Handle := 0; + Canvas.Free; + end; +end; + +procedure TTBXToolbar.WMSize(var Message: TWMSize); +var + I: Integer; + V: TTBItemViewer; + R: TRect; +begin + inherited; + if Docked and TDockAccess(CurrentDock).UsingBackground and + TDockAccess(CurrentDock).BackgroundOnToolbars and + ((CurrentDock is TTBXDock) and not TTBXDock(CurrentDock).FResizing) then + begin + for I := 0 to View.ViewerCount - 1 do + begin + V := View.Viewers[I]; + if V.Show and not IsRectEmpty(V.BoundsRect) and not (V.Item is TTBControlItem) + then View.Invalidate(V); + end; + Self.Update; + InvalidateRect(Handle, nil, True); + for I := 0 to View.ViewerCount - 1 do + begin + V := View.Viewers[I]; + if V.Show and not IsRectEmpty(V.BoundsRect) and not (V.Item is TTBControlItem) + then + begin + R := V.BoundsRect; + ValidateRect(Handle, @R); + end; + end; + end; +end; + + +//============================================================================// + +{ TTBXChevronItem } + +function TTBXChevronItem.GetItemViewerClass(AView: TTBView): TTBItemViewerClass; +begin + Result := TTBXChevronItemViewer; +end; + +procedure TTBXChevronItem.GetPopupPosition(ParentView: TTBView; + PopupWindow: TTBPopupWindow; var PopupPositionRec: TTBPopupPositionRec); +begin + if CurrentTheme.OfficeXPPopupAlignment then with PopupPositionRec do + begin + GetOfficeXPPopupPosition1(PopupPositionRec); + inherited GetPopupPosition(ParentView, PopupWindow, PopupPositionRec); + GetOfficeXPPopupPosition2(PopupPositionRec); + end + else inherited; +end; + +function TTBXChevronItem.GetPopupWindowClass: TTBPopupWindowClass; +begin + Result := TTBXChevronPopupWindow; +end; + + +//============================================================================// + +{ TTBXChevronItemViewer } + +procedure TTBXChevronItemViewer.Paint(const Canvas: TCanvas; + const ClientAreaRect: TRect; IsHoverItem, IsPushed, UseDisabledShadow: Boolean); +const + CDesigning: array [Boolean] of Integer = (0, IO_DESIGNING); +var + ItemInfo: TTBXItemInfo; +begin + FillChar(ItemInfo, SizeOf(TTBXItemInfo), 0); + ItemInfo.ViewType := GetViewType(View); + ItemInfo.ItemOptions := IO_TOOLBARSTYLE or CDesigning[csDesigning in Item.ComponentState]; + ItemInfo.Enabled := Item.Enabled or View.Customizing; + ItemInfo.Pushed := IsPushed; + ItemInfo.Selected := False; + ItemInfo.ImageShown := False; + ItemInfo.ImageWidth := 0; + ItemInfo.ImageHeight := 0; + ItemInfo.IsPopupParent := IsPushed; + if IsHoverItem then + begin + if not ItemInfo.Enabled and not TTBViewAccess(View).MouseOverSelected then ItemInfo.HoverKind := hkKeyboardHover + else if ItemInfo.Enabled then ItemInfo.HoverKind := hkMouseHover; + end + else ItemInfo.HoverKind := hkNone; + ItemInfo.IsVertical := View.Orientation = tbvoVertical; + CurrentTheme.PaintChevron(Canvas, ClientAreaRect, ItemInfo); +end; + + +//============================================================================// + +{ TTBXRootItem } + +function TTBXRootItem.CreatePopupEx(SelectFirstItem: Boolean; + const AControlRect: TRect; Alignment: TTBPopupAlignment): TTBPopupWindow; +var + SavePopupRect: TRect; + Pt: TPoint; +begin + SavePopupRect := FPopupControlRect; + try + FPopupControlRect := AControlRect; + Pt.X := AControlRect.Left; + Pt.Y := AControlRect.Bottom; + Result := inherited CreatePopup(nil, nil, False, SelectFirstItem, False, Pt, Alignment); + if Result is TTBXPopupWindow then TTBXPopupWindow(Result).FControlRect := FPopupControlRect; + finally + FPopupControlRect := SavePopupRect; + end; +end; + +procedure TTBXRootItem.GetPopupPosition(ParentView: TTBView; + PopupWindow: TTBPopupWindow; var PopupPositionRec: TTBPopupPositionRec); +var + Y2: Integer; + VT: Integer; +begin + if IsRectEmpty(FPopupControlRect) then inherited + else with PopupPositionRec do + begin + ParentItemRect := FPopupControlRect; + if Y + H > MonitorRect.Bottom then + begin + Y2 := FPopupControlRect.Top - H; + if Y2 >= MonitorRect.Top then Y := Y2; + end; + if Y < MonitorRect.Top then Y := MonitorRect.Top + else if Y + H > MonitorRect.Bottom then Y := MonitorRect.Bottom - H; + + if Alignment = tbpaRight then X := FPopupControlRect.Right - W; + + if X + W > MonitorRect.Right then X := MonitorRect.Right - W; + if X < MonitorRect.Left then X := MonitorRect.Left; + end; + if CurrentTheme.OfficeXPPopupAlignment then with PopupPositionRec do + begin + GetOfficeXPPopupPosition1(PopupPositionRec); + inherited GetPopupPosition(ParentView, PopupWindow, PopupPositionRec); + GetOfficeXPPopupPosition2(PopupPositionRec); + VT := GetWinViewType(PopupWindow); + PopupPositionRec.PlaySound := not (VT and PVT_LISTBOX = PVT_LISTBOX); + end + else inherited; +end; + +function TTBXRootItem.GetPopupWindowClass: TTBPopupWindowClass; +begin + Result := TTBXPopupWindow; +end; + +procedure TTBXRootItem.OpenPopupEx(const SelectFirstItem, TrackRightButton: Boolean; + const ControlRect: TRect; const Alignment: TTBPopupAlignment); +var + ModalHandler: TTBModalHandler; + Popup: TTBPopupWindow; + DoneActionData: TTBDoneActionData; + State: TTBViewState; +begin + ModalHandler := TTBModalHandler.Create(0); + try + Popup := CreatePopupEx(SelectFirstItem, ControlRect, Alignment); + try + State := Popup.View.State; + Include(State, vsIgnoreFirstMouseUp); + TTBViewAccess(Popup.View).SetState(State); + ModalHandler.Loop(Popup.View, False, False, False, TrackRightButton); + DoneActionData := TTBViewAccess(Popup.View).DoneActionData; + finally + { Remove vsModal state from the root view before any TTBView.Destroy + methods get called, so that NotifyFocusEvent becomes a no-op } + State := Popup.View.State; + Exclude(State, vsModal); + TTBViewAccess(Popup.View).SetState(State); + Popup.Free; + end; + finally + ModalHandler.Free; + end; + ProcessDoneAction(DoneActionData); +end; + +procedure TTBXRootItem.PopupEx(const ControlRect: TRect; + TrackRightButton: Boolean; Alignment: TTBPopupAlignment); +begin + OpenPopupEx(False, TrackRightButton, ControlRect, Alignment); +end; + + +//============================================================================// + +{ TTBXPopupMenu } + +function TTBXPopupMenu.GetRootItemClass: TTBRootItemClass; +begin + Result := TTBXRootItem; +end; + +procedure TTBXPopupMenu.PopupEx(const ControlRect: TRect); +begin + {$IFDEF JR_D5} + PPoint(@PopupPoint)^ := Point(ControlRect.Left, ControlRect.Bottom); + {$ENDIF} + TTBXRootItem(Items).PopupEx(ControlRect, TrackButton = tbRightButton, TTBPopupAlignment(Alignment)) +end; + +procedure TTBXPopupMenu.TBMGetViewType(var Message: TMessage); +begin + Message.Result := PVT_POPUPMENU; +end; + + +//============================================================================// + +{ TTBXFloatingWindowParent } + +procedure TTBXFloatingWindowParent.CancelNCHover; +begin + if FCloseButtonHover then + begin + FCloseButtonHover := False; + if HandleAllocated and IsWindowVisible(Handle) then + DrawNCArea(False, 0, 0, [twrdCloseButton]); + end; +end; + +procedure TTBXFloatingWindowParent.CMMouseLeave(var Message: TMessage); +begin + inherited; + CancelNCHover; +end; + +procedure TTBXFloatingWindowParent.DrawNCArea(const DrawToDC: Boolean; + const ADC: HDC; const Clip: HRGN; RedrawWhat: TTBToolWindowNCRedrawWhat); +const + CDown: array [Boolean] of Integer = (0, CDBS_PRESSED); + CHover: array [Boolean] of Integer = (0, CDBS_HOT); + CBord: array [Boolean] of Integer = (0, WRP_BORDER); + CCapt: array [Boolean] of Integer = (0, WRP_CAPTION); + CBtn: array [Boolean] of Integer = (0, WRP_CLOSEBTN); +var + DC: HDC; + R: TRect; + Canvas: TCanvas; + WindowInfo: TTBXWindowInfo; + DockWindow: TTBCustomDockableWindowAccess; +begin + if not HandleAllocated then Exit; + if not DrawToDC then DC := GetWindowDC(Handle) + else DC := ADC; + try + if not DrawToDC then SelectNCUpdateRgn(Handle, DC, Clip); + GetWindowRect(Handle, R); + OffsetRect(R, -R.Left, -R.Top); + with R do IntersectClipRect(DC, Left, Top, Right, Bottom); + Canvas := TCanvas.Create; + try + Canvas.Handle := DC; + GetWindowRect(Handle, R); + OffsetRect(R, -R.Left, -R.Top); + DockWindow := TTBCustomDockableWindowAccess(DockableWindow); + + FillChar(WindowInfo, SizeOf(WindowInfo), 0); + WindowInfo.ParentHandle := Handle; + WindowInfo.WindowHandle := DockWindow.Handle; + WindowInfo.ViewType := GetWinViewType(DockWindow); + WindowInfo.ClientWidth := ClientWidth; + WindowInfo.ClientHeight := ClientHeight; + WindowInfo.ShowCaption := DockWindow.ShowCaption; + WindowInfo.FloatingBorderSize := DockWindow.GetFloatingBorderSize; + if DockWindow.CloseButton and DockWindow.ShowCaption then + begin + WindowInfo.CloseButtonState := CDBS_VISIBLE; + if CloseButtonDown then WindowInfo.CloseButtonState := WindowInfo.CloseButtonState or CDBS_PRESSED + else if CloseButtonHover then WindowInfo.CloseButtonState := WindowInfo.CloseButtonState or CDBS_HOT; + end; + WindowInfo.RedrawPart := + CBord[twrdBorder in RedrawWhat] or + CCapt[twrdCaption in RedrawWhat] or + CBtn[twrdCloseButton in RedrawWhat]; + WindowInfo.Caption := PChar(Caption); + WindowInfo.EffectiveColor := GetEffectiveColor(DockWindow); + WindowInfo.Active := not DockWindow.InactiveCaption; + Canvas.Brush.Color := WindowInfo.EffectiveColor; + CurrentTheme.PaintFloatingBorder(Canvas, R, WindowInfo); + finally + Canvas.Handle := 0; + Canvas.Free; + end; + finally + if not DrawToDC then ReleaseDC(Handle, DC); + end; +end; + +procedure TTBXFloatingWindowParent.WMEraseBkgnd(var Message: TMessage); +begin + Message.Result := 1; +end; + +procedure TTBXFloatingWindowParent.WMNCMouseLeave(var Message: TMessage); +begin + if not MouseCapture then CancelNCHover; + inherited; +end; + +procedure TTBXFloatingWindowParent.WMNCMouseMove(var Message: TWMNCMouseMove); +var + InArea: Boolean; +begin + inherited; + { Note: TME_NONCLIENT was introduced in Windows 98 and 2000 } + if (Win32MajorVersion >= 5) or + (Win32MajorVersion = 4) and (Win32MinorVersion >= 10) then + CallTrackMouseEvent (Handle, TME_LEAVE or $10 {TME_NONCLIENT}); + InArea := Message.HitTest = 2001; {HT_TB2k_Close} + if FCloseButtonHover <> InArea then + begin + FCloseButtonHover := InArea; + if HandleAllocated and IsWindowVisible(Handle) then + DrawNCArea(False, 0, 0, [twrdCloseButton]); + end; +end; + +procedure TTBXFloatingWindowParent.WMWindowPosChanging(var Message: TWMWindowPosChanging); +var + R: TRect; + MonInfo: TMonitorInfo; +begin + if SnapDistance > 0 then with Message.WindowPos^ do + begin + if (cx = Width) and (cy = Height) then + begin + MonInfo.cbSize := SizeOf(MonInfo); + GetMonitorInfo(Monitor.Handle, @MonInfo); + R := MonInfo.rcWork; + if Abs(x + Width - R.Right) < SnapDistance then x := R.Right - Width; + if Abs(y + Height - R.Bottom) < SnapDistance then y := R.Bottom - Height; + if Abs(x - R.Left) < SnapDistance then x := R.Left; + if Abs(y - R.Top) < SnapDistance then y := R.Top; + end; + end; + inherited; +end; + + +//============================================================================// + +{ TTBXToolWindow } + +procedure TTBXToolWindow.CMColorChanged(var Message: TMessage); +begin + UpdateEffectiveColor; + if Docked and HandleAllocated then + RedrawWindow(Handle, nil, 0, RDW_FRAME or RDW_INVALIDATE or + RDW_ERASE or RDW_UPDATENOW or RDW_ALLCHILDREN); + UpdateChildColors; + Invalidate; +end; + +procedure TTBXToolWindow.CMControlChange(var Message: TCMControlChange); +begin + inherited; + if Message.Inserting and (Color = clNone) then + Message.Control.Perform(CM_PARENTCOLORCHANGED, 1, EffectiveColor); +end; + +procedure TTBXToolWindow.CMTextChanged(var Message: TMessage); +begin + inherited; + if HandleAllocated then + begin + if Docked then RedrawWindow(Handle, nil, 0, RDW_FRAME or RDW_INVALIDATE) + else RedrawWindow(TTBXFloatingWindowParent(Parent).Handle, nil, 0, RDW_FRAME or RDW_INVALIDATE); + end; +end; + +constructor TTBXToolWindow.Create(AOwner: TComponent); +begin + inherited; + AddThemeNotification(Self); + DblClickUndock := False; + FEffectiveColor := Color; + Color := clNone; +end; + +destructor TTBXToolWindow.Destroy; +begin + RemoveThemeNotification(Self); + inherited; +end; + +procedure TTBXToolWindow.DrawNCArea(const DrawToDC: Boolean; + const ADC: HDC; const Clip: HRGN); +var + DC: HDC; + R, CR, R2: TRect; + ACanvas: TCanvas; + ToolbarInfo: TTBXToolbarInfo; + UsingBackground: Boolean; +begin + if not Docked or not HandleAllocated then Exit; + + if not DrawToDC then DC := GetWindowDC(Handle) + else DC := ADC; + + UsingBackground := TDockAccess(CurrentDock).UsingBackground; + + try + GetToolbarInfo(ToolbarInfo); + GetWindowRect(Handle, R); + OffsetRect(R, -R.Left, -R.Top); + if not DrawToDC then + begin + SelectNCUpdateRgn(Handle, DC, Clip); + CR := R; + with ToolbarInfo.BorderSize, CR do + begin + InflateRect(CR, -X, -Y); + if ToolbarInfo.IsVertical then Inc(Top, GetTBXDragHandleSize(ToolbarInfo)) + else Inc(Left, GetTBXDragHandleSize(ToolbarInfo)); + ExcludeClipRect(DC, Left, Top, Right, Bottom); + end; + end; + ACanvas := TCanvas.Create; + try + ACanvas.Handle := DC; + ACanvas.Brush.Color := EffectiveColor; + if CurrentTheme.SolidToolbarNCArea then + begin + ACanvas.Brush.Color := EffectiveColor; + ACanvas.Brush.Style := bsSolid; + end + else if UsingBackground then + begin + ACanvas.Brush.Color := EffectiveColor; + R2 := CurrentDock.ClientRect; + OffsetRect(R2, -Left, -Top); + TDockAccess(CurrentDock).DrawBackground(DC, R2); + if (Color = clNone) and CurrentDock.BackgroundOnToolbars then + ACanvas.Brush.Style := bsClear; + end + else + begin + ACanvas.Brush.Color := GetEffectiveColor(CurrentDock); + ACanvas.FillRect(R); + ACanvas.Brush.Color := EffectiveColor; + ACanvas.Brush.Style := bsSolid; + end; + + CurrentTheme.PaintToolbarNCArea(ACanvas, R, ToolbarInfo); + finally + ACanvas.Handle := 0; + ACanvas.Free; + end; + finally + if not DrawToDC then ReleaseDC(Handle, DC); + end; +end; + +function TTBXToolWindow.GetFloatingBorderSize: TPoint; +begin + CurrentTheme.GetViewBorder(GetWinViewType(Self) or TVT_FLOATING, Result); +end; + +function TTBXToolWindow.GetFloatingWindowParentClass: TTBFloatingWindowParentClass; +begin + Result := TTBXFloatingWindowParent; +end; + +procedure TTBXToolWindow.GetToolbarInfo(out ToolbarInfo: TTBXToolbarInfo); +begin + FillChar(ToolbarInfo, SizeOf(ToolbarInfo), 0); + ToolbarInfo.WindowHandle := WindowHandle; + ToolbarInfo.ViewType := GetWinViewType(Self); + if CurrentDock <> nil then + ToolbarInfo.IsVertical := CurrentDock.Position in [dpLeft,dpRight]; + ToolbarInfo.AllowDrag := CurrentDock.AllowDrag; + ToolbarInfo.DragHandleStyle := Ord(DragHandleStyle); + ToolbarInfo.ClientWidth := ClientWidth; + ToolbarInfo.ClientHeight := ClientHeight; + if ToolbarInfo.AllowDrag and CloseButtonWhenDocked then + begin + ToolbarInfo.CloseButtonState := CDBS_VISIBLE; + if CloseButtonDown then ToolbarInfo.CloseButtonState := ToolbarInfo.CloseButtonState or CDBS_PRESSED; + if CloseButtonHover then ToolbarInfo.CloseButtonState := ToolbarInfo.CloseButtonState or CDBS_HOT; + end; + ToolbarInfo.BorderStyle := BorderStyle; + ToolbarInfo.EffectiveColor := EffectiveColor; + CurrentTheme.GetViewBorder(ToolbarInfo.ViewType, ToolbarInfo.BorderSize); +end; + +procedure TTBXToolWindow.SetParent(AParent: TWinControl); +begin + inherited; + if AParent is TTBXFloatingWindowParent then + TTBXFloatingWindowParent(AParent).SnapDistance := SnapDistance; +end; + +procedure TTBXToolWindow.SetSnapDistance(Value: Integer); +begin + if Value < 0 then Value := 0; + FSnapDistance := Value; + if (Parent <> nil) and (Parent is TTBXFloatingWindowParent) then + TTBXFloatingWindowParent(Parent).SnapDistance := Value; +end; + +procedure TTBXToolWindow.TBMGetEffectiveColor(var Message: TMessage); +begin + Message.WParam := EffectiveColor; + Message.Result := 1; +end; + +procedure TTBXToolWindow.TBMGetViewType(var Message: TMessage); +begin + Message.Result := TVT_TOOLWINDOW; + if Floating then Message.Result := Message.Result or TVT_FLOATING; + if Resizable then Message.Result := Message.Result or TVT_RESIZABLE; +end; + +procedure TTBXToolWindow.TBMThemeChange(var Message: TMessage); +begin + case Message.WParam of + TSC_BEFOREVIEWCHANGE: BeginUpdate; + TSC_AFTERVIEWCHANGE: + begin + EndUpdate; + UpdateEffectiveColor; + if HandleAllocated and not (csDestroying in ComponentState) then + if Parent is TTBXFloatingWindowParent then + UpdateNCArea(TTBXFloatingWindowParent(Parent), GetWinViewType(Self)) + else + UpdateNCArea(Self, GetWinViewType(Self)); + UpdateChildColors; + Invalidate; + end; + end; +end; + +procedure TTBXToolWindow.UpdateChildColors; +var + M: TMessage; +begin + M.Msg := CM_PARENTCOLORCHANGED; + M.WParam := 1; + M.LParam := EffectiveColor; + M.Result := 0; + Broadcast(M); +end; + +procedure TTBXToolWindow.UpdateEffectiveColor; +begin + if Color = clNone then FEffectiveColor := CurrentTheme.GetViewColor(GetWinViewType(Self)) + else FEffectiveColor := Color; +end; + +procedure TTBXToolWindow.WMEraseBkgnd(var Message: TWmEraseBkgnd); +var + Canvas: TCanvas; + R, CR: TRect; + Transparent: Boolean; +begin + Transparent := False; + CR := ClientRect; + if Color = clNone then + if Docked and (TDockAccess(CurrentDock).UsingBackground) and CurrentDock.BackgroundOnToolbars + and not CurrentTheme.SolidToolbarClientArea then + begin + R := CurrentDock.ClientRect; + R.TopLeft := ScreenToClient(CurrentDock.ClientToScreen(R.TopLeft)); + R.BottomRight := ScreenToClient(CurrentDock.ClientToScreen(R.BottomRight)); + SaveDC(Message.DC); + with CR do IntersectClipRect(Message.DC, Left, Top, Right, Bottom); + TDockAccess(CurrentDock).DrawBackground(Message.DC, R); + RestoreDC(Message.DC, -1); + Message.Result := 1; + Transparent := True; + end; + + Canvas := TCanvas.Create; + Canvas.Handle := Message.DC; + try + if Docked then + begin + R := CurrentDock.ClientRect; + R.TopLeft := ScreenToClient(CurrentDock.ClientToScreen(R.TopLeft)); + R.BottomRight := ScreenToClient(CurrentDock.ClientToScreen(R.BottomRight)); + end + else R := Rect(0, 0, 0, 0); + CurrentTheme.PaintBackgnd(Canvas, R, CR, CR, EffectiveColor, Transparent, GetWinViewType(Self)); + Message.Result := 1; + finally + Canvas.Handle := 0; + Canvas.Free; + end; +end; + +//============================================================================// + +{ Additional system colors } + +type + TColorEntry = packed record + ColorPtr: ^TColor; + Name: string; + end; + +var + ColorRegistry: array of TColorEntry; + +procedure AddTBXColor(var AColor: TColor; const AName: string); +var + L: Integer; +begin + L := Length(ColorRegistry); + SetLength(ColorRegistry, L + 1); + with ColorRegistry[L] do + begin + ColorPtr := @AColor; + Name := AName; + end; +end; + +function TBXColorToString(Color: TColor): string; +var + I: Integer; +begin + if not ColorToIdent(Color, Result) then + begin + for I := 0 to Length(ColorRegistry) - 1 do + if ColorRegistry[I].ColorPtr^ = Color then + begin + Result := ColorRegistry[I].Name; + Exit; + end; + FmtStr(Result, '%s%.8x', [HexDisplayPrefix, Color]); + end; +end; + +function TBXIdentToColor(const Ident: string; var Color: Longint): Boolean; +var + I: Integer; +begin + for I := 0 to Length(ColorRegistry) - 1 do + if CompareText(ColorRegistry[I].Name, Ident) = 0 then + begin + Color := ColorRegistry[I].ColorPtr^; + Result := True; + Exit; + end; + Result := IdentToColor(Ident, Color); +end; + +function TBXStringToColor(S: string): TColor; +begin + if not TBXIdentToColor(S, Longint(Result)) then Result := StringToColor(S); +end; + +procedure TBXGetColorValues(Proc: TGetStrProc); +var + I: Integer; +begin + GetColorValues(Proc); + for I := 0 to Length(ColorRegistry) - 1 do Proc(ColorRegistry[I].Name); +end; + +procedure TBXSetTheme(const AThemeName: string); +begin + TBXNexus.SetTheme(AThemeName); +end; + +function TBXCurrentTheme: string; +begin + Result := TBXNexus.GetTheme; +end; + + +//============================================================================// + + +{ TTBXNexus } + +procedure TTBXNexus.AddNotifie(AObject: TObject); +begin + if FNotifies.IndexOf(AObject) < 0 then FNotifies.Add(AObject); + Exit; asm db 0,'TBX (C) 2001-2003 Alex Denisov',0 end; +end; + +procedure TTBXNexus.Broadcast(Msg: Cardinal; WParam, LParam: Integer); +var + M: TMessage; + I: Integer; +begin + if FNotifies.Count > 0 then + begin + M.Msg := Msg; + M.WParam := WParam; + M.LParam := LParam; + M.Result := 0; + for I := 0 to FNotifies.Count - 1 do TObject(FNotifies[I]).Dispatch(M); + end; +end; + +constructor TTBXNexus.Create(const DefaultTheme: string); +begin + FNotifies := TList.Create; + CurrentTheme := GetTBXTheme(DefaultTheme); + AddTBXSysChangeNotification(Self); +end; + +destructor TTBXNexus.Destroy; +begin + RemoveTBXSysChangeNotification(Self); + ReleaseTBXTheme(CurrentTheme); + FNotifies.Free; + inherited; +end; + +function TTBXNexus.GetTheme: string; +begin + Result := CurrentTheme.Name; +end; + +procedure TTBXNexus.RemoveNotifie(AObject: TObject); +begin + FNotifies.Remove(AObject); +end; + +procedure TTBXNexus.SetTheme(const AThemeName: string); +begin + if IsTBXThemeAvailable(AThemeName) then + begin + ReleaseTBXTheme(CurrentTheme); + CurrentTheme := GetTBXTheme(AThemeName); + Broadcast(TBM_THEMECHANGE, TSC_BEFOREVIEWCHANGE, 1); + Broadcast(TBM_THEMECHANGE, TSC_VIEWCHANGE, 1); + Broadcast(TBM_THEMECHANGE, TSC_AFTERVIEWCHANGE, 1); + end; +end; + +procedure TTBXNexus.TBXSysCommand(var Message: TMessage); +begin + { Retranslate TBX_SYSCOMMAND to TBM_THEMECHANGE } + if Message.Msg = TBX_SYSCOMMAND then + Broadcast(TBM_THEMECHANGE, Message.WParam, 0); +end; + +procedure InitAdditionalSysColors; +begin + AddTBXColor(clHotLight, 'clHotLight'); +{$IFNDEF JR_D6} + AddTBXColor(clMoneyGreen, 'clMoneyGreen'); + AddTBXColor(clSkyBlue, 'clSkyBlue'); + AddTBXColor(clCream, 'clCream'); + AddTBXColor(clMedGray, 'clMedGray'); +{$ENDIF} +end; + +{ TTBXDock } + +procedure TTBXDock.CMColorChanged(var Message: TMessage); +var + I: Integer; +begin + inherited; + for I := 0 to Self.ControlCount - 1 do + if Controls[I] is TWinControl then + InvalidateAll(TWinControl(Controls[I])); +end; + +constructor TTBXDock.Create(AOwner: TComponent); +begin + inherited; + Color := clNone; + AddThemeNotification(Self); +end; + +destructor TTBXDock.Destroy; +begin + RemoveThemeNotification(Self); + inherited; +end; + +procedure TTBXDock.DrawBackground(DC: HDC; const DrawRect: TRect); +const + DOCK_POSITIONS: array [TTBDockPosition] of Integer = (DP_TOP, DP_BOTTOM, DP_LEFT, DP_RIGHT); +var + Canvas: TCanvas; +begin + if UseParentBackground then DrawParentBackground(Self, DC, ClientRect) + else if ThemedBackground then + begin + Canvas := TCanvas.Create; + Canvas.Handle := DC; + CurrentTheme.PaintDock(Canvas, ClientRect, DrawRect, DOCK_POSITIONS[Position]); + Canvas.Handle := 0; + Canvas.Free; + end + else inherited; +end; + +procedure TTBXDock.Resize; +var + I, J: Integer; + V: TTBItemViewer; + R: TRect; +begin + inherited Resize; + if UsingBackground then + begin + for J := 0 to ToolbarCount - 1 do + begin + Invalidate; + if Toolbars[J] is TTBXToolbar then with TTBXToolbar(Toolbars[J]) do + begin + for I := 0 to View.ViewerCount - 1 do + begin + V := View.Viewers[I]; + if V.Show and not IsRectEmpty(V.BoundsRect) and not (V.Item is TTBControlItem) + then View.Invalidate(V); + end; + Update; + if HandleAllocated then + RedrawWindow(Handle, nil, 0, RDW_FRAME or RDW_INVALIDATE or RDW_ERASE); + for I := 0 to View.ViewerCount - 1 do + begin + V := View.Viewers[I]; + if V.Show and not IsRectEmpty(V.BoundsRect) and not (V.Item is TTBControlItem) + then + begin + R := V.BoundsRect; + ValidateRect(Handle, @R); + end; + end; + end + else if Toolbars[J] is TTBXToolWindow then with TTBXToolWindow(Toolbars[J]) do + begin + if HandleAllocated then + RedrawWindow(Handle, nil, 0, RDW_FRAME or RDW_INVALIDATE or RDW_ERASE); + end; + end; + end; +end; + +procedure TTBXDock.SetUseParentBackground(Value: Boolean); +begin + if Value <> FUseParentBackground then + begin + FUseParentBackground := Value; + if HandleAllocated then + RedrawWindow(Handle, nil, 0, RDW_FRAME or RDW_INVALIDATE or + RDW_ERASE or RDW_ALLCHILDREN); + end; +end; + +procedure TTBXDock.TBMGetEffectiveColor(var Message: TMessage); +begin + if Color <> clNone then Message.WParam := Color + else if Parent <> nil then Message.WParam := GetEffectiveColor(Parent) + else Message.WParam := clBtnFace; + Message.Result := 1; +end; + +procedure TTBXDock.TBMThemeChange(var Message: TMessage); +begin + case Message.WParam of + TSC_AFTERVIEWCHANGE: + begin + Invalidate; + end; + end; +end; + +function TTBXDock.ThemedBackground: Boolean; +begin + Result := (Background = nil) and (Color = clNone) and CurrentTheme.PaintDockBackground; +end; + +function TTBXDock.UsingBackground: Boolean; +begin + Result := UseParentBackground or (ThemedBackground and not FMoving) or + inherited UsingBackground; +end; + +procedure TTBXDock.WMEraseBkgnd(var Message: TWMEraseBkgnd); +var + R: TRect; + C: TColor; +begin + R := Self.ClientRect; + if UsingBackground then + begin + DrawBackground(Message.DC, R); + Message.Result := 1; + end + else + begin + C := Color; + if C = clNone then C := GetEffectiveColor(Parent); + FillRectEx(Message.DC, R, C); + Message.Result := 1; + end; +end; + +procedure TTBXDock.WMMove(var Message: TWMMove); +begin + FMoving := True; + inherited; + FMoving := False; +end; + +procedure TTBXDock.WMSize(var Message: TWMSize); +begin + FResizing := True; + inherited; + FResizing := False; +end; + +initialization + CurrentTheme := nil; + RegisterTBXTheme('Default', TTBXDefaultTheme); + TBXNexus := TTBXNexus.Create('Default'); + InitAdditionalSysColors; + +finalization + TBXNexus.Free; + ColorRegistry := nil; + +end. diff --git a/official/2.1.6+2.1.beta1/TBX/TBXDefaultTheme.pas b/official/2.1.6+2.1.beta1/TBX/TBXDefaultTheme.pas new file mode 100644 index 0000000..9defed9 --- /dev/null +++ b/official/2.1.6+2.1.beta1/TBX/TBXDefaultTheme.pas @@ -0,0 +1,1788 @@ +unit TBXDefaultTheme; + +// TBX Package +// Copyright 2001-2004 Alex A. Denisov. All Rights Reserved +// See TBX.chm for license and installation instructions +// +// $Id: TBXDefaultTheme.pas 16 2004-05-26 02:02:55Z Alex@ZEISS $ + +interface + +{$I ..\..\Source\TB2Ver.inc} +{$I TBX.inc} + +uses + Windows, Messages, Graphics, TBXThemes, ImgList; + +type + TTBXDefaultTheme = class(TTBXTheme) + private + procedure TBXSysCommand(var Message: TMessage); message TBX_SYSCOMMAND; + protected + ToolbarColor: TColor; + ToolbarText: TColor; + DockPanelColor: TColor; + StatusBarColor: TColor; + procedure SetupColorCache; virtual; + public + constructor Create(const AName: string); override; + destructor Destroy; override; + + { Metrics Access, etc. } + function GetBooleanMetrics(Index: Integer): Boolean; override; + function GetImageOffset(Canvas: TCanvas; const ItemInfo: TTBXItemInfo; ImageList: TCustomImageList): TPoint; override; + function GetIntegerMetrics(Index: Integer): Integer; override; + procedure GetMargins(MarginID: Integer; out Margins: TTBXMargins); override; + + function GetItemColor(const ItemInfo: TTBXItemInfo): TColor; override; + function GetItemTextColor(const ItemInfo: TTBXItemInfo): TColor; override; + function GetItemImageBackground(const ItemInfo: TTBXItemInfo): TColor; override; + function GetPopupShadowType: Integer; override; + procedure GetViewBorder(ViewType: Integer; out Border: TPoint); override; + function GetViewColor(ViewType: Integer): TColor; override; + procedure GetViewMargins(ViewType: Integer; out Margins: TTBXMargins); override; + + { Painting routines } + procedure PaintBackgnd(Canvas: TCanvas; const ADockRect, ARect, AClipRect: TRect; AColor: TColor; Transparent: Boolean; AViewType: Integer); override; + procedure PaintButton(Canvas: TCanvas; const ARect: TRect; const ItemInfo: TTBXItemInfo); override; + procedure PaintCaption(Canvas: TCanvas; const ARect: TRect; const ItemInfo: TTBXItemInfo; const ACaption: string; AFormat: Cardinal; Rotated: Boolean); override; + procedure PaintCheckMark(Canvas: TCanvas; ARect: TRect; const ItemInfo: TTBXItemInfo); override; + procedure PaintChevron(Canvas: TCanvas; ARect: TRect; const ItemInfo: TTBXItemInfo); override; + procedure PaintDock(Canvas: TCanvas; const ClientRect, DockRect: TRect; DockPosition: Integer); override; + procedure PaintDockPanelNCArea(Canvas: TCanvas; R: TRect; const DockPanelInfo: TTBXDockPanelInfo); override; + procedure PaintDropDownArrow(Canvas: TCanvas; const ARect: TRect; const ItemInfo: TTBXItemInfo); override; + procedure PaintEditButton(Canvas: TCanvas; const ARect: TRect; var ItemInfo: TTBXItemInfo; ButtonInfo: TTBXEditBtnInfo); override; + procedure PaintEditFrame(Canvas: TCanvas; const ARect: TRect; var ItemInfo: TTBXItemInfo; const EditInfo: TTBXEditInfo); override; + procedure PaintFloatingBorder(Canvas: TCanvas; const ARect: TRect; const WindowInfo: TTBXWindowInfo); override; + procedure PaintFrame(Canvas: TCanvas; const ARect: TRect; const ItemInfo: TTBXItemInfo); override; + procedure PaintImage(Canvas: TCanvas; ARect: TRect; const ItemInfo: TTBXItemInfo; ImageList: TCustomImageList; ImageIndex: Integer); override; + procedure PaintMDIButton(Canvas: TCanvas; ARect: TRect; const ItemInfo: TTBXItemInfo; ButtonKind: Cardinal); override; + procedure PaintMenuItem(Canvas: TCanvas; const ARect: TRect; var ItemInfo: TTBXItemInfo); override; + procedure PaintMenuItemFrame(Canvas: TCanvas; const ARect: TRect; const ItemInfo: TTBXItemInfo); override; + procedure PaintPageScrollButton(Canvas: TCanvas; const ARect: TRect; ButtonType: Integer; Hot: Boolean); override; + procedure PaintPopupNCArea(Canvas: TCanvas; R: TRect; const PopupInfo: TTBXPopupInfo); override; + procedure PaintSeparator(Canvas: TCanvas; ARect: TRect; ItemInfo: TTBXItemInfo; Horizontal, LineSeparator: Boolean); override; + procedure PaintToolbarNCArea(Canvas: TCanvas; R: TRect; const ToolbarInfo: TTBXToolbarInfo); override; + procedure PaintFrameControl(Canvas: TCanvas; R: TRect; Kind, State: Integer; Params: Pointer); override; + procedure PaintStatusBar(Canvas: TCanvas; R: TRect; Part: Integer); override; + end; + +implementation + +uses + Classes, Controls, CommCtrl, TBXUtils, TBXUxThemes, TB2Common, TB2Item, TBX, Forms; + +var + SmCaptionFont: TFont; + +procedure InitializeStock; +var + NonClientMetrics: TNonClientMetrics; +begin + SmCaptionFont := TFont.Create; + NonClientMetrics.cbSize := SizeOf(NonClientMetrics); + if SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, @NonClientMetrics, 0) then + SmCaptionFont.Handle := CreateFontIndirect(NonClientMetrics.lfSmCaptionFont); +end; + +procedure FinalizeStock; +begin + SmCaptionFont.Free; + SmCaptionFont := nil; +end; + +procedure DrawButtonBitmap(Canvas: TCanvas; R: TRect); +const + Pattern: array [0..15] of Byte = ($C6, 0, $6C, 0, $38, 0, $38, 0, $6C, 0, $C6, 0, 0, 0, 0, 0); +begin + DrawGlyph(Canvas.Handle, R, 7, 6, Pattern[0], clBtnText); +end; + +{ TTBXDefaultTheme } + +constructor TTBXDefaultTheme.Create; +begin + inherited; + AddTBXSysChangeNotification(Self); + SetupColorCache; +end; + +destructor TTBXDefaultTheme.Destroy; +begin + RemoveTBXSysChangeNotification(Self); + inherited; +end; + +function TTBXDefaultTheme.GetBooleanMetrics(Index: Integer): Boolean; +begin + case Index of + TMB_OFFICEXPPOPUPALIGNMENT: Result := False; + TMB_EDITMENUFULLSELECT: Result := False; + TMB_EDITHEIGHTEVEN: Result := False; + TMB_PAINTDOCKBACKGROUND: Result := USE_THEMES; + TMB_SOLIDTOOLBARNCAREA: Result := False; + TMB_SOLIDTOOLBARCLIENTAREA: Result := False; + else + Result := False; + end; +end; + +function TTBXDefaultTheme.GetIntegerMetrics(Index: Integer): Integer; +const + DEFAULT = -1; +var + Sz: TSize; +begin + case Index of + TMI_SPLITBTN_ARROWWIDTH: + if USE_THEMES then + begin + if GetThemePartSize(TOOLBAR_THEME, StockCompatibleBitmap.Canvas.Handle, + TP_SPLITBUTTONDROPDOWN, TS_NORMAL, nil, TS_TRUE, Sz) = S_OK then + begin + Result := Sz.cx + 2; + end + else Result := 11; + end + else Result := 11; + + TMI_DROPDOWN_ARROWWIDTH: Result := 8; + TMI_DROPDOWN_ARROWMARGIN: Result := 3; + + TMI_MENU_IMGTEXTSPACE: Result := 1; + TMI_MENU_LCAPTIONMARGIN: Result := 2; + TMI_MENU_RCAPTIONMARGIN: Result := 2; + TMI_MENU_SEPARATORSIZE: Result := DEFAULT; + TMI_MENU_MDI_DW: Result := 2; + TMI_MENU_MDI_DH: Result := 4; + + TMI_TLBR_SEPARATORSIZE: Result := 6; + + TMI_EDIT_FRAMEWIDTH: Result := 2; + TMI_EDIT_TEXTMARGINHORZ: Result := 2; + TMI_EDIT_TEXTMARGINVERT: Result := 1; + TMI_EDIT_BTNWIDTH: Result := 13; + TMI_EDIT_MENURIGHTINDENT: Result := 0; + else + Result := DEFAULT; + end; +end; + +function TTBXDefaultTheme.GetViewColor(ViewType: Integer): TColor; +begin + Result := ToolbarColor; + if (ViewType and VT_TOOLBAR) = VT_TOOLBAR then Result := ToolbarColor + else if (ViewType and VT_POPUP) = VT_POPUP then + begin + if (ViewType and PVT_POPUPMENU) = PVT_POPUPMENU then Result := clPopup + else if (ViewType and PVT_LISTBOX) = PVT_LISTBOX then Result := clWindow + else if (ViewType and PVT_TOOLBOX) = PVT_TOOLBOX then Result := ToolbarColor + else if (ViewType and PVT_CHEVRONMENU) = PVT_CHEVRONMENU then Result := clPopup; + end + else if (ViewType and VT_DOCKPANEL) = VT_DOCKPANEL then Result := DockPanelColor + else if (ViewType and VT_STATUSBAR) = VT_STATUSBAR then Result := StatusBarColor + else Result := clBtnFace; +end; + +function TTBXDefaultTheme.GetItemColor(const ItemInfo: TTBXItemInfo): TColor; +var + IsMenuItem: Boolean; +begin + with ItemInfo do + begin + IsMenuItem := ((ViewType and PVT_POPUPMENU) = PVT_POPUPMENU) and ((ItemOptions and IO_TOOLBARSTYLE) = 0); + if not USE_THEMES then + begin + if IsMenuItem and (ItemInfo.HoverKind <> hkNone) then Result := clHighlight + else Result := GetViewColor(ItemInfo.ViewType); + end + else + Result := GetViewColor(ItemInfo.ViewType); + end; +end; + +function TTBXDefaultTheme.GetItemTextColor(const ItemInfo: TTBXItemInfo): TColor; +var + InMenuBar, ToolbarStyle, ShowInactive: Boolean; +begin + Result := clBtnText; + with ItemInfo do + begin + InMenuBar := (ViewType and TVT_MENUBAR) = TVT_MENUBAR; + ToolbarStyle := Boolean(ItemOptions and IO_TOOLBARSTYLE); + ShowInactive := InMenubar and not Boolean(ItemOptions and IO_APPACTIVE); + + if not ToolbarStyle and not Enabled and (HoverKind = hkKeyboardHover) then Result := clGrayText + else if Enabled then + begin + if not ToolbarStyle or (InMenuBar and USE_FLATMENUS) then + begin + if HoverKind <> hkNone then Result := clHighlightText + else if ShowInactive then Result := clGrayText + else Result := clPopupText + end + else if ShowInactive then Result := clGrayText; + end + else Result := clGrayText; + end; +end; + +function TTBXDefaultTheme.GetItemImageBackground(const ItemInfo: TTBXItemInfo): TColor; +var + IsFlatMenuItem, InFlatMenuBar, InFlatChevronBar: Boolean; +begin + with ItemInfo do + begin + InFlatMenuBar := ((ViewType and TVT_MENUBAR) = TVT_MENUBAR) and USE_FLATMENUS; + InFlatChevronBar := ((ViewType and PVT_CHEVRONMENU) = PVT_CHEVRONMENU) and USE_FLATMENUS; + IsFlatMenuItem := ((ViewType and PVT_POPUPMENU) = PVT_POPUPMENU) and ((ItemOptions and IO_TOOLBARSTYLE) = 0) and USE_FLATMENUS; + + if InFlatMenuBar and (HoverKind <> hkNone) then Result := clHighlight + else if InFlatChevronBar or IsFlatMenuItem and (HoverKind <> hkNone) then Result := ToolbarColor + else Result := GetViewColor(ViewType); + end; +end; + +procedure TTBXDefaultTheme.GetViewBorder(ViewType: Integer; out Border: TPoint); +const + XMetrics: array [Boolean] of Integer = (SM_CXDLGFRAME, SM_CXFRAME); + YMetrics: array [Boolean] of Integer = (SM_CYDLGFRAME, SM_CYFRAME); +var + Resizable: Boolean; + Sz: Integer; +begin + Sz := 0; + if (ViewType and VT_TOOLBAR) = VT_TOOLBAR then + begin + if (ViewType and TVT_FLOATING) = TVT_FLOATING then + begin + Resizable := (ViewType and TVT_RESIZABLE) = TVT_RESIZABLE; + Border.X := GetSystemMetrics(XMetrics[Resizable]); + Border.Y := GetSystemMetrics(YMetrics[Resizable]); + Exit; + end + else Sz := 2; + end + else if (ViewType and VT_POPUP) = VT_POPUP then + begin +{$IFNDEF OFFICE2K_COMBOS} + if (ViewType and PVT_LISTBOX) = PVT_LISTBOX then Sz := 1 + else Sz := 3; +{$ELSE} + Sz := 3; +{$ENDIF} + end + else if (ViewType and VT_DOCKPANEL) = VT_DOCKPANEL then + begin + if (ViewType and DPVT_FLOATING) = DPVT_FLOATING then + begin + Resizable := (ViewType and DPVT_RESIZABLE) = DPVT_RESIZABLE; + Border.X := GetSystemMetrics(XMetrics[Resizable]); + Border.Y := GetSystemMetrics(YMetrics[Resizable]); + Exit; + end + else Sz := 2; + end; + Border.X := Sz; + Border.Y := Sz; +end; + +procedure TTBXDefaultTheme.GetMargins(MarginID: Integer; out Margins: TTBXMargins); +var + R, R2: TRect; +begin + with Margins do + case MarginID of + MID_TOOLBARITEM: + begin + LeftWidth := 2; RightWidth := 2; + TopHeight := 2; BottomHeight := 2; + if USE_THEMES then + GetThemeMargins(TOOLBAR_THEME, StockBitmap1.Canvas.Handle, TP_BUTTON, TS_HOT, TMT_CAPTIONMARGINS, + nil, TMargins(Margins)); + end; + + MID_MENUITEM: + begin + LeftWidth := 0; RightWidth := 0; + TopHeight := 2; BottomHeight := 2; + end; + + MID_STATUSPANE: + begin + if USE_THEMES then + begin + R := Rect(0, 0, 100, 100); + GetThemeBackgroundContentRect(STATUSBAR_THEME, StockBitmap1.Canvas.Handle, SP_PANE, 0, R, @R2); + LeftWidth := R2.Left - R.Left; + RightWidth := R.Right - R2.Right; + TopHeight := R2.Top - R.Top; + BottomHeight := R.Bottom - R2.Bottom; + end + else + begin + LeftWidth := 1; RightWidth := 3; + TopHeight := 1; BottomHeight := 1; + end; + end; + else + LeftWidth := 0; RightWidth := 0; + TopHeight := 0; BottomHeight := 0; + end; +end; + +procedure TTBXDefaultTheme.PaintBackgnd(Canvas: TCanvas; const ADockRect, ARect, AClipRect: TRect; + AColor: TColor; Transparent: Boolean; AViewType: Integer); +var + DC: HDC; + R: TRect; +begin + DC := Canvas.Handle; + if not Transparent then + begin + IntersectRect(R, ARect, AClipRect); + FillRectEx(DC, R, AColor); + end; +end; + +procedure TTBXDefaultTheme.PaintCaption(Canvas: TCanvas; + const ARect: TRect; const ItemInfo: TTBXItemInfo; const ACaption: string; + AFormat: Cardinal; Rotated: Boolean); +var + R: TRect; + C: TColor; + InMenuBar, ToolbarStyle: Boolean; + + procedure _Draw(Color: TColor); + begin + Canvas.Font.Color := Color; + if not Rotated then Windows.DrawText(Canvas.Handle, PChar(ACaption), Length(ACaption), R, AFormat) + else DrawRotatedText(Canvas.Handle, ACaption, R, AFormat); + end; + +begin + with ItemInfo, Canvas do + begin + R := ARect; + C := Font.Color; + { Apply theme-dependent color only when Font.Color = clNone } + if C = clNone then C := GetItemTextColor(ItemInfo); + Brush.Style := bsClear; + InMenuBar := (ViewType and TVT_MENUBAR) = TVT_MENUBAR; + ToolbarStyle := Boolean(ItemOptions and IO_TOOLBARSTYLE); + if not ToolbarStyle and not Enabled and (HoverKind = hkKeyboardHover) then _Draw(C) + else if Enabled then + begin + if ToolbarStyle and (Pushed or Selected) and not (InMenuBar and USE_FLATMENUS) then + OffsetRect(R, 1, 1); + _Draw(C); + end + else if USE_THEMES then _Draw(C) + else + begin + OffsetRect(R, 1, 1); + _Draw(clBtnHighlight); + OffsetRect(R, -1, -1); + _Draw(clBtnShadow); + end; + Brush.Style := bsSolid; + end; +end; + +procedure TTBXDefaultTheme.PaintCheckMark(Canvas: TCanvas; ARect: TRect; const ItemInfo: TTBXItemInfo); +var + DC: HDC; + X, Y: Integer; + C: TColor; +begin + DC := Canvas.Handle; + X := (ARect.Left + ARect.Right) div 2 - 1; + Y := (ARect.Top + ARect.Bottom) div 2 + 1; + if ItemInfo.Enabled + then C := clBtnText + else C := clGrayText; + if ItemInfo.ItemOptions and IO_RADIO > 0 then + begin + RoundRectEx(DC, X-2, Y-4, X+4, Y+2, 2, 2, + MixColors(C, clBtnHighlight, 128), clNone); + RoundRectEx(DC, X-2, Y-4, X+4, Y+2, 6, 6, C, C); + if ItemInfo.Enabled then + RoundRectEx(DC, X-3, Y-5, X+5, Y+3, 6, 6, clBtnHighlight, clNone); + end + else begin + PolyLineEx(DC, [Point(X-2, Y-2), Point(X, Y), Point(X+4, Y-4), + Point(X+4, Y-3), Point(X, Y+1), Point(X-2, Y-1), Point(X-2, Y-2)], C); + if ItemInfo.Enabled then + PolyLineEx(DC, [Point(X-3, Y-2), Point(X-3, Y-1), Point(X, Y+2), + Point(X+5, Y-3), Point(X+5, Y-5)], clBtnHighlight); + end; +end; + +procedure TTBXDefaultTheme.PaintChevron(Canvas: TCanvas; ARect: TRect; + const ItemInfo: TTBXItemInfo); +const + Pattern: array [Boolean, 0..15] of Byte = ( + ($CC, 0, $66, 0, $33, 0, $66, 0, $CC, 0, 0, 0, 0, 0, 0, 0), + ($88, 0, $D8, 0, $70, 0, $20, 0, $88, 0, $D8, 0, $70, 0, $20, 0)); +var + DC: HDC; + R2: TRect; + P: PByte; + W, H: Integer; +begin + DC := Canvas.Handle; + R2 := ARect; + PaintButton(Canvas, R2, ItemInfo); + + if not ItemInfo.IsVertical then + begin + Inc(R2.Top, 4); + R2.Bottom := R2.Top + 5; + W := 8; + H := 5; + end + else + begin + R2.Left := R2.Right - 9; + R2.Right := R2.Left + 5; + W := 5; + H := 8; + end; + if ItemInfo.Pushed then OffsetRect(R2, 1, 1); + + P := @Pattern[ItemInfo.IsVertical][0]; + if ItemInfo.Enabled then DrawGlyph(DC, R2, W, H, P^, clBtnText) + else + begin + OffsetRect(R2, 1, 1); + DrawGlyph(DC, R2, W, H, P^, clBtnHighlight); + OffsetRect(R2, -1, -1); + DrawGlyph(DC, R2, W, H, P^, clBtnShadow); + end; +end; + +procedure TTBXDefaultTheme.PaintEditButton(Canvas: TCanvas; const ARect: TRect; + var ItemInfo: TTBXItemInfo; ButtonInfo: TTBXEditBtnInfo); +var + DC: HDC; + BtnDisabled, BtnHot, BtnPressed, Embedded: Boolean; + StateFlags: Integer; + R, BR: TRect; + C: TColor; + X, Y: Integer; + + procedure DrawEnabled(var R: TRect); + begin + if BtnPressed then + Windows.DrawEdge(Canvas.Handle, R, BDR_SUNKENOUTER, BF_RECT or BF_ADJUST) + else if BtnHot then + Windows.DrawEdge(Canvas.Handle, R, BDR_RAISEDINNER, BF_RECT or BF_ADJUST) + else if not Embedded then + FrameRectEx(DC, R, clWindow, False); + end; + + procedure DrawUp; + begin + X := (R.Left + R.Right) div 2 + Ord(BtnPressed); + Y := (R.Top * 3 + R.Bottom + 3) div 4 + Ord(BtnPressed); + if not BtnDisabled then + begin + if Boolean(ItemInfo.ItemOptions and IO_TOOLBARSTYLE) then C := clPopupText + else C := clBtnText; + end + else with Canvas do + begin + Inc(X); Inc(Y); + Pen.Color := clBtnHighlight; Brush.Color := clBtnHighlight; + Polygon([Point(X - 2, Y), Point(X + 2, Y), Point(X, Y - 2)]); + Dec(X); Dec(Y); + C := clBtnShadow; + end; + Canvas.Pen.Color := C; Canvas.Brush.Color := C; + Canvas.Polygon([Point(X - 2, Y), Point(X + 2, Y), Point(X, Y - 2)]) + end; + + procedure DrawDn; + begin + X := (R.Left + R.Right) div 2 + Ord(BtnPressed); + Y := (R.Top + R.Bottom * 3 - 4) div 4 + Ord(BtnPressed); + if not BtnDisabled then + begin + if Boolean(ItemInfo.ItemOptions and IO_TOOLBARSTYLE) then C := clPopupText + else C := clBtnText; + end + else with Canvas do + begin + Inc(X); Inc(Y); + Pen.Color := clBtnHighlight; Brush.Color := clBtnHighlight; + Polygon([Point(X - 2, Y), Point(X + 2, Y), Point(X, Y + 2)]); + Dec(X); Dec(Y); + C := clBtnShadow; + end; + Canvas.Pen.Color := C; Canvas.Brush.Color := C; + Canvas.Polygon([Point(X - 2, Y), Point(X + 2, Y), Point(X, Y + 2)]) + end; + +begin + DC := Canvas.Handle; + R := ARect; + with Canvas, ItemInfo do + begin + Embedded := ((ViewType and VT_TOOLBAR) = VT_TOOLBAR) and + ((ViewType and TVT_EMBEDDED) = TVT_EMBEDDED); + + if ButtonInfo.ButtonType = EBT_DROPDOWN then + begin + { DropDown button } + BtnDisabled := (ButtonInfo.ButtonState and EBDS_DISABLED) <> 0; + BtnHot := (ButtonInfo.ButtonState and EBDS_HOT) <> 0; + BtnPressed := (ButtonInfo.ButtonState and EBDS_PRESSED) <> 0; + if USE_THEMES then + begin + if BtnDisabled then StateFlags := CBXS_DISABLED + else if BtnPressed then StateFlags := CBXS_PRESSED + else if BtnHot then StateFlags := CBXS_HOT + else StateFlags := CBXS_NORMAL; + if BtnHot then InflateRect(R, 1, 1); + DrawThemeBackground(COMBO_THEME, Handle, CP_DROPDOWNBUTTON, StateFlags, R, nil); + end + else + begin + Inc(R.Left, 2); + if not BtnDisabled then with R do + begin + if Embedded then FillRectEx(DC, R, clBtnFace); + if BtnPressed or BtnHot then + DrawLineEx(DC, Left - 1, Top, Left - 1, Bottom + 1, ToolbarColor) + else if Embedded then + DrawLineEx(DC, Left - 1, Top, Left - 1, Bottom, clBtnShadow) + else + DrawLineEx(DC, Left - 1, Top, Left - 1, Bottom, clWindow); + DrawEnabled(R); + end; + PaintDropDownArrow(Canvas, R, ItemInfo); + end; + end + else if ButtonInfo.ButtonType = EBT_SPIN then + begin + { Paint spin buttons } + BtnDisabled := (ButtonInfo.ButtonState and EBSS_DISABLED) <> 0; + BtnHot := (ButtonInfo.ButtonState and EBSS_HOT) <> 0; + if USE_THEMES then + begin + if BtnHot then InflateRect(R, 1, 1); + + { Upper with XP themes } + BR := R; + BR.Bottom := (R.Top + R.Bottom - 1) div 2; + BtnPressed := (ButtonInfo.ButtonState and EBSS_UP) <> 0; + if BtnDisabled then StateFlags := UPS_DISABLED + else if BtnPressed then StateFlags := UPS_PRESSED + else if BtnHot then StateFlags := UPS_HOT + else StateFlags := UPS_NORMAL; + DrawThemeBackground(SPIN_THEME, Handle, SPNP_UP, StateFlags, BR, nil); + + { Lower with XP themes } + BR := R; + BR.Top := (R.Top + R.Bottom) div 2; + BtnPressed := (ButtonInfo.ButtonState and EBSS_DOWN) <> 0; + if BtnDisabled then StateFlags := DNS_DISABLED + else if BtnPressed then StateFlags := DNS_PRESSED + else if BtnHot then StateFlags := DNS_HOT + else StateFlags := DNS_NORMAL; + DrawThemeBackground(SPIN_THEME, Handle, SPNP_DOWN, StateFlags, BR, nil); + end + else + begin + Inc(R.Left, 2); + + if not BtnDisabled then with R do + if BtnPressed or BtnHot then + DrawLineEx(DC, Left - 1, Top - 1, Left - 1, Bottom + 1, ToolbarColor) + else if Embedded then + DrawLineEx(DC, Left - 1, Top, Left - 1, Bottom, clBtnShadow) + else + DrawLineEx(DC, Left - 1, Top, Left - 1, Bottom, clWindow); + + + BR := R; + BR.Bottom := (R.Top + R.Bottom + 1) div 2; + BtnPressed := (ButtonInfo.ButtonState and EBSS_UP) <> 0; + if BtnHot or BtnPressed then Dec(BR.Bottom); + if not BtnDisabled then DrawEnabled(BR); + DrawUp; + + BR := R; + BR.Top := (R.Top + R.Bottom) div 2; + BtnPressed := (ButtonInfo.ButtonState and EBSS_DOWN) <> 0; + if BtnHot or BtnPressed then Inc(BR.Top); + if not BtnDisabled then DrawEnabled(BR); + DrawDn; + end; + end; + end; +end; + +procedure TTBXDefaultTheme.PaintEditFrame(Canvas: TCanvas; + const ARect: TRect; var ItemInfo: TTBXItemInfo; const EditInfo: TTBXEditInfo); +var + R: TRect; + W: Integer; +begin + R := ARect; + PaintFrame(Canvas, R, ItemInfo); + W := EditFrameWidth; + InflateRect(R, -W, -W); + with EditInfo do if RightBtnWidth > 0 then Dec(R.Right, RightBtnWidth - 2); + Canvas.Brush.Color := clWindow; + if ItemInfo.Enabled then Canvas.FillRect(R); + with EditInfo do if LeftBtnWidth > 0 then Inc(R.Left, LeftBtnWidth - 2); + if EditInfo.RightBtnWidth > 0 then + begin + R := ARect; + InflateRect(R, -W, -W); + R.Left := R.Right - EditInfo.RightBtnWidth; + PaintEditButton(Canvas, R, ItemInfo, EditInfo.RightBtnInfo); + end; +end; + +procedure TTBXDefaultTheme.PaintDropDownArrow(Canvas: TCanvas; + const ARect: TRect; const ItemInfo: TTBXItemInfo); +var + X, Y: Integer; + + procedure Draw(AColor: TColor); + begin + Canvas.Pen.Color := AColor; + Canvas.Brush.Color := AColor; + if ItemInfo.IsVertical then Canvas.Polygon([Point(X, Y + 2), Point(X, Y - 2), Point(X - 2, Y)]) + else Canvas.Polygon([Point(X - 2, Y), Point(X + 2, Y), Point(X, Y + 2)]); + end; + +begin + with ItemInfo, ARect do + begin + X := (Left + Right) div 2; + Y := (Top + Bottom) div 2 - 1; + + if (Pushed or Selected) and (ComboPart <> cpSplitRight) then + begin + Inc(X); Inc(Y); + end; + + if Enabled then + begin + if Boolean(ItemOptions and IO_TOOLBARSTYLE) then Draw(clPopupText) + else Draw(clBtnText); + end + else + begin + Inc(X); Inc(Y); + Draw(clBtnHighlight); + Dec(X); Dec(Y); + Draw(clBtnShadow); + end; + end; +end; + +procedure TTBXDefaultTheme.PaintButton(Canvas: TCanvas; const ARect: TRect; const ItemInfo: TTBXItemInfo); +const + XPPart: array [TTBXComboPart] of Integer = (TP_BUTTON, TP_DROPDOWNBUTTON, + TP_SPLITBUTTON, TP_SPLITBUTTONDROPDOWN); + Edge: array [Boolean] of Integer = (BDR_RAISEDINNER, EDGE_RAISED); +var + R: TRect; + Flags, RegionFlags: Cardinal; + InMenuBar, ShowHover, Embedded, ShowFlatSL: Boolean; + Region: HRGN; + DC: HDC; + Brush, OldBrush: HBrush; +begin + R := ARect; + DC := Canvas.Handle; + with ItemInfo do + begin + ShowHover := (Enabled and (HoverKind <> hkNone)) or + (not Enabled and (HoverKind = hkKeyboardHover)); + + InMenuBar := (ViewType and TVT_MENUBAR) = TVT_MENUBAR; + Embedded := ((ViewType and VT_TOOLBAR) = VT_TOOLBAR) and + ((ViewType and TVT_EMBEDDED) = TVT_EMBEDDED); + + if not InMenuBar and USE_THEMES then + begin + { The support for XP themes in menus is not yet implemented since standard + XP themes seem to have no theming for menus } + + if not Enabled then + begin + if HoverKind = hkKeyboardHover then Flags := TS_HOT + else Flags := TS_DISABLED; + end + else if ItemInfo.Pushed then Flags := TS_PRESSED + else if ItemInfo.Selected then + begin + if HoverKind <> hkNone then Flags := TS_HOTCHECKED + else Flags := TS_CHECKED; + end + else if HoverKind <> hkNone then Flags := TS_HOT + else Flags := TS_NORMAL; + + if Embedded or Boolean(ItemOptions and IO_DESIGNING) then + begin + { There is no state for non-transparent normal toolbar button, trying to + simulate it with regions... } + RegionFlags := TS_HOT; + if ComboPart = cpSplitRight then Dec(R.Left); + GetThemeBackgroundRegion(TOOLBAR_THEME, Canvas.Handle, XPPart[ComboPart], RegionFlags, R, Region); + if ComboPart = cpSplitRight then Inc(R.Left); + if Embedded or not Boolean(ItemOptions and IO_DESIGNING) then + begin + Brush := CreateBrushEx(ToolbarColor); + OldBrush := SelectObject(DC, Brush); + FillRgn(DC, Region, Brush); + SelectObject(DC, OldBrush); + DeleteObject(Brush); + end; + Brush := CreateBrushEx(clBtnShadow); + OldBrush := SelectObject(DC, Brush); + FrameRgn(DC, Region, Brush, 1, 1); + SelectObject(DC, OldBrush); + DeleteObject(Brush); + DeleteObject(Region); + end; + + DrawThemeBackground(TOOLBAR_THEME, DC, XPPart[ComboPart], Flags, R, nil); + end + else + begin + if InMenuBar and USE_FLATMENUS then + begin + if ((Pushed or Selected) and Enabled) or ShowHover then + FillRectEx(DC, R, clHighlight); + Exit; + end; +{$IFDEF NARROWCOMBOBUTTON} + if (ItemInfo.ComboPart = cpSplitRight) and not (InMenuBar or USE_THEMES) then Dec(R.Right, 2); +{$ENDIF} + if USE_FLATMENUS and (((Pushed or Selected) and Enabled) or ShowHover) then + FillRectEx(DC, R, ToolbarColor); + if Embedded then with Canvas do + begin + Flags := BF_RECT or BF_MIDDLE or BF_ADJUST; + if not ShowHover or (Pushed or Selected or not Enabled) then Flags := Flags or BF_FLAT; + ShowFlatSL := (ComboPart = cpSplitLeft) and not (ShowHover or Pushed); + if ShowFlatSL then Inc(R.Right); + Windows.DrawEdge(Handle, R, EDGE_RAISED, Flags); + if Selected and Enabled and (HoverKind = hkNone) then + DitherRect(DC, R, ToolbarColor, clBtnHighlight); + if ShowFlatSL then Dec(R.Right); + end + else if (Pushed or Selected) and Enabled then with Canvas do + begin + Windows.DrawEdge(Handle, R, BDR_SUNKENOUTER, BF_RECT or BF_ADJUST); + if not Pushed and (HoverKind = hkNone) then + DitherRect(DC, R, ToolbarColor, clBtnHighlight); + end + else if ShowHover or Boolean(ItemOptions and IO_DESIGNING) then + Windows.DrawEdge(Canvas.Handle, R, BDR_RAISEDINNER, BF_RECT); + if ComboPart = cpSplitRight then PaintDropDownArrow(Canvas, R, ItemInfo); + end; + end; +end; + +procedure TTBXDefaultTheme.PaintFloatingBorder(Canvas: TCanvas; const ARect: TRect; const WindowInfo: TTBXWindowInfo); +const + SPI_GETGRADIENTCAPTIONS = $1008; + DC_GRADIENT = $20; + ActiveCaptionFlags: array [Boolean] of Integer = (0, DC_ACTIVE); + GradientCaptionFlags: array [Boolean] of Integer = (0, DC_GRADIENT); + CaptionBkColors: array [Boolean, Boolean] of Integer = + ((COLOR_INACTIVECAPTION, COLOR_ACTIVECAPTION), + (COLOR_GRADIENTINACTIVECAPTION, COLOR_GRADIENTACTIVECAPTION)); + ButtonStateFlags: array [Boolean] of Integer = (0, DFCS_PUSHED); +var + R, R2: TRect; + DC: HDC; + Flags: Integer; + Gradient, ShowCloseBtn: Boolean; + B: BOOL; +begin + DC := Canvas.Handle; + + with WindowInfo do + if not USE_THEMES then + begin + R := ARect; + if (WRP_BORDER and RedrawPart) <> 0 then + begin + R2 := R; + with FloatingBorderSize do InflateRect(R2, -X, -Y); + SaveDC(DC); + with R2 do ExcludeClipRect(DC, Left, Top, Right, Bottom); + Windows.DrawEdge(DC, R, EDGE_RAISED, BF_RECT or BF_MIDDLE); + RestoreDC(DC, -1); + end; + + if not WindowInfo.ShowCaption then Exit; + Gradient := SystemParametersInfo(SPI_GETGRADIENTCAPTIONS, 0, @B, 0) and B; + ShowCloseBtn := (CDBS_VISIBLE and CloseButtonState) <> 0; + R := GetTBXCloseButtonRect(WindowInfo, True); + + if (WRP_CAPTION and RedrawPart) <> 0 then + begin + if ShowCloseBtn then + begin + SaveDC(DC); + with R do ExcludeClipRect(DC, Left, Top, Right, Bottom); + end; + R2 := GetTBXCaptionRect(WindowInfo, True, ShowCloseBtn); + DrawCaption(ParentHandle, DC, R2, DC_TEXT or DC_SMALLCAP or + ActiveCaptionFlags[Active] or GradientCaptionFlags[Gradient]); + if ShowCloseBtn then RestoreDC(DC, -1); + R2 := GetTBXCaptionRect(WindowInfo, True, False); + R2.Top := R2.Bottom; + Inc(R2.Bottom); + FillRect(DC, R2, GetSysColorBrush(COLOR_BTNFACE)); + end; + + if ShowCloseBtn then + begin + R2 := R; + InflateRect(R2, -2, -2); + if (WRP_CAPTION and RedrawPart) <> 0 then + begin + SaveDC(DC); + with R2 do ExcludeClipRect(DC, Left, Top, Right, Bottom); + FillRect(DC, R, GetSysColorBrush(CaptionBkColors[Gradient, WindowInfo.Active])); + RestoreDC(DC, -1); + end; + if (WRP_CLOSEBTN and RedrawPart) <> 0 then + DrawFrameControl(DC, R2, DFC_CAPTION, DFCS_CAPTIONCLOSE or + ButtonStateFlags[(CDBS_PRESSED and CloseButtonState) <> 0]); + end; + end + else { Use WindowsXP visual styles } + begin + if (WRP_BORDER and RedrawPart) <> 0 then + begin + if Active then Flags := FS_ACTIVE else Flags := FS_INACTIVE; + R := ARect; + R.Top := R.Bottom - FloatingBorderSize.Y; + DrawThemeBackground(WINDOW_THEME, DC, WP_SMALLFRAMEBOTTOM, Flags, R, nil); + R.Top := ARect.Top; + R.Bottom := R.Top + FloatingBorderSize.Y; + {if WindowInfo.ShowCaption then} { TODO : how to paint a captionless window frame } + Inc(R.Bottom, GetSystemMetrics(SM_CYSMCAPTION)); + DrawThemeBackground(WINDOW_THEME, DC, WP_SMALLCAPTION, Flags, R, nil); + R.Top := R.Bottom; + R.Bottom := ARect.Bottom - FloatingBorderSize.Y; + R.Right := R.Left + FloatingBorderSize.X; + DrawThemeBackground(WINDOW_THEME, DC, WP_SMALLFRAMELEFT, Flags, R, nil); + R.Right := ARect.Right; + R.Left := R.Right - FloatingBorderSize.X; + DrawThemeBackground(WINDOW_THEME, DC, WP_SMALLFRAMERIGHT, Flags, R, nil); + end; + + if not ShowCaption then Exit; + + { Get the caption area } + R := ARect; + with FloatingBorderSize do InflateRect(R, -X, -Y); + Dec(R.Bottom, ClientHeight); + + if (WRP_CAPTION and RedrawPart) <> 0 then + begin + R2 := R; + if ((CDBS_VISIBLE and CloseButtonState) <> 0) and ((WRP_CLOSEBTN and RedrawPart) <> 0) then + Dec(R2.Right, GetSystemMetrics(SM_CYSMCAPTION)); + + Canvas.Font.Assign(SmCaptionFont); + if Active then Canvas.Font.Color := clCaptionText + else Canvas.Font.Color := clInactiveCaptionText; + Canvas.Brush.Style := bsClear; + + { This is strange... the DrawThemeText function refuses to work... + Use standard API... } + DrawText(Canvas.Handle, WindowInfo.Caption, -1, R2, + DT_SINGLELINE or DT_VCENTER or DT_END_ELLIPSIS or DT_HIDEPREFIX); + + Canvas.Brush.Style := bsSolid; + end; + + if (CDBS_VISIBLE and CloseButtonState) <> 0 then + begin + Dec(R.Bottom); + R.Left := R.Right - R.Bottom + R.Top; + InflateRect(R, -2, -2); + if (CDBS_PRESSED and CloseButtonState) <> 0 then Flags := CBS_PUSHED + else if (CDBS_HOT and CloseButtonState) <> 0 then Flags := CBS_HOT + else Flags := CBS_NORMAL; + DrawThemeBackground(WINDOW_THEME, DC, WP_SMALLCLOSEBUTTON, Flags, R, nil); + end; + end; +end; + +procedure TTBXDefaultTheme.PaintFrame(Canvas: TCanvas; const ARect: TRect; const ItemInfo: TTBXItemInfo); +var + DC: HDC; + R: TRect; + E, Embedded: Boolean; + Flags, Border: Integer; + C: TColor; +begin + R := ARect; + DC := Canvas.Handle; + with ItemInfo do + begin + E := (Enabled and (HoverKind <> hkNone)) or + (not Enabled and (HoverKind = hkKeyboardHover)); + Embedded := ((ViewType and VT_TOOLBAR) = VT_TOOLBAR) and + ((ViewType and TVT_EMBEDDED) = TVT_EMBEDDED); + if USE_THEMES then + begin + InflateRect(R, -1, -1); + if Embedded then C := clBtnShadow + else C := ToolbarColor; + FrameRectEx(DC, R, C, False); + InflateRect(R, 1, 1); + if Pushed or Selected or E or ((ItemOptions and IO_DESIGNING) <> 0) + then DrawThemeBackground(COMBO_THEME, DC, 0, 0, R, nil); + InflateRect(R, -2, -2); + FrameRectEx(DC, R, clWindow, False); + end + else + begin + if Embedded then + begin + Flags := BF_RECT; + if not (Pushed or Selected or E) then + begin + InflateRect(R, -1, -1); + Flags := Flags or BF_FLAT; + Border := BDR_SUNKENOUTER; + end + else Border := EDGE_SUNKEN; + Windows.DrawEdge(DC, R, Border, Flags); + if (Pushed or Selected or E) then InflateRect(R, -1, -1); + end + else + begin + if Pushed or Selected or E or ((ItemOptions and IO_DESIGNING) <> 0) then + Windows.DrawEdge(DC, R, BDR_SUNKENOUTER, BF_RECT); + InflateRect(R, -1, -1); + FrameRectEx(DC, R, ToolbarColor, True); + FrameRectEx(DC, R, clWindow, False); + end; + end; + end; +end; + +function TTBXDefaultTheme.GetImageOffset(Canvas: TCanvas; const ItemInfo: TTBXItemInfo; + ImageList: TCustomImageList): TPoint; +const + Offsets: array [Boolean] of TPoint = ((X:0; Y:0), (X:1; Y:1)); +begin + with ItemInfo do + Result := Offsets[Pushed or Selected]; +end; + +procedure TTBXDefaultTheme.PaintImage(Canvas: TCanvas; ARect: TRect; + const ItemInfo: TTBXItemInfo; ImageList: TCustomImageList; ImageIndex: Integer); +var + BgColor: TColor; + HiContrast: Boolean; + IsMenuItem: Boolean; +begin + with ItemInfo do + begin + if ImageList is TTBCustomImageList then + begin + if Pushed or Selected then OffsetRect(ARect, 1, 1); + TTBCustomImageList(ImageList).DrawState(Canvas, ARect.Left, ARect.Top, + ImageIndex, Enabled, (HoverKind <> hkNone), Selected); + Exit; + end; + + IsMenuItem := ((ViewType and PVT_POPUPMENU) = PVT_POPUPMENU) and + ((ItemOptions and IO_TOOLBARSTYLE) = 0); + + if (IsMenuItem and USE_FLATMENUS) or (not IsMenuItem and USE_THEMES) then + begin + { The icon painting here is not really made by the uxtheme.dll, this is + just a simulation until I figure out how to work with DrawThemedIcon function } + if Pushed or Selected then OffsetRect(ARect, 1, 1); + BgColor := GetItemImageBackground(ItemInfo); + HiContrast := not IsMenuItem and IsDarkColor(BGColor); + if not Enabled then + DrawTBXIconShadow(Canvas, ARect, ImageList, ImageIndex, 0) + else if Selected or Pushed or (HoverKind <> hkNone) then + DrawTBXIcon(Canvas, ARect, ImageList, ImageIndex, HiContrast) + else if HiContrast or TBXHiContrast or TBXLoColor then + DrawTBXIcon(Canvas, ARect, ImageList, ImageIndex, HiContrast) + else + HighlightTBXIcon(Canvas, ARect, ImageList, ImageIndex, clWindow, 178); + end + else + begin + if Pushed or Selected then OffsetRect(ARect, 1, 1); + ImageList.Draw(Canvas, ARect.Left, ARect.Top, ImageIndex, Enabled); + end; + end; +end; + +procedure TTBXDefaultTheme.PaintMDIButton(Canvas: TCanvas; ARect: TRect; + const ItemInfo: TTBXItemInfo; ButtonKind: Cardinal); +const + PushedFlags: array[Boolean] of UINT = (0, DFCS_PUSHED); +var + XPPart, XPFlags: Cardinal; +begin + if USE_THEMES then + begin + case ButtonKind of + DFCS_CAPTIONMIN: XPPart := WP_MDIMINBUTTON; + DFCS_CAPTIONRESTORE: XPPart := WP_MDIRESTOREBUTTON; + DFCS_CAPTIONCLOSE: XPPart := WP_MDICLOSEBUTTON; + else + XPPart := 0; + end; + if ItemInfo.Pushed then XPFlags := CBS_PUSHED + else if ItemInfo.HoverKind <> hkNone then XPFlags := CBS_HOT + else XPFlags := CBS_NORMAL; + DrawThemeBackground(WINDOW_THEME, Canvas.Handle, XPPart, XPFLags, ARect, nil); + end + else + begin + DrawFrameControl(Canvas.Handle, ARect, DFC_CAPTION, + ButtonKind or PushedFlags[ItemInfo.Pushed]); + end; +end; + +procedure TTBXDefaultTheme.PaintMenuItemFrame(Canvas: TCanvas; + const ARect: TRect; const ItemInfo: TTBXItemInfo); +var + DC: HDC; +begin + DC := Canvas.Handle; + with ItemInfo do if (Enabled and (HoverKind <> hkNone)) or + (not Enabled and (HoverKind = hkKeyboardHover)) then + FillRectEx(DC, ARect, clHighlight); +end; + +procedure TTBXDefaultTheme.PaintMenuItem(Canvas: TCanvas; const ARect: TRect; var ItemInfo: TTBXItemInfo); +var + DC: HDC; + R: TRect; + ShowImageOrCheck: Boolean; + ShowHover: Boolean; + IsComboItem: Boolean; + X, Y: Integer; + ArrowWidth: Integer; + + procedure DrawArrow(AColor: TColor); + begin + PolygonEx(DC, [Point(X, Y - 3), Point(X, Y + 3), Point(X + 3, Y)], AColor, AColor); + end; + +begin + DC := Canvas.Handle; + with ItemInfo do + begin + ShowImageOrCheck := (ImageWidth > 0) or Selected; + ShowHover := (Enabled and (HoverKind <> hkNone)) or + (not Enabled and (HoverKind = hkKeyboardHover)); + ArrowWidth := GetSystemMetrics(SM_CXMENUCHECK); + + R := ARect; + if ShowImageOrCheck then Inc(R.Left, ItemInfo.PopupMargin + MenuImageTextSpace); + IsComboItem := ((ItemOptions and IO_COMBO) <> 0); + if IsComboItem and Enabled then Dec(R.Right, ArrowWidth); + + PaintMenuItemFrame(Canvas, R, ItemInfo); + + if IsComboItem then + begin + R.Left := ARect.Right - ArrowWidth; + R.Right := ARect.Right; + if Enabled and (HoverKind <> hkNone) then + Windows.DrawEdge(DC, R, BDR_SUNKENOUTER, BF_RECT) + else + begin + Dec(R.Left); + if not ShowHover then DrawEdge(DC, R, EDGE_ETCHED, BF_LEFT) + else DrawEdge(DC, R, BDR_SUNKENOUTER, BF_LEFT); + end; + end; + + if (ItemOptions and IO_SUBMENUITEM) <> 0 then + begin + Y := ARect.Bottom div 2; + X := ARect.Right - ArrowWidth * 2 div 3 - 2; + if not Enabled then + begin + if HoverKind = hkKeyboardHover then DrawArrow(clBtnShadow) + else + begin + Inc(X); Inc(Y); + DrawArrow(clBtnHighlight); + Dec(X); Dec(Y); + DrawArrow(clBtnShadow); + end; + end + else if (HoverKind <> hkNone) and not IsComboItem then DrawArrow(clHighlightText) + else DrawArrow(clPopupText); + end; + + if Enabled and ShowImageOrCheck and ((HoverKind <> hkNone) or Selected) then + begin + R.Left := ARect.Left; + R.Right := R.Left + ItemInfo.PopupMargin; + if USE_FLATMENUS then FillRectEx(DC, R, ToolbarColor); + PaintButton(Canvas, R, ItemInfo); + end; + end; +end; + +procedure TTBXDefaultTheme.PaintPopupNCArea(Canvas: TCanvas; R: TRect; const PopupInfo: TTBXPopupInfo); +var + DC: HDC; +begin + DC := Canvas.Handle; + +{$IFNDEF OFFICE2K_COMBOS} + if (PopupInfo.ViewType and PVT_LISTBOX) = PVT_LISTBOX then + begin + FrameRectEx(DC, R, clWindowFrame, True); + FrameRectEx(DC, R, clWindow, True); + FrameRectEx(DC, R, clWindow, False); + end + else +{$ENDIF} + if USE_FLATMENUS and ((PopupInfo.ViewType and PVT_TOOLBOX) <> PVT_TOOLBOX) then + begin + FrameRectEx(DC, R, clBtnShadow, True); + FrameRectEx(DC, R, clPopup, True); + FrameRectEx(DC, R, clPopup, False); + end + else if (PopupInfo.ViewType and PVT_TOOLBOX) = PVT_TOOLBOX then + begin + Windows.DrawEdge(DC, R, EDGE_RAISED, BF_RECT or BF_ADJUST); + FrameRectEx(DC, R, ToolbarColor, False); + end + else + begin + Windows.DrawEdge(DC, R, EDGE_RAISED, BF_RECT or BF_ADJUST); + FrameRectEx(DC, R, clPopup, False); + end; +end; + +procedure TTBXDefaultTheme.PaintSeparator(Canvas: TCanvas; ARect: TRect; + ItemInfo: TTBXItemInfo; Horizontal, LineSeparator: Boolean); +const + XPFlags: array [Boolean] of Integer = (TP_SEPARATOR, TP_SEPARATORVERT); +var + D: Integer; +begin + { Note: for blank separators, Enabled = False } + with ItemInfo, ARect do if Enabled then + begin + if not USE_THEMES or ((ViewType and PVT_POPUPMENU) = PVT_POPUPMENU) then + begin + D := 0; + if LineSeparator then + if (ViewType and TVT_FLOATING) <> 0 then D := 1 + else D := 4; + + if Horizontal then + begin + if (ItemOptions and IO_TOOLBARSTYLE) = 0 then D := 12; + Top := (Top + Bottom) div 2 - 1; + Inc(Left, D); Dec(Right, D); + Windows.DrawEdge(Canvas.Handle, ARect, EDGE_ETCHED, BF_TOP); + end + else + begin + Left := (Left + Right) div 2 - 1; + Inc(Top, D); Dec(Bottom, D); + Windows.DrawEdge(Canvas.Handle, ARect, EDGE_ETCHED, BF_LEFT); + end; + end + else + DrawThemeBackground(TOOLBAR_THEME, Canvas.Handle, XPFlags[Horizontal], TS_NORMAL, ARect, nil); + end; +end; + +procedure TTBXDefaultTheme.PaintToolbarNCArea(Canvas: TCanvas; R: TRect; const ToolbarInfo: TTBXToolbarInfo); +const + DragHandleSizes: array [Boolean, DHS_DOUBLE..DHS_SINGLE] of Integer = ((9, 0, 6), (14, 14, 14)); + DragHandleOffsets: array [Boolean, DHS_DOUBLE..DHS_SINGLE] of Integer = ((2, 0, 2), (3, 0, 5)); + GripperPart: array [Boolean] of Cardinal = (RP_GRIPPER, RP_GRIPPERVERT); + Pattern: array [0..15] of Byte = (0, 0, $CC, 0, $78, 0, $30, 0, $78, 0, $CC, 0, 0, 0, 0, 0); +var +// DC: HDC; + DHSize: Integer; +// Sz: TSize; + R2: TRect; + Flags: Cardinal; + Z: Integer; + BtnVisible, Horz, CloseButtondown, CloseButtonHover: Boolean; +begin +{ DC := Canvas.Handle; + if ToolbarInfo.EffectiveColor <> clNone then FillRectEx(DC, R, ToolbarInfo.EffectiveColor); } + Canvas.FillRect(R); + + { Border } + if ToolbarInfo.BorderStyle = bsSingle then + if USE_THEMES then + begin + Frame3D(Canvas.Handle, R, Lighten(ToolbarInfo.EffectiveColor, 24), Lighten(ToolbarInfo.EffectiveColor, -32), False); +// DrawThemeEdge(TOOLBAR_THEME, Canvas.Handle, RP_BAND, 0, R, BDR_RAISEDINNER, BF_RECT or BF_ADJUST, @R) + end + else + Windows.DrawEdge(Canvas.Handle, R, BDR_RAISEDINNER, BF_RECT or BF_ADJUST); + + if not ToolbarInfo.AllowDrag then Exit; + + BtnVisible := (ToolbarInfo.CloseButtonState and CDBS_VISIBLE) <> 0; + Horz := not ToolbarInfo.IsVertical; + + DHSize := GetTBXDragHandleSize(ToolbarInfo); + if Horz then R.Right := R.Left + DHSize + else R.Bottom := R.Top + DHSize; + + { Drag handle area } + if ToolbarInfo.DragHandleStyle <> DHS_NONE then + begin + if USE_THEMES then + begin + R2 := R; + if BtnVisible then + if Horz then Inc(R2.Top, DHSize - 1) + else Dec(R2.Right, DHSize - 1); + + { Since GetThemePartSize does not seem to work properly, assume we use default + WindowsXP themes where the gripper pattern repeats itself every 4 pixels } + + if Horz then + begin + R2.Left := (R2.Left + R2.Right - 6) div 2; + R2.Right := R2.Left + 6; + Z := R2.Bottom - R2.Top; + R2.Top := R2.Top - 1 + (Z and $3) shr 1; + R2.Bottom := R2.Top + Z and not $3 + 1; + end + else + begin + R2.Top := (R2.Top + R2.Bottom - 6) div 2; + R2.Bottom := R2.Top + 6; + Z := R2.Right - R2.Left; + R2.Left := R2.Left - 1 + (Z and $3) shr 1; + R2.Right := R2.Left + Z and not $3 + 2; + end; + + DrawThemeBackground(REBAR_THEME, Canvas.Handle, GripperPart[ToolbarInfo.IsVertical], 0, R2, nil) + end + else + begin + R2 := R; + if Horz then + begin + Inc(R2.Left, DragHandleOffsets[BtnVisible, ToolbarInfo.DragHandleStyle]); + if BtnVisible then Inc(R2.Top, DHSize - 2); + R2.Right := R2.Left + 3; + InflateRect(R2, 0, -1); + end + else + begin + Inc(R2.Top, DragHandleOffsets[BtnVisible, ToolbarInfo.DragHandleStyle]); + if BtnVisible then Dec(R2.Right, DHSize - 2); + R2.Bottom := R2.Top + 3; + InflateRect(R2, -1, 0); + end; + + Windows.DrawEdge(Canvas.Handle, R2, BDR_RAISEDINNER, BF_RECT); + Canvas.Pixels[R2.Left, R2.Bottom - 1] := clBtnHighlight; + if ToolbarInfo.DragHandleStyle = DHS_DOUBLE then + begin + if Horz then OffsetRect(R2, 3, 0) + else OffsetRect(R2, 0, 3); + Windows.DrawEdge(Canvas.Handle, R2, BDR_RAISEDINNER, BF_RECT); + Canvas.Pixels[R2.Left, R2.Bottom - 1] := clBtnHighlight; + end; + end; + end; + + { Close Button } + if BtnVisible then + begin + CloseButtonDown := (ToolbarInfo.CloseButtonState and CDBS_PRESSED) <> 0; + CloseButtonHover := (ToolbarInfo.CloseButtonState and CDBS_HOT) <> 0; + R2 := GetTBXDockedCloseButtonRect(ToolbarInfo); + Z := 2; + if USE_THEMES then Z := 1; + if Horz then + begin + Dec(R2.Bottom, Z); + Dec(R2.Right, Z); + end + else + begin + Dec(R2.Bottom, Z); + Inc(R2.Left, Z); + end; + if USE_THEMES then + begin + Flags := TS_NORMAL; + if CloseButtonDown then Flags := TS_PRESSED + else if CloseButtonHover then Flags := TS_HOT; + DrawThemeBackground(TOOLBAR_THEME, Canvas.Handle, TP_BUTTON, Flags, R2, nil); + if CloseButtonDown then OffsetRect(R2, 1, 1); + DrawGlyph(Canvas.Handle, R2, 7, 7, Pattern[0], clBtnText); + end + else + begin + if CloseButtonDown then + begin + Windows.DrawEdge(Canvas.Handle, R2, BDR_SUNKENOUTER, BF_RECT); + OffsetRect(R2, 1, 1); + end + else if CloseButtonHover then + Windows.DrawEdge(Canvas.Handle, R2, BDR_RAISEDINNER, BF_RECT); + DrawGlyph(Canvas.Handle, R2, 7, 7, Pattern[0], clBtnText); + end; + end; +end; + +procedure TTBXDefaultTheme.PaintDock(Canvas: TCanvas; const ClientRect, DockRect: TRect; DockPosition: Integer); +var + R: TRect; +begin + if not USE_THEMES then Exit; + if DockPosition in [DP_LEFT, DP_RIGHT] then + begin + R := DockRect; + Inc(R.Bottom, 1); + DrawThemeBackground(REBAR_THEME, Canvas.Handle, 0, 0, R, nil); + end + else DrawThemeBackground(REBAR_THEME, Canvas.Handle, 0, 0, DockRect, nil); +end; + +procedure TTBXDefaultTheme.PaintDockPanelNCArea(Canvas: TCanvas; R: TRect; const DockPanelInfo: TTBXDockPanelInfo); +var + DC: HDC; + Sz: Integer; + R2: TRect; + Flags: Integer; + CloseButtonDown, CloseButtonHover: Boolean; + + procedure CaptionFill(R: TRect); + const + GRAD: array [Boolean] of TGradientKind = (gkHorz, gkVert); + begin + if USE_THEMES then + GradFill(DC, R, Lighten(ToolbarColor, 12), Lighten(ToolbarColor, -12), GRAD[DockPanelInfo.IsVertical]) + else + FillRectEx(DC, R, ToolbarColor); + end; + +begin + DC := Canvas.Handle; + with Canvas, DockPanelInfo do + begin + Sz := GetSystemMetrics(SM_CYSMCAPTION); + + { Border } + FrameRectEx(DC, R, ToolbarColor, True); + R2 := R; + if ShowCaption then + if IsVertical then Inc(R2.Top, Sz) + else Inc(R2.Left, Sz); + FrameRectEx(DC, R2, clWindow, False); + + if not ShowCaption then Exit; + + { Caption area } + if IsVertical then R.Bottom := R.Top + Sz + else R.Right := R.Left + Sz; + Windows.DrawEdge(Handle, R, BDR_RAISEDINNER, BF_RECT or BF_ADJUST); + + { Close button } + if (CDBS_VISIBLE and CloseButtonState) <> 0 then + begin + CloseButtonDown := (CloseButtonState and CDBS_PRESSED) <> 0; + CloseButtonHover := (CloseButtonState and CDBS_HOT) <> 0; + R2 := R; + Brush.Color := ToolbarColor; + if IsVertical then + begin + R2.Left := R2.Right - Sz; + R.Right := R2.Left; + CaptionFill(R2); + InflateRect(R2, -1, -1); + Inc(R2.Left); + end + else + begin + R2.Top := R2.Bottom - Sz; + R.Bottom := R2.Top; + CaptionFill(R2); + InflateRect(R2, -1, -1); + Dec(R2.Bottom); + end; + + if USE_THEMES then + begin + Flags := TS_NORMAL; + if CloseButtonDown then Flags := TS_PRESSED + else if CloseButtonHover then Flags := TS_HOT; + DrawThemeBackground(TOOLBAR_THEME, DC, TP_BUTTON, Flags, R2, nil); + if CloseButtonDown then OffsetRect(R2, 1, 1); + InflateRect(R2, -2, -2); + end + else + begin + if CloseButtonDown then + begin + Windows.DrawEdge(DC, R2, BDR_SUNKENOUTER, BF_RECT); + OffsetRect(R2, 1, 1); + end + else if CloseButtonHover then + Windows.DrawEdge(DC, R2, BDR_RAISEDINNER, BF_RECT); + InflateRect(R2, -2, -2); + end; + DrawButtonBitmap(Canvas, R2); + end; + + { Caption } + CaptionFill(R); + if IsVertical then InflateRect(R, -2, 0) + else Inflaterect(R, 0, -2); + Font.Assign(SmCaptionFont); + Font.Color := clBtnText; + Brush.Style := bsClear; + Flags := DT_SINGLELINE or DT_VCENTER or DT_END_ELLIPSIS or DT_NOPREFIX; + if IsVertical then DrawText(Canvas.Handle, Caption, -1, R, Flags) + else DrawRotatedText(Canvas.Handle, string(Caption), R, Flags); + Brush.Style := bsSolid; + end; +end; + +function TTBXDefaultTheme.GetPopupShadowType: Integer; +begin + Result := PST_WINDOWSXP; +end; + +procedure TTBXDefaultTheme.GetViewMargins(ViewType: Integer; out Margins: TTBXMargins); +begin + with Margins do + if ((ViewType and VT_TOOLBAR) = VT_TOOLBAR) and + ((ViewType and TVT_FLOATING) = TVT_FLOATING) then + begin + LeftWidth := 4; + TopHeight := 2; + RightWidth := 4; + BottomHeight := 1; + end + else + begin + LeftWidth := 0; + TopHeight := 0; + RightWidth := 0; + BottomHeight := 0; + end; +end; + +procedure TTBXDefaultTheme.PaintPageScrollButton(Canvas: TCanvas; + const ARect: TRect; ButtonType: Integer; Hot: Boolean); +var + R: TRect; + Flags: Integer; + X, Y, Sz: Integer; +begin + R := ARect; + if USE_THEMES then + begin + if Hot then Flags := TS_PRESSED + else Flags := TS_HOT; + DrawThemeBackground(TOOLBAR_THEME, Canvas.Handle, TP_BUTTON, Flags, ARect, nil); + X := (R.Left + R.Right) div 2; + Y := (R.Top + R.Bottom) div 2; + Sz := Min(X - R.Left, Y - R.Top) * 3 div 4; + if Hot then Canvas.Pen.Color := clBtnText; + Canvas.Brush.Color := Canvas.Pen.Color; + case ButtonType of + PSBT_UP: + begin + Inc(Y, Sz div 2); + Canvas.Polygon([Point(X + Sz, Y), Point(X, Y - Sz), Point(X - Sz, Y)]); + end; + PSBT_DOWN: + begin + Y := (R.Top + R.Bottom - 1) div 2; + Dec(Y, Sz div 2); + Canvas.Polygon([Point(X + Sz, Y), Point(X, Y + Sz), Point(X - Sz, Y)]); + end; + PSBT_LEFT: + begin + Inc(X, Sz div 2); + Canvas.Polygon([Point(X, Y + Sz), Point(X - Sz, Y), Point(X, Y - Sz)]); + end; + PSBT_RIGHT: + begin + X := (R.Left + R.Right - 1) div 2; + Dec(X, Sz div 2); + Canvas.Polygon([Point(X, Y + Sz), Point(X + Sz, Y), Point(X, Y - Sz)]); + end; + end; + end + else + begin + if Hot then Flags := DFCS_FLAT + else Flags := 0; + case ButtonType of + PSBT_UP: Flags := Flags or DFCS_SCROLLUP; + PSBT_DOWN: Flags := Flags or DFCS_SCROLLDOWN; + PSBT_LEFT: Flags := Flags or DFCS_SCROLLLEFT; + PSBT_RIGHT: Flags := Flags or DFCS_SCROLLRIGHT; + end; + Windows.DrawFrameControl(Canvas.Handle, R, DFC_SCROLL, Flags); + end; +end; + +procedure TTBXDefaultTheme.PaintFrameControl(Canvas: TCanvas; R: TRect; Kind, State: Integer; Params: Pointer); +var + DC: HDC; + X, Y, Flags: Integer; + C: TColor; + Pen, OldPen: HPen; + Brush, OldBrush: HBrush; + + function FrameColor: TColor; + begin + if Boolean(State and PFS_DISABLED) then Result := clBtnShadow + else if Boolean(State and (PFS_PUSHED or PFS_HOT)) then Result := clNone + else Result := clBtnShadow; + end; + + procedure DiagLine(C: TColor); + begin + with R do + DrawLineEx(DC, Right - 2 - X, Bottom - 2, Right - 1, Bottom - X - 3, C); + Inc(X); + end; + +begin + DC := Canvas.Handle; + case Kind of + PFC_CHECKBOX: + begin + if USE_THEMES then + begin + if Boolean(State and PFS_CHECKED) then Flags := CBS_CHECKEDNORMAL + else if Boolean(State and PFS_MIXED) then Flags := CBS_MIXEDNORMAL + else Flags := CBS_UNCHECKEDNORMAL; + if Boolean(State and PFS_DISABLED) then Inc(Flags, 3) + else if Boolean(State and PFS_PUSHED) then Inc(Flags, 2) + else if Boolean(State and PFS_HOT) then Inc(Flags); + DrawThemeBackground(BUTTON_THEME, DC, BP_CHECKBOX, Flags, R, nil); + end + else + begin + C := FrameColor; + if C = clNone then + begin + if Boolean(State and PFS_MIXED) then Flags := DFCS_BUTTON3STATE or DFCS_CHECKED + else Flags := DFCS_BUTTONCHECK; + if Boolean(State and PFS_CHECKED) then Flags := Flags or DFCS_CHECKED; + if Boolean(State and PFS_PUSHED) then Flags := Flags or DFCS_PUSHED; + DrawFrameControl(DC, R, DFC_BUTTON, Flags); + end + else + begin + InflateRect(R, -1, -1); + FrameRectEx(DC, R, C, True); + if Boolean(State and (PFS_DISABLED or PFS_PUSHED)) then FillRectEx(DC, R, clBtnFace) + else if Boolean(State and PFS_MIXED) then DitherRect(DC, R, clWindow, clBtnFace) + else FillRectEx(DC, R, clWindow); + + if Boolean(State and (PFS_CHECKED or PFS_MIXED)) then + begin + X := (R.Left + R.Right) div 2 - 1; + Y := (R.Top + R.Bottom) div 2 + 1; + if Boolean(State and PFS_DISABLED) then C := clGrayText + else if Boolean(State and PFS_MIXED) then C := clBtnShadow + else C := clBtnText; + PolygonEx(DC, [Point(X-2, Y), Point(X, Y+2), Point(X+4, Y-2), + Point(X+4, Y-4), Point(X, Y), Point(X-2, Y-2), Point(X-2, Y)], C, C); + end; + end; + end; + end; + PFC_RADIOBUTTON: + begin + if USE_THEMES then + begin + if Boolean(State and PFS_CHECKED) then Flags := RBS_CHECKEDNORMAL + else Flags := RBS_UNCHECKEDNORMAL; + if Boolean(State and PFS_DISABLED) then Inc(Flags, 3) + else if Boolean(State and PFS_PUSHED) then Inc(Flags, 2) + else if Boolean(State and PFS_HOT) then Inc(Flags); + DrawThemeBackground(BUTTON_THEME, DC, BP_RADIOBUTTON, Flags, R, nil); + end + else + begin + C := FrameColor; + if C = clNone then + begin + Flags := DFCS_BUTTONRADIO; + if Boolean(State and PFS_CHECKED) then Flags := Flags or DFCS_CHECKED; + if Boolean(State and PFS_PUSHED) then Flags := Flags or DFCS_PUSHED; + DrawFrameControl(DC, R, DFC_BUTTON, Flags); + end + else + begin + Pen := CreatePenEx(C); + if Boolean(State and (PFS_DISABLED or PFS_PUSHED)) then C := clBtnFace + else C := clWindow; + Brush := CreateBrushEx(C); + + InflateRect(R, -1, -1); Inc(R.Left); Dec(R.Bottom); + OldPen := SelectObject(DC, Pen); + OldBrush := SelectObject(DC, Brush); + with R do + Windows.RoundRect(DC, Left, Top, Right, Bottom, Right - Left - 2, Bottom - Top - 2); + SelectObject(DC, OldPen); + SelectObject(DC, OldBrush); + DeleteObject(Pen); + DeleteObject(Brush); + + if Boolean(State and PFS_CHECKED) then + begin + InflateRect(R, -3, -3); + Pen := CreatePenEx(clBtnText); + Brush := CreateBrushEx(clBtnText); + OldPen := SelectObject(DC, Pen); + OldBrush := SelectObject(DC, Brush); + with R do Windows.RoundRect(DC, Left, Top, Right, Bottom, Right - Left, Bottom - Top); + SelectObject(DC, OldPen); + SelectObject(DC, OldBrush); + DeleteObject(Pen); + DeleteObject(Brush); + end; + end; + end; + end; + end; +end; + +procedure TTBXDefaultTheme.PaintStatusBar(Canvas: TCanvas; R: TRect; Part: Integer); +var + DC: HDC; + D, Sz, I, Flags: Integer; + + procedure DiagLine(C: TColor); + begin + with R do + DrawLineEx(DC, Right - 2 - D, Bottom - 2, Right - 1, Bottom - D - 3, C); + Inc(D); + end; + +begin + DC := Canvas.Handle; + case Part of + SBP_BODY: + begin + if USE_THEMES then + DrawThemeBackground(STATUSBAR_THEME, DC, 0, 0, R, nil) + else + FillRectEx(DC, R, StatusBarColor); + end; + SBP_PANE, SBP_LASTPANE: + begin + if USE_THEMES then + begin + if Part = SBP_LASTPANE then Flags := SP_GRIPPERPANE + else Flags := SP_PANE; + DrawThemeBackground(STATUSBAR_THEME, DC, Flags, 0, R, nil); + end + else + begin + if Part = SBP_PANE then Dec(R.Right, 2); + Frame3D(DC, R, clBtnShadow, clBtnHighlight, False); + end; + end; + SBP_GRIPPER: + begin + if USE_THEMES then + DrawThemeBackground(STATUSBAR_THEME, DC, SP_GRIPPER, 0, R, nil) + else + begin + D := 0; + Sz := Min(R.Right - R.Left, R.Bottom - R.Top); + for I := 1 to 3 do + case Sz of + 0..8: + begin + DiagLine(clBtnShadow); + DiagLine(clBtnHighlight); + end; + 9..11: + begin + DiagLine(StatusBarColor); + DiagLine(clBtnShadow); + DiagLine(clBtnHighlight); + end; + 12..14: + begin + DiagLine(clBtnShadow); + DiagLine(clBtnShadow); + DiagLine(clBtnHighlight); + end; + else + DiagLine(StatusBarColor); + DiagLine(clBtnShadow); + DiagLine(clBtnShadow); + DiagLine(clBtnHighlight); + end; + + with Canvas, R do + begin + Pen.Color := StatusBarColor; + PolylineEx(DC, [ + Point(Right - D - 1, Bottom - 1), + Point(Right - 1, Bottom - 1), + Point(Right - 1, Bottom - D - 2)], + StatusBarColor); + end; + end; + end; + end; +end; + +procedure TTBXDefaultTheme.SetupColorCache; +begin + ToolbarColor := clBtnFace; + ToolbarText := clBtnText; + StatusBarColor := clBtnFace; + if USE_THEMES then + begin + GetThemeColor(TOOLBAR_THEME, 0, 0, TMT_FILLCOLOR, Cardinal(ToolbarColor)); + GetThemeColor(TOOLBAR_THEME, 0, 0, TMT_TEXTCOLOR, Cardinal(ToolbarText)); + GetThemeColor(STATUSBAR_THEME, 0, 0, TMT_FILLCOLOR, Cardinal(StatusBarColor)); + end; + DockPanelColor := NearestMixedColor(ToolbarColor, clWindow, 64); +end; + +procedure TTBXDefaultTheme.TBXSysCommand(var Message: TMessage); +begin + if Message.WParam = TSC_VIEWCHANGE then SetupColorCache; +end; + +initialization + InitializeStock; + +finalization + FinalizeStock; + +end. diff --git a/official/2.1.6+2.1.beta1/TBX/TBXDefaultTheme.pas.orig b/official/2.1.6+2.1.beta1/TBX/TBXDefaultTheme.pas.orig new file mode 100644 index 0000000..976041d --- /dev/null +++ b/official/2.1.6+2.1.beta1/TBX/TBXDefaultTheme.pas.orig @@ -0,0 +1,1777 @@ +unit TBXDefaultTheme; + +// TBX Package +// Copyright 2001-2004 Alex A. Denisov. All Rights Reserved +// See TBX.chm for license and installation instructions +// +// $Id: TBXDefaultTheme.pas 16 2004-05-26 02:02:55Z Alex@ZEISS $ + +interface + +{$I TB2Ver.inc} +{$I TBX.inc} + +uses + Windows, Messages, Graphics, TBXThemes, ImgList; + +type + TTBXDefaultTheme = class(TTBXTheme) + private + procedure TBXSysCommand(var Message: TMessage); message TBX_SYSCOMMAND; + protected + ToolbarColor: TColor; + ToolbarText: TColor; + DockPanelColor: TColor; + StatusBarColor: TColor; + procedure SetupColorCache; virtual; + public + constructor Create(const AName: string); override; + destructor Destroy; override; + + { Metrics Access, etc. } + function GetBooleanMetrics(Index: Integer): Boolean; override; + function GetImageOffset(Canvas: TCanvas; const ItemInfo: TTBXItemInfo; ImageList: TCustomImageList): TPoint; override; + function GetIntegerMetrics(Index: Integer): Integer; override; + procedure GetMargins(MarginID: Integer; out Margins: TTBXMargins); override; + + function GetItemColor(const ItemInfo: TTBXItemInfo): TColor; override; + function GetItemTextColor(const ItemInfo: TTBXItemInfo): TColor; override; + function GetItemImageBackground(const ItemInfo: TTBXItemInfo): TColor; override; + function GetPopupShadowType: Integer; override; + procedure GetViewBorder(ViewType: Integer; out Border: TPoint); override; + function GetViewColor(ViewType: Integer): TColor; override; + procedure GetViewMargins(ViewType: Integer; out Margins: TTBXMargins); override; + + { Painting routines } + procedure PaintBackgnd(Canvas: TCanvas; const ADockRect, ARect, AClipRect: TRect; AColor: TColor; Transparent: Boolean; AViewType: Integer); override; + procedure PaintButton(Canvas: TCanvas; const ARect: TRect; const ItemInfo: TTBXItemInfo); override; + procedure PaintCaption(Canvas: TCanvas; const ARect: TRect; const ItemInfo: TTBXItemInfo; const ACaption: string; AFormat: Cardinal; Rotated: Boolean); override; + procedure PaintCheckMark(Canvas: TCanvas; ARect: TRect; const ItemInfo: TTBXItemInfo); override; + procedure PaintChevron(Canvas: TCanvas; ARect: TRect; const ItemInfo: TTBXItemInfo); override; + procedure PaintDock(Canvas: TCanvas; const ClientRect, DockRect: TRect; DockPosition: Integer); override; + procedure PaintDockPanelNCArea(Canvas: TCanvas; R: TRect; const DockPanelInfo: TTBXDockPanelInfo); override; + procedure PaintDropDownArrow(Canvas: TCanvas; const ARect: TRect; const ItemInfo: TTBXItemInfo); override; + procedure PaintEditButton(Canvas: TCanvas; const ARect: TRect; var ItemInfo: TTBXItemInfo; ButtonInfo: TTBXEditBtnInfo); override; + procedure PaintEditFrame(Canvas: TCanvas; const ARect: TRect; var ItemInfo: TTBXItemInfo; const EditInfo: TTBXEditInfo); override; + procedure PaintFloatingBorder(Canvas: TCanvas; const ARect: TRect; const WindowInfo: TTBXWindowInfo); override; + procedure PaintFrame(Canvas: TCanvas; const ARect: TRect; const ItemInfo: TTBXItemInfo); override; + procedure PaintImage(Canvas: TCanvas; ARect: TRect; const ItemInfo: TTBXItemInfo; ImageList: TCustomImageList; ImageIndex: Integer); override; + procedure PaintMDIButton(Canvas: TCanvas; ARect: TRect; const ItemInfo: TTBXItemInfo; ButtonKind: Cardinal); override; + procedure PaintMenuItem(Canvas: TCanvas; const ARect: TRect; var ItemInfo: TTBXItemInfo); override; + procedure PaintMenuItemFrame(Canvas: TCanvas; const ARect: TRect; const ItemInfo: TTBXItemInfo); override; + procedure PaintPageScrollButton(Canvas: TCanvas; const ARect: TRect; ButtonType: Integer; Hot: Boolean); override; + procedure PaintPopupNCArea(Canvas: TCanvas; R: TRect; const PopupInfo: TTBXPopupInfo); override; + procedure PaintSeparator(Canvas: TCanvas; ARect: TRect; ItemInfo: TTBXItemInfo; Horizontal, LineSeparator: Boolean); override; + procedure PaintToolbarNCArea(Canvas: TCanvas; R: TRect; const ToolbarInfo: TTBXToolbarInfo); override; + procedure PaintFrameControl(Canvas: TCanvas; R: TRect; Kind, State: Integer; Params: Pointer); override; + procedure PaintStatusBar(Canvas: TCanvas; R: TRect; Part: Integer); override; + end; + +implementation + +uses + Classes, Controls, CommCtrl, TBXUtils, TBXUxThemes, TB2Common, TB2Item, TBX, Forms; + +var + SmCaptionFont: TFont; + +procedure InitializeStock; +var + NonClientMetrics: TNonClientMetrics; +begin + SmCaptionFont := TFont.Create; + NonClientMetrics.cbSize := SizeOf(NonClientMetrics); + if SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, @NonClientMetrics, 0) then + SmCaptionFont.Handle := CreateFontIndirect(NonClientMetrics.lfSmCaptionFont); +end; + +procedure FinalizeStock; +begin + SmCaptionFont.Free; + SmCaptionFont := nil; +end; + +procedure DrawButtonBitmap(Canvas: TCanvas; R: TRect); +const + Pattern: array [0..15] of Byte = ($C6, 0, $6C, 0, $38, 0, $38, 0, $6C, 0, $C6, 0, 0, 0, 0, 0); +begin + DrawGlyph(Canvas.Handle, R, 7, 6, Pattern[0], clBtnText); +end; + +{ TTBXDefaultTheme } + +constructor TTBXDefaultTheme.Create; +begin + inherited; + AddTBXSysChangeNotification(Self); + SetupColorCache; +end; + +destructor TTBXDefaultTheme.Destroy; +begin + RemoveTBXSysChangeNotification(Self); + inherited; +end; + +function TTBXDefaultTheme.GetBooleanMetrics(Index: Integer): Boolean; +begin + case Index of + TMB_OFFICEXPPOPUPALIGNMENT: Result := False; + TMB_EDITMENUFULLSELECT: Result := False; + TMB_EDITHEIGHTEVEN: Result := False; + TMB_PAINTDOCKBACKGROUND: Result := USE_THEMES; + TMB_SOLIDTOOLBARNCAREA: Result := False; + TMB_SOLIDTOOLBARCLIENTAREA: Result := False; + else + Result := False; + end; +end; + +function TTBXDefaultTheme.GetIntegerMetrics(Index: Integer): Integer; +const + DEFAULT = -1; +var + Sz: TSize; +begin + case Index of + TMI_SPLITBTN_ARROWWIDTH: + if USE_THEMES then + begin + if GetThemePartSize(TOOLBAR_THEME, StockCompatibleBitmap.Canvas.Handle, + TP_SPLITBUTTONDROPDOWN, TS_NORMAL, nil, TS_TRUE, Sz) = S_OK then + begin + Result := Sz.cx + 2; + end + else Result := 11; + end + else Result := 11; + + TMI_DROPDOWN_ARROWWIDTH: Result := 8; + TMI_DROPDOWN_ARROWMARGIN: Result := 3; + + TMI_MENU_IMGTEXTSPACE: Result := 1; + TMI_MENU_LCAPTIONMARGIN: Result := 2; + TMI_MENU_RCAPTIONMARGIN: Result := 2; + TMI_MENU_SEPARATORSIZE: Result := DEFAULT; + TMI_MENU_MDI_DW: Result := 2; + TMI_MENU_MDI_DH: Result := 4; + + TMI_TLBR_SEPARATORSIZE: Result := 6; + + TMI_EDIT_FRAMEWIDTH: Result := 2; + TMI_EDIT_TEXTMARGINHORZ: Result := 2; + TMI_EDIT_TEXTMARGINVERT: Result := 1; + TMI_EDIT_BTNWIDTH: Result := 13; + TMI_EDIT_MENURIGHTINDENT: Result := 0; + else + Result := DEFAULT; + end; +end; + +function TTBXDefaultTheme.GetViewColor(ViewType: Integer): TColor; +begin + Result := ToolbarColor; + if (ViewType and VT_TOOLBAR) = VT_TOOLBAR then Result := ToolbarColor + else if (ViewType and VT_POPUP) = VT_POPUP then + begin + if (ViewType and PVT_POPUPMENU) = PVT_POPUPMENU then Result := clPopup + else if (ViewType and PVT_LISTBOX) = PVT_LISTBOX then Result := clWindow + else if (ViewType and PVT_TOOLBOX) = PVT_TOOLBOX then Result := ToolbarColor + else if (ViewType and PVT_CHEVRONMENU) = PVT_CHEVRONMENU then Result := clPopup; + end + else if (ViewType and VT_DOCKPANEL) = VT_DOCKPANEL then Result := DockPanelColor + else if (ViewType and VT_STATUSBAR) = VT_STATUSBAR then Result := StatusBarColor + else Result := clBtnFace; +end; + +function TTBXDefaultTheme.GetItemColor(const ItemInfo: TTBXItemInfo): TColor; +var + IsMenuItem: Boolean; +begin + with ItemInfo do + begin + IsMenuItem := ((ViewType and PVT_POPUPMENU) = PVT_POPUPMENU) and ((ItemOptions and IO_TOOLBARSTYLE) = 0); + if not USE_THEMES then + begin + if IsMenuItem and (ItemInfo.HoverKind <> hkNone) then Result := clHighlight + else Result := GetViewColor(ItemInfo.ViewType); + end + else + Result := GetViewColor(ItemInfo.ViewType); + end; +end; + +function TTBXDefaultTheme.GetItemTextColor(const ItemInfo: TTBXItemInfo): TColor; +var + InMenuBar, ToolbarStyle, ShowInactive: Boolean; +begin + Result := clBtnText; + with ItemInfo do + begin + InMenuBar := (ViewType and TVT_MENUBAR) = TVT_MENUBAR; + ToolbarStyle := Boolean(ItemOptions and IO_TOOLBARSTYLE); + ShowInactive := InMenubar and not Boolean(ItemOptions and IO_APPACTIVE); + + if not ToolbarStyle and not Enabled and (HoverKind = hkKeyboardHover) then Result := clGrayText + else if Enabled then + begin + if not ToolbarStyle or (InMenuBar and USE_FLATMENUS) then + begin + if HoverKind <> hkNone then Result := clHighlightText + else if ShowInactive then Result := clGrayText + else Result := clPopupText + end + else if ShowInactive then Result := clGrayText; + end + else Result := clGrayText; + end; +end; + +function TTBXDefaultTheme.GetItemImageBackground(const ItemInfo: TTBXItemInfo): TColor; +var + IsFlatMenuItem, InFlatMenuBar, InFlatChevronBar: Boolean; +begin + with ItemInfo do + begin + InFlatMenuBar := ((ViewType and TVT_MENUBAR) = TVT_MENUBAR) and USE_FLATMENUS; + InFlatChevronBar := ((ViewType and PVT_CHEVRONMENU) = PVT_CHEVRONMENU) and USE_FLATMENUS; + IsFlatMenuItem := ((ViewType and PVT_POPUPMENU) = PVT_POPUPMENU) and ((ItemOptions and IO_TOOLBARSTYLE) = 0) and USE_FLATMENUS; + + if InFlatMenuBar and (HoverKind <> hkNone) then Result := clHighlight + else if InFlatChevronBar or IsFlatMenuItem and (HoverKind <> hkNone) then Result := ToolbarColor + else Result := GetViewColor(ViewType); + end; +end; + +procedure TTBXDefaultTheme.GetViewBorder(ViewType: Integer; out Border: TPoint); +const + XMetrics: array [Boolean] of Integer = (SM_CXDLGFRAME, SM_CXFRAME); + YMetrics: array [Boolean] of Integer = (SM_CYDLGFRAME, SM_CYFRAME); +var + Resizable: Boolean; + Sz: Integer; +begin + Sz := 0; + if (ViewType and VT_TOOLBAR) = VT_TOOLBAR then + begin + if (ViewType and TVT_FLOATING) = TVT_FLOATING then + begin + Resizable := (ViewType and TVT_RESIZABLE) = TVT_RESIZABLE; + Border.X := GetSystemMetrics(XMetrics[Resizable]); + Border.Y := GetSystemMetrics(YMetrics[Resizable]); + Exit; + end + else Sz := 2; + end + else if (ViewType and VT_POPUP) = VT_POPUP then + begin +{$IFNDEF OFFICE2K_COMBOS} + if (ViewType and PVT_LISTBOX) = PVT_LISTBOX then Sz := 1 + else Sz := 3; +{$ELSE} + Sz := 3; +{$ENDIF} + end + else if (ViewType and VT_DOCKPANEL) = VT_DOCKPANEL then + begin + if (ViewType and DPVT_FLOATING) = DPVT_FLOATING then + begin + Resizable := (ViewType and DPVT_RESIZABLE) = DPVT_RESIZABLE; + Border.X := GetSystemMetrics(XMetrics[Resizable]); + Border.Y := GetSystemMetrics(YMetrics[Resizable]); + Exit; + end + else Sz := 2; + end; + Border.X := Sz; + Border.Y := Sz; +end; + +procedure TTBXDefaultTheme.GetMargins(MarginID: Integer; out Margins: TTBXMargins); +var + R, R2: TRect; +begin + with Margins do + case MarginID of + MID_TOOLBARITEM: + begin + LeftWidth := 2; RightWidth := 2; + TopHeight := 2; BottomHeight := 2; + if USE_THEMES then + GetThemeMargins(TOOLBAR_THEME, StockBitmap1.Canvas.Handle, TP_BUTTON, TS_HOT, TMT_CAPTIONMARGINS, + nil, TMargins(Margins)); + end; + + MID_MENUITEM: + begin + LeftWidth := 0; RightWidth := 0; + TopHeight := 2; BottomHeight := 2; + end; + + MID_STATUSPANE: + begin + if USE_THEMES then + begin + R := Rect(0, 0, 100, 100); + GetThemeBackgroundContentRect(STATUSBAR_THEME, StockBitmap1.Canvas.Handle, SP_PANE, 0, R, @R2); + LeftWidth := R2.Left - R.Left; + RightWidth := R.Right - R2.Right; + TopHeight := R2.Top - R.Top; + BottomHeight := R.Bottom - R2.Bottom; + end + else + begin + LeftWidth := 1; RightWidth := 3; + TopHeight := 1; BottomHeight := 1; + end; + end; + else + LeftWidth := 0; RightWidth := 0; + TopHeight := 0; BottomHeight := 0; + end; +end; + +procedure TTBXDefaultTheme.PaintBackgnd(Canvas: TCanvas; const ADockRect, ARect, AClipRect: TRect; + AColor: TColor; Transparent: Boolean; AViewType: Integer); +var + DC: HDC; + R: TRect; +begin + DC := Canvas.Handle; + if not Transparent then + begin + IntersectRect(R, ARect, AClipRect); + FillRectEx(DC, R, AColor); + end; +end; + +procedure TTBXDefaultTheme.PaintCaption(Canvas: TCanvas; + const ARect: TRect; const ItemInfo: TTBXItemInfo; const ACaption: string; + AFormat: Cardinal; Rotated: Boolean); +var + R: TRect; + C: TColor; + InMenuBar, ToolbarStyle: Boolean; + + procedure _Draw(Color: TColor); + begin + Canvas.Font.Color := Color; + if not Rotated then Windows.DrawText(Canvas.Handle, PChar(ACaption), Length(ACaption), R, AFormat) + else DrawRotatedText(Canvas.Handle, ACaption, R, AFormat); + end; + +begin + with ItemInfo, Canvas do + begin + R := ARect; + C := Font.Color; + { Apply theme-dependent color only when Font.Color = clNone } + if C = clNone then C := GetItemTextColor(ItemInfo); + Brush.Style := bsClear; + InMenuBar := (ViewType and TVT_MENUBAR) = TVT_MENUBAR; + ToolbarStyle := Boolean(ItemOptions and IO_TOOLBARSTYLE); + if not ToolbarStyle and not Enabled and (HoverKind = hkKeyboardHover) then _Draw(C) + else if Enabled then + begin + if ToolbarStyle and (Pushed or Selected) and not (InMenuBar and USE_FLATMENUS) then + OffsetRect(R, 1, 1); + _Draw(C); + end + else if USE_THEMES then _Draw(C) + else + begin + OffsetRect(R, 1, 1); + _Draw(clBtnHighlight); + OffsetRect(R, -1, -1); + _Draw(clBtnShadow); + end; + Brush.Style := bsSolid; + end; +end; + +procedure TTBXDefaultTheme.PaintCheckMark(Canvas: TCanvas; ARect: TRect; const ItemInfo: TTBXItemInfo); +var + X, Y: Integer; +begin + X := (ARect.Left + ARect.Right) div 2 - 1; + Y := (ARect.Top + ARect.Bottom) div 2 + 2; + if ItemInfo.Enabled then Canvas.Pen.Color := clBtnText + else Canvas.Pen.Color := clGrayText; + Canvas.Polyline([Point(X-2, Y-2), Point(X, Y), Point(X+4, Y-4), + Point(X+4, Y-3), Point(X, Y+1), Point(X-2, Y-1), Point(X-2, Y-2)]); + if ItemInfo.Enabled then + begin + Canvas.Pen.Color := clBtnHighlight; + Canvas.Polyline([Point(X-3, Y-2), Point(X-3, Y-1), Point(X, Y+2), + Point(X+5, Y-3), Point(X+5, Y-5)]); + end; +end; + +procedure TTBXDefaultTheme.PaintChevron(Canvas: TCanvas; ARect: TRect; + const ItemInfo: TTBXItemInfo); +const + Pattern: array [Boolean, 0..15] of Byte = ( + ($CC, 0, $66, 0, $33, 0, $66, 0, $CC, 0, 0, 0, 0, 0, 0, 0), + ($88, 0, $D8, 0, $70, 0, $20, 0, $88, 0, $D8, 0, $70, 0, $20, 0)); +var + DC: HDC; + R2: TRect; + P: PByte; + W, H: Integer; +begin + DC := Canvas.Handle; + R2 := ARect; + PaintButton(Canvas, R2, ItemInfo); + + if not ItemInfo.IsVertical then + begin + Inc(R2.Top, 4); + R2.Bottom := R2.Top + 5; + W := 8; + H := 5; + end + else + begin + R2.Left := R2.Right - 9; + R2.Right := R2.Left + 5; + W := 5; + H := 8; + end; + if ItemInfo.Pushed then OffsetRect(R2, 1, 1); + + P := @Pattern[ItemInfo.IsVertical][0]; + if ItemInfo.Enabled then DrawGlyph(DC, R2, W, H, P^, clBtnText) + else + begin + OffsetRect(R2, 1, 1); + DrawGlyph(DC, R2, W, H, P^, clBtnHighlight); + OffsetRect(R2, -1, -1); + DrawGlyph(DC, R2, W, H, P^, clBtnShadow); + end; +end; + +procedure TTBXDefaultTheme.PaintEditButton(Canvas: TCanvas; const ARect: TRect; + var ItemInfo: TTBXItemInfo; ButtonInfo: TTBXEditBtnInfo); +var + DC: HDC; + BtnDisabled, BtnHot, BtnPressed, Embedded: Boolean; + StateFlags: Integer; + R, BR: TRect; + C: TColor; + X, Y: Integer; + + procedure DrawEnabled(var R: TRect); + begin + if BtnPressed then + Windows.DrawEdge(Canvas.Handle, R, BDR_SUNKENOUTER, BF_RECT or BF_ADJUST) + else if BtnHot then + Windows.DrawEdge(Canvas.Handle, R, BDR_RAISEDINNER, BF_RECT or BF_ADJUST) + else if not Embedded then + FrameRectEx(DC, R, clWindow, False); + end; + + procedure DrawUp; + begin + X := (R.Left + R.Right) div 2 + Ord(BtnPressed); + Y := (R.Top * 3 + R.Bottom + 3) div 4 + Ord(BtnPressed); + if not BtnDisabled then + begin + if Boolean(ItemInfo.ItemOptions and IO_TOOLBARSTYLE) then C := clPopupText + else C := clBtnText; + end + else with Canvas do + begin + Inc(X); Inc(Y); + Pen.Color := clBtnHighlight; Brush.Color := clBtnHighlight; + Polygon([Point(X - 2, Y), Point(X + 2, Y), Point(X, Y - 2)]); + Dec(X); Dec(Y); + C := clBtnShadow; + end; + Canvas.Pen.Color := C; Canvas.Brush.Color := C; + Canvas.Polygon([Point(X - 2, Y), Point(X + 2, Y), Point(X, Y - 2)]) + end; + + procedure DrawDn; + begin + X := (R.Left + R.Right) div 2 + Ord(BtnPressed); + Y := (R.Top + R.Bottom * 3 - 4) div 4 + Ord(BtnPressed); + if not BtnDisabled then + begin + if Boolean(ItemInfo.ItemOptions and IO_TOOLBARSTYLE) then C := clPopupText + else C := clBtnText; + end + else with Canvas do + begin + Inc(X); Inc(Y); + Pen.Color := clBtnHighlight; Brush.Color := clBtnHighlight; + Polygon([Point(X - 2, Y), Point(X + 2, Y), Point(X, Y + 2)]); + Dec(X); Dec(Y); + C := clBtnShadow; + end; + Canvas.Pen.Color := C; Canvas.Brush.Color := C; + Canvas.Polygon([Point(X - 2, Y), Point(X + 2, Y), Point(X, Y + 2)]) + end; + +begin + DC := Canvas.Handle; + R := ARect; + with Canvas, ItemInfo do + begin + Embedded := ((ViewType and VT_TOOLBAR) = VT_TOOLBAR) and + ((ViewType and TVT_EMBEDDED) = TVT_EMBEDDED); + + if ButtonInfo.ButtonType = EBT_DROPDOWN then + begin + { DropDown button } + BtnDisabled := (ButtonInfo.ButtonState and EBDS_DISABLED) <> 0; + BtnHot := (ButtonInfo.ButtonState and EBDS_HOT) <> 0; + BtnPressed := (ButtonInfo.ButtonState and EBDS_PRESSED) <> 0; + if USE_THEMES then + begin + if BtnDisabled then StateFlags := CBXS_DISABLED + else if BtnPressed then StateFlags := CBXS_PRESSED + else if BtnHot then StateFlags := CBXS_HOT + else StateFlags := CBXS_NORMAL; + if BtnHot then InflateRect(R, 1, 1); + DrawThemeBackground(COMBO_THEME, Handle, CP_DROPDOWNBUTTON, StateFlags, R, nil); + end + else + begin + Inc(R.Left, 2); + if not BtnDisabled then with R do + begin + if Embedded then FillRectEx(DC, R, clBtnFace); + if BtnPressed or BtnHot then + DrawLineEx(DC, Left - 1, Top, Left - 1, Bottom + 1, ToolbarColor) + else if Embedded then + DrawLineEx(DC, Left - 1, Top, Left - 1, Bottom, clBtnShadow) + else + DrawLineEx(DC, Left - 1, Top, Left - 1, Bottom, clWindow); + DrawEnabled(R); + end; + PaintDropDownArrow(Canvas, R, ItemInfo); + end; + end + else if ButtonInfo.ButtonType = EBT_SPIN then + begin + { Paint spin buttons } + BtnDisabled := (ButtonInfo.ButtonState and EBSS_DISABLED) <> 0; + BtnHot := (ButtonInfo.ButtonState and EBSS_HOT) <> 0; + if USE_THEMES then + begin + if BtnHot then InflateRect(R, 1, 1); + + { Upper with XP themes } + BR := R; + BR.Bottom := (R.Top + R.Bottom - 1) div 2; + BtnPressed := (ButtonInfo.ButtonState and EBSS_UP) <> 0; + if BtnDisabled then StateFlags := UPS_DISABLED + else if BtnPressed then StateFlags := UPS_PRESSED + else if BtnHot then StateFlags := UPS_HOT + else StateFlags := UPS_NORMAL; + DrawThemeBackground(SPIN_THEME, Handle, SPNP_UP, StateFlags, BR, nil); + + { Lower with XP themes } + BR := R; + BR.Top := (R.Top + R.Bottom) div 2; + BtnPressed := (ButtonInfo.ButtonState and EBSS_DOWN) <> 0; + if BtnDisabled then StateFlags := DNS_DISABLED + else if BtnPressed then StateFlags := DNS_PRESSED + else if BtnHot then StateFlags := DNS_HOT + else StateFlags := DNS_NORMAL; + DrawThemeBackground(SPIN_THEME, Handle, SPNP_DOWN, StateFlags, BR, nil); + end + else + begin + Inc(R.Left, 2); + + if not BtnDisabled then with R do + if BtnPressed or BtnHot then + DrawLineEx(DC, Left - 1, Top - 1, Left - 1, Bottom + 1, ToolbarColor) + else if Embedded then + DrawLineEx(DC, Left - 1, Top, Left - 1, Bottom, clBtnShadow) + else + DrawLineEx(DC, Left - 1, Top, Left - 1, Bottom, clWindow); + + + BR := R; + BR.Bottom := (R.Top + R.Bottom + 1) div 2; + BtnPressed := (ButtonInfo.ButtonState and EBSS_UP) <> 0; + if BtnHot or BtnPressed then Dec(BR.Bottom); + if not BtnDisabled then DrawEnabled(BR); + DrawUp; + + BR := R; + BR.Top := (R.Top + R.Bottom) div 2; + BtnPressed := (ButtonInfo.ButtonState and EBSS_DOWN) <> 0; + if BtnHot or BtnPressed then Inc(BR.Top); + if not BtnDisabled then DrawEnabled(BR); + DrawDn; + end; + end; + end; +end; + +procedure TTBXDefaultTheme.PaintEditFrame(Canvas: TCanvas; + const ARect: TRect; var ItemInfo: TTBXItemInfo; const EditInfo: TTBXEditInfo); +var + R: TRect; + W: Integer; +begin + R := ARect; + PaintFrame(Canvas, R, ItemInfo); + W := EditFrameWidth; + InflateRect(R, -W, -W); + with EditInfo do if RightBtnWidth > 0 then Dec(R.Right, RightBtnWidth - 2); + Canvas.Brush.Color := clWindow; + if ItemInfo.Enabled then Canvas.FillRect(R); + with EditInfo do if LeftBtnWidth > 0 then Inc(R.Left, LeftBtnWidth - 2); + if EditInfo.RightBtnWidth > 0 then + begin + R := ARect; + InflateRect(R, -W, -W); + R.Left := R.Right - EditInfo.RightBtnWidth; + PaintEditButton(Canvas, R, ItemInfo, EditInfo.RightBtnInfo); + end; +end; + +procedure TTBXDefaultTheme.PaintDropDownArrow(Canvas: TCanvas; + const ARect: TRect; const ItemInfo: TTBXItemInfo); +var + X, Y: Integer; + + procedure Draw(AColor: TColor); + begin + Canvas.Pen.Color := AColor; + Canvas.Brush.Color := AColor; + if ItemInfo.IsVertical then Canvas.Polygon([Point(X, Y + 2), Point(X, Y - 2), Point(X - 2, Y)]) + else Canvas.Polygon([Point(X - 2, Y), Point(X + 2, Y), Point(X, Y + 2)]); + end; + +begin + with ItemInfo, ARect do + begin + X := (Left + Right) div 2; + Y := (Top + Bottom) div 2 - 1; + + if (Pushed or Selected) and (ComboPart <> cpSplitRight) then + begin + Inc(X); Inc(Y); + end; + + if Enabled then + begin + if Boolean(ItemOptions and IO_TOOLBARSTYLE) then Draw(clPopupText) + else Draw(clBtnText); + end + else + begin + Inc(X); Inc(Y); + Draw(clBtnHighlight); + Dec(X); Dec(Y); + Draw(clBtnShadow); + end; + end; +end; + +procedure TTBXDefaultTheme.PaintButton(Canvas: TCanvas; const ARect: TRect; const ItemInfo: TTBXItemInfo); +const + XPPart: array [TTBXComboPart] of Integer = (TP_BUTTON, TP_DROPDOWNBUTTON, + TP_SPLITBUTTON, TP_SPLITBUTTONDROPDOWN); + Edge: array [Boolean] of Integer = (BDR_RAISEDINNER, EDGE_RAISED); +var + R: TRect; + Flags, RegionFlags: Cardinal; + InMenuBar, ShowHover, Embedded, ShowFlatSL: Boolean; + Region: HRGN; + DC: HDC; + Brush, OldBrush: HBrush; +begin + R := ARect; + DC := Canvas.Handle; + with ItemInfo do + begin + ShowHover := (Enabled and (HoverKind <> hkNone)) or + (not Enabled and (HoverKind = hkKeyboardHover)); + + InMenuBar := (ViewType and TVT_MENUBAR) = TVT_MENUBAR; + Embedded := ((ViewType and VT_TOOLBAR) = VT_TOOLBAR) and + ((ViewType and TVT_EMBEDDED) = TVT_EMBEDDED); + + if not InMenuBar and USE_THEMES then + begin + { The support for XP themes in menus is not yet implemented since standard + XP themes seem to have no theming for menus } + + if not Enabled then + begin + if HoverKind = hkKeyboardHover then Flags := TS_HOT + else Flags := TS_DISABLED; + end + else if ItemInfo.Pushed then Flags := TS_PRESSED + else if ItemInfo.Selected then + begin + if HoverKind <> hkNone then Flags := TS_HOTCHECKED + else Flags := TS_CHECKED; + end + else if HoverKind <> hkNone then Flags := TS_HOT + else Flags := TS_NORMAL; + + if Embedded or Boolean(ItemOptions and IO_DESIGNING) then + begin + { There is no state for non-transparent normal toolbar button, trying to + simulate it with regions... } + RegionFlags := TS_HOT; + if ComboPart = cpSplitRight then Dec(R.Left); + GetThemeBackgroundRegion(TOOLBAR_THEME, Canvas.Handle, XPPart[ComboPart], RegionFlags, R, Region); + if ComboPart = cpSplitRight then Inc(R.Left); + if Embedded or not Boolean(ItemOptions and IO_DESIGNING) then + begin + Brush := CreateBrushEx(ToolbarColor); + OldBrush := SelectObject(DC, Brush); + FillRgn(DC, Region, Brush); + SelectObject(DC, OldBrush); + DeleteObject(Brush); + end; + Brush := CreateBrushEx(clBtnShadow); + OldBrush := SelectObject(DC, Brush); + FrameRgn(DC, Region, Brush, 1, 1); + SelectObject(DC, OldBrush); + DeleteObject(Brush); + DeleteObject(Region); + end; + + DrawThemeBackground(TOOLBAR_THEME, DC, XPPart[ComboPart], Flags, R, nil); + end + else + begin + if InMenuBar and USE_FLATMENUS then + begin + if ((Pushed or Selected) and Enabled) or ShowHover then + FillRectEx(DC, R, clHighlight); + Exit; + end; +{$IFDEF NARROWCOMBOBUTTON} + if (ItemInfo.ComboPart = cpSplitRight) and not (InMenuBar or USE_THEMES) then Dec(R.Right, 2); +{$ENDIF} + if USE_FLATMENUS and (((Pushed or Selected) and Enabled) or ShowHover) then + FillRectEx(DC, R, ToolbarColor); + if Embedded then with Canvas do + begin + Flags := BF_RECT or BF_MIDDLE or BF_ADJUST; + if not ShowHover or (Pushed or Selected or not Enabled) then Flags := Flags or BF_FLAT; + ShowFlatSL := (ComboPart = cpSplitLeft) and not (ShowHover or Pushed); + if ShowFlatSL then Inc(R.Right); + Windows.DrawEdge(Handle, R, EDGE_RAISED, Flags); + if Selected and Enabled and (HoverKind = hkNone) then + DitherRect(DC, R, ToolbarColor, clBtnHighlight); + if ShowFlatSL then Dec(R.Right); + end + else if (Pushed or Selected) and Enabled then with Canvas do + begin + Windows.DrawEdge(Handle, R, BDR_SUNKENOUTER, BF_RECT or BF_ADJUST); + if not Pushed and (HoverKind = hkNone) then + DitherRect(DC, R, ToolbarColor, clBtnHighlight); + end + else if ShowHover or Boolean(ItemOptions and IO_DESIGNING) then + Windows.DrawEdge(Canvas.Handle, R, BDR_RAISEDINNER, BF_RECT); + if ComboPart = cpSplitRight then PaintDropDownArrow(Canvas, R, ItemInfo); + end; + end; +end; + +procedure TTBXDefaultTheme.PaintFloatingBorder(Canvas: TCanvas; const ARect: TRect; const WindowInfo: TTBXWindowInfo); +const + SPI_GETGRADIENTCAPTIONS = $1008; + DC_GRADIENT = $20; + ActiveCaptionFlags: array [Boolean] of Integer = (0, DC_ACTIVE); + GradientCaptionFlags: array [Boolean] of Integer = (0, DC_GRADIENT); + CaptionBkColors: array [Boolean, Boolean] of Integer = + ((COLOR_INACTIVECAPTION, COLOR_ACTIVECAPTION), + (COLOR_GRADIENTINACTIVECAPTION, COLOR_GRADIENTACTIVECAPTION)); + ButtonStateFlags: array [Boolean] of Integer = (0, DFCS_PUSHED); +var + R, R2: TRect; + DC: HDC; + Flags: Integer; + Gradient, ShowCloseBtn: Boolean; + B: BOOL; +begin + DC := Canvas.Handle; + + with WindowInfo do + if not USE_THEMES then + begin + R := ARect; + if (WRP_BORDER and RedrawPart) <> 0 then + begin + R2 := R; + with FloatingBorderSize do InflateRect(R2, -X, -Y); + SaveDC(DC); + with R2 do ExcludeClipRect(DC, Left, Top, Right, Bottom); + Windows.DrawEdge(DC, R, EDGE_RAISED, BF_RECT or BF_MIDDLE); + RestoreDC(DC, -1); + end; + + if not WindowInfo.ShowCaption then Exit; + Gradient := SystemParametersInfo(SPI_GETGRADIENTCAPTIONS, 0, @B, 0) and B; + ShowCloseBtn := (CDBS_VISIBLE and CloseButtonState) <> 0; + R := GetTBXCloseButtonRect(WindowInfo, True); + + if (WRP_CAPTION and RedrawPart) <> 0 then + begin + if ShowCloseBtn then + begin + SaveDC(DC); + with R do ExcludeClipRect(DC, Left, Top, Right, Bottom); + end; + R2 := GetTBXCaptionRect(WindowInfo, True, ShowCloseBtn); + DrawCaption(ParentHandle, DC, R2, DC_TEXT or DC_SMALLCAP or + ActiveCaptionFlags[Active] or GradientCaptionFlags[Gradient]); + if ShowCloseBtn then RestoreDC(DC, -1); + R2 := GetTBXCaptionRect(WindowInfo, True, False); + R2.Top := R2.Bottom; + Inc(R2.Bottom); + FillRect(DC, R2, GetSysColorBrush(COLOR_BTNFACE)); + end; + + if ShowCloseBtn then + begin + R2 := R; + InflateRect(R2, -2, -2); + if (WRP_CAPTION and RedrawPart) <> 0 then + begin + SaveDC(DC); + with R2 do ExcludeClipRect(DC, Left, Top, Right, Bottom); + FillRect(DC, R, GetSysColorBrush(CaptionBkColors[Gradient, WindowInfo.Active])); + RestoreDC(DC, -1); + end; + if (WRP_CLOSEBTN and RedrawPart) <> 0 then + DrawFrameControl(DC, R2, DFC_CAPTION, DFCS_CAPTIONCLOSE or + ButtonStateFlags[(CDBS_PRESSED and CloseButtonState) <> 0]); + end; + end + else { Use WindowsXP visual styles } + begin + if (WRP_BORDER and RedrawPart) <> 0 then + begin + if Active then Flags := FS_ACTIVE else Flags := FS_INACTIVE; + R := ARect; + R.Top := R.Bottom - FloatingBorderSize.Y; + DrawThemeBackground(WINDOW_THEME, DC, WP_SMALLFRAMEBOTTOM, Flags, R, nil); + R.Top := ARect.Top; + R.Bottom := R.Top + FloatingBorderSize.Y; + {if WindowInfo.ShowCaption then} { TODO : how to paint a captionless window frame } + Inc(R.Bottom, GetSystemMetrics(SM_CYSMCAPTION)); + DrawThemeBackground(WINDOW_THEME, DC, WP_SMALLCAPTION, Flags, R, nil); + R.Top := R.Bottom; + R.Bottom := ARect.Bottom - FloatingBorderSize.Y; + R.Right := R.Left + FloatingBorderSize.X; + DrawThemeBackground(WINDOW_THEME, DC, WP_SMALLFRAMELEFT, Flags, R, nil); + R.Right := ARect.Right; + R.Left := R.Right - FloatingBorderSize.X; + DrawThemeBackground(WINDOW_THEME, DC, WP_SMALLFRAMERIGHT, Flags, R, nil); + end; + + if not ShowCaption then Exit; + + { Get the caption area } + R := ARect; + with FloatingBorderSize do InflateRect(R, -X, -Y); + Dec(R.Bottom, ClientHeight); + + if (WRP_CAPTION and RedrawPart) <> 0 then + begin + R2 := R; + if ((CDBS_VISIBLE and CloseButtonState) <> 0) and ((WRP_CLOSEBTN and RedrawPart) <> 0) then + Dec(R2.Right, GetSystemMetrics(SM_CYSMCAPTION)); + + Canvas.Font.Assign(SmCaptionFont); + if Active then Canvas.Font.Color := clCaptionText + else Canvas.Font.Color := clInactiveCaptionText; + Canvas.Brush.Style := bsClear; + + { This is strange... the DrawThemeText function refuses to work... + Use standard API... } + DrawText(Canvas.Handle, WindowInfo.Caption, -1, R2, + DT_SINGLELINE or DT_VCENTER or DT_END_ELLIPSIS or DT_HIDEPREFIX); + + Canvas.Brush.Style := bsSolid; + end; + + if (CDBS_VISIBLE and CloseButtonState) <> 0 then + begin + Dec(R.Bottom); + R.Left := R.Right - R.Bottom + R.Top; + InflateRect(R, -2, -2); + if (CDBS_PRESSED and CloseButtonState) <> 0 then Flags := CBS_PUSHED + else if (CDBS_HOT and CloseButtonState) <> 0 then Flags := CBS_HOT + else Flags := CBS_NORMAL; + DrawThemeBackground(WINDOW_THEME, DC, WP_SMALLCLOSEBUTTON, Flags, R, nil); + end; + end; +end; + +procedure TTBXDefaultTheme.PaintFrame(Canvas: TCanvas; const ARect: TRect; const ItemInfo: TTBXItemInfo); +var + DC: HDC; + R: TRect; + E, Embedded: Boolean; + Flags, Border: Integer; + C: TColor; +begin + R := ARect; + DC := Canvas.Handle; + with ItemInfo do + begin + E := (Enabled and (HoverKind <> hkNone)) or + (not Enabled and (HoverKind = hkKeyboardHover)); + Embedded := ((ViewType and VT_TOOLBAR) = VT_TOOLBAR) and + ((ViewType and TVT_EMBEDDED) = TVT_EMBEDDED); + if USE_THEMES then + begin + InflateRect(R, -1, -1); + if Embedded then C := clBtnShadow + else C := ToolbarColor; + FrameRectEx(DC, R, C, False); + InflateRect(R, 1, 1); + if Pushed or Selected or E or ((ItemOptions and IO_DESIGNING) <> 0) + then DrawThemeBackground(COMBO_THEME, DC, 0, 0, R, nil); + InflateRect(R, -2, -2); + FrameRectEx(DC, R, clWindow, False); + end + else + begin + if Embedded then + begin + Flags := BF_RECT; + if not (Pushed or Selected or E) then + begin + InflateRect(R, -1, -1); + Flags := Flags or BF_FLAT; + Border := BDR_SUNKENOUTER; + end + else Border := EDGE_SUNKEN; + Windows.DrawEdge(DC, R, Border, Flags); + if (Pushed or Selected or E) then InflateRect(R, -1, -1); + end + else + begin + if Pushed or Selected or E or ((ItemOptions and IO_DESIGNING) <> 0) then + Windows.DrawEdge(DC, R, BDR_SUNKENOUTER, BF_RECT); + InflateRect(R, -1, -1); + FrameRectEx(DC, R, ToolbarColor, True); + FrameRectEx(DC, R, clWindow, False); + end; + end; + end; +end; + +function TTBXDefaultTheme.GetImageOffset(Canvas: TCanvas; const ItemInfo: TTBXItemInfo; + ImageList: TCustomImageList): TPoint; +const + Offsets: array [Boolean] of TPoint = ((X:0; Y:0), (X:1; Y:1)); +begin + with ItemInfo do + Result := Offsets[Pushed or Selected]; +end; + +procedure TTBXDefaultTheme.PaintImage(Canvas: TCanvas; ARect: TRect; + const ItemInfo: TTBXItemInfo; ImageList: TCustomImageList; ImageIndex: Integer); +var + BgColor: TColor; + HiContrast: Boolean; + IsMenuItem: Boolean; +begin + with ItemInfo do + begin + if ImageList is TTBCustomImageList then + begin + if Pushed or Selected then OffsetRect(ARect, 1, 1); + TTBCustomImageList(ImageList).DrawState(Canvas, ARect.Left, ARect.Top, + ImageIndex, Enabled, (HoverKind <> hkNone), Selected); + Exit; + end; + + IsMenuItem := ((ViewType and PVT_POPUPMENU) = PVT_POPUPMENU) and + ((ItemOptions and IO_TOOLBARSTYLE) = 0); + + if (IsMenuItem and USE_FLATMENUS) or (not IsMenuItem and USE_THEMES) then + begin + { The icon painting here is not really made by the uxtheme.dll, this is + just a simulation until I figure out how to work with DrawThemedIcon function } + if Pushed or Selected then OffsetRect(ARect, 1, 1); + BgColor := GetItemImageBackground(ItemInfo); + HiContrast := not IsMenuItem and IsDarkColor(BGColor); + if not Enabled then + DrawTBXIconShadow(Canvas, ARect, ImageList, ImageIndex, 0) + else if Selected or Pushed or (HoverKind <> hkNone) then + DrawTBXIcon(Canvas, ARect, ImageList, ImageIndex, HiContrast) + else if HiContrast or TBXHiContrast or TBXLoColor then + DrawTBXIcon(Canvas, ARect, ImageList, ImageIndex, HiContrast) + else + HighlightTBXIcon(Canvas, ARect, ImageList, ImageIndex, clWindow, 178); + end + else + begin + if Pushed or Selected then OffsetRect(ARect, 1, 1); + ImageList.Draw(Canvas, ARect.Left, ARect.Top, ImageIndex, Enabled); + end; + end; +end; + +procedure TTBXDefaultTheme.PaintMDIButton(Canvas: TCanvas; ARect: TRect; + const ItemInfo: TTBXItemInfo; ButtonKind: Cardinal); +const + PushedFlags: array[Boolean] of UINT = (0, DFCS_PUSHED); +var + XPPart, XPFlags: Cardinal; +begin + if USE_THEMES then + begin + case ButtonKind of + DFCS_CAPTIONMIN: XPPart := WP_MDIMINBUTTON; + DFCS_CAPTIONRESTORE: XPPart := WP_MDIRESTOREBUTTON; + DFCS_CAPTIONCLOSE: XPPart := WP_MDICLOSEBUTTON; + else + XPPart := 0; + end; + if ItemInfo.Pushed then XPFlags := CBS_PUSHED + else if ItemInfo.HoverKind <> hkNone then XPFlags := CBS_HOT + else XPFlags := CBS_NORMAL; + DrawThemeBackground(WINDOW_THEME, Canvas.Handle, XPPart, XPFLags, ARect, nil); + end + else + begin + DrawFrameControl(Canvas.Handle, ARect, DFC_CAPTION, + ButtonKind or PushedFlags[ItemInfo.Pushed]); + end; +end; + +procedure TTBXDefaultTheme.PaintMenuItemFrame(Canvas: TCanvas; + const ARect: TRect; const ItemInfo: TTBXItemInfo); +var + DC: HDC; +begin + DC := Canvas.Handle; + with ItemInfo do if (Enabled and (HoverKind <> hkNone)) or + (not Enabled and (HoverKind = hkKeyboardHover)) then + FillRectEx(DC, ARect, clHighlight); +end; + +procedure TTBXDefaultTheme.PaintMenuItem(Canvas: TCanvas; const ARect: TRect; var ItemInfo: TTBXItemInfo); +var + DC: HDC; + R: TRect; + ShowImageOrCheck: Boolean; + ShowHover: Boolean; + IsComboItem: Boolean; + X, Y: Integer; + ArrowWidth: Integer; + + procedure DrawArrow(AColor: TColor); + begin + PolygonEx(DC, [Point(X, Y - 3), Point(X, Y + 3), Point(X + 3, Y)], AColor, AColor); + end; + +begin + DC := Canvas.Handle; + with ItemInfo do + begin + ShowImageOrCheck := (ImageWidth > 0) or Selected; + ShowHover := (Enabled and (HoverKind <> hkNone)) or + (not Enabled and (HoverKind = hkKeyboardHover)); + ArrowWidth := GetSystemMetrics(SM_CXMENUCHECK); + + R := ARect; + if ShowImageOrCheck then Inc(R.Left, ItemInfo.PopupMargin + MenuImageTextSpace); + IsComboItem := ((ItemOptions and IO_COMBO) <> 0); + if IsComboItem and Enabled then Dec(R.Right, ArrowWidth); + + PaintMenuItemFrame(Canvas, R, ItemInfo); + + if IsComboItem then + begin + R.Left := ARect.Right - ArrowWidth; + R.Right := ARect.Right; + if Enabled and (HoverKind <> hkNone) then + Windows.DrawEdge(DC, R, BDR_SUNKENOUTER, BF_RECT) + else + begin + Dec(R.Left); + if not ShowHover then DrawEdge(DC, R, EDGE_ETCHED, BF_LEFT) + else DrawEdge(DC, R, BDR_SUNKENOUTER, BF_LEFT); + end; + end; + + if (ItemOptions and IO_SUBMENUITEM) <> 0 then + begin + Y := ARect.Bottom div 2; + X := ARect.Right - ArrowWidth * 2 div 3 - 2; + if not Enabled then + begin + if HoverKind = hkKeyboardHover then DrawArrow(clBtnShadow) + else + begin + Inc(X); Inc(Y); + DrawArrow(clBtnHighlight); + Dec(X); Dec(Y); + DrawArrow(clBtnShadow); + end; + end + else if (HoverKind <> hkNone) and not IsComboItem then DrawArrow(clHighlightText) + else DrawArrow(clPopupText); + end; + + if Enabled and ShowImageOrCheck and ((HoverKind <> hkNone) or Selected) then + begin + R.Left := ARect.Left; + R.Right := R.Left + ItemInfo.PopupMargin; + if USE_FLATMENUS then FillRectEx(DC, R, ToolbarColor); + PaintButton(Canvas, R, ItemInfo); + end; + end; +end; + +procedure TTBXDefaultTheme.PaintPopupNCArea(Canvas: TCanvas; R: TRect; const PopupInfo: TTBXPopupInfo); +var + DC: HDC; +begin + DC := Canvas.Handle; + +{$IFNDEF OFFICE2K_COMBOS} + if (PopupInfo.ViewType and PVT_LISTBOX) = PVT_LISTBOX then + begin + FrameRectEx(DC, R, clWindowFrame, True); + FrameRectEx(DC, R, clWindow, True); + FrameRectEx(DC, R, clWindow, False); + end + else +{$ENDIF} + if USE_FLATMENUS and ((PopupInfo.ViewType and PVT_TOOLBOX) <> PVT_TOOLBOX) then + begin + FrameRectEx(DC, R, clBtnShadow, True); + FrameRectEx(DC, R, clPopup, True); + FrameRectEx(DC, R, clPopup, False); + end + else if (PopupInfo.ViewType and PVT_TOOLBOX) = PVT_TOOLBOX then + begin + Windows.DrawEdge(DC, R, EDGE_RAISED, BF_RECT or BF_ADJUST); + FrameRectEx(DC, R, ToolbarColor, False); + end + else + begin + Windows.DrawEdge(DC, R, EDGE_RAISED, BF_RECT or BF_ADJUST); + FrameRectEx(DC, R, clPopup, False); + end; +end; + +procedure TTBXDefaultTheme.PaintSeparator(Canvas: TCanvas; ARect: TRect; + ItemInfo: TTBXItemInfo; Horizontal, LineSeparator: Boolean); +const + XPFlags: array [Boolean] of Integer = (TP_SEPARATOR, TP_SEPARATORVERT); +var + D: Integer; +begin + { Note: for blank separators, Enabled = False } + with ItemInfo, ARect do if Enabled then + begin + if not USE_THEMES or ((ViewType and PVT_POPUPMENU) = PVT_POPUPMENU) then + begin + D := 0; + if LineSeparator then + if (ViewType and TVT_FLOATING) <> 0 then D := 1 + else D := 4; + + if Horizontal then + begin + if (ItemOptions and IO_TOOLBARSTYLE) = 0 then D := 12; + Top := (Top + Bottom) div 2 - 1; + Inc(Left, D); Dec(Right, D); + Windows.DrawEdge(Canvas.Handle, ARect, EDGE_ETCHED, BF_TOP); + end + else + begin + Left := (Left + Right) div 2 - 1; + Inc(Top, D); Dec(Bottom, D); + Windows.DrawEdge(Canvas.Handle, ARect, EDGE_ETCHED, BF_LEFT); + end; + end + else + DrawThemeBackground(TOOLBAR_THEME, Canvas.Handle, XPFlags[Horizontal], TS_NORMAL, ARect, nil); + end; +end; + +procedure TTBXDefaultTheme.PaintToolbarNCArea(Canvas: TCanvas; R: TRect; const ToolbarInfo: TTBXToolbarInfo); +const + DragHandleSizes: array [Boolean, DHS_DOUBLE..DHS_SINGLE] of Integer = ((9, 0, 6), (14, 14, 14)); + DragHandleOffsets: array [Boolean, DHS_DOUBLE..DHS_SINGLE] of Integer = ((2, 0, 2), (3, 0, 5)); + GripperPart: array [Boolean] of Cardinal = (RP_GRIPPER, RP_GRIPPERVERT); + Pattern: array [0..15] of Byte = (0, 0, $CC, 0, $78, 0, $30, 0, $78, 0, $CC, 0, 0, 0, 0, 0); +var +// DC: HDC; + DHSize: Integer; +// Sz: TSize; + R2: TRect; + Flags: Cardinal; + Z: Integer; + BtnVisible, Horz, CloseButtondown, CloseButtonHover: Boolean; +begin +{ DC := Canvas.Handle; + if ToolbarInfo.EffectiveColor <> clNone then FillRectEx(DC, R, ToolbarInfo.EffectiveColor); } + Canvas.FillRect(R); + + { Border } + if ToolbarInfo.BorderStyle = bsSingle then + if USE_THEMES then + begin + Frame3D(Canvas.Handle, R, Lighten(ToolbarInfo.EffectiveColor, 24), Lighten(ToolbarInfo.EffectiveColor, -32), False); +// DrawThemeEdge(TOOLBAR_THEME, Canvas.Handle, RP_BAND, 0, R, BDR_RAISEDINNER, BF_RECT or BF_ADJUST, @R) + end + else + Windows.DrawEdge(Canvas.Handle, R, BDR_RAISEDINNER, BF_RECT or BF_ADJUST); + + if not ToolbarInfo.AllowDrag then Exit; + + BtnVisible := (ToolbarInfo.CloseButtonState and CDBS_VISIBLE) <> 0; + Horz := not ToolbarInfo.IsVertical; + + DHSize := GetTBXDragHandleSize(ToolbarInfo); + if Horz then R.Right := R.Left + DHSize + else R.Bottom := R.Top + DHSize; + + { Drag handle area } + if ToolbarInfo.DragHandleStyle <> DHS_NONE then + begin + if USE_THEMES then + begin + R2 := R; + if BtnVisible then + if Horz then Inc(R2.Top, DHSize - 1) + else Dec(R2.Right, DHSize - 1); + + { Since GetThemePartSize does not seem to work properly, assume we use default + WindowsXP themes where the gripper pattern repeats itself every 4 pixels } + + if Horz then + begin + R2.Left := (R2.Left + R2.Right - 6) div 2; + R2.Right := R2.Left + 6; + Z := R2.Bottom - R2.Top; + R2.Top := R2.Top - 1 + (Z and $3) shr 1; + R2.Bottom := R2.Top + Z and not $3 + 1; + end + else + begin + R2.Top := (R2.Top + R2.Bottom - 6) div 2; + R2.Bottom := R2.Top + 6; + Z := R2.Right - R2.Left; + R2.Left := R2.Left - 1 + (Z and $3) shr 1; + R2.Right := R2.Left + Z and not $3 + 2; + end; + + DrawThemeBackground(REBAR_THEME, Canvas.Handle, GripperPart[ToolbarInfo.IsVertical], 0, R2, nil) + end + else + begin + R2 := R; + if Horz then + begin + Inc(R2.Left, DragHandleOffsets[BtnVisible, ToolbarInfo.DragHandleStyle]); + if BtnVisible then Inc(R2.Top, DHSize - 2); + R2.Right := R2.Left + 3; + InflateRect(R2, 0, -1); + end + else + begin + Inc(R2.Top, DragHandleOffsets[BtnVisible, ToolbarInfo.DragHandleStyle]); + if BtnVisible then Dec(R2.Right, DHSize - 2); + R2.Bottom := R2.Top + 3; + InflateRect(R2, -1, 0); + end; + + Windows.DrawEdge(Canvas.Handle, R2, BDR_RAISEDINNER, BF_RECT); + Canvas.Pixels[R2.Left, R2.Bottom - 1] := clBtnHighlight; + if ToolbarInfo.DragHandleStyle = DHS_DOUBLE then + begin + if Horz then OffsetRect(R2, 3, 0) + else OffsetRect(R2, 0, 3); + Windows.DrawEdge(Canvas.Handle, R2, BDR_RAISEDINNER, BF_RECT); + Canvas.Pixels[R2.Left, R2.Bottom - 1] := clBtnHighlight; + end; + end; + end; + + { Close Button } + if BtnVisible then + begin + CloseButtonDown := (ToolbarInfo.CloseButtonState and CDBS_PRESSED) <> 0; + CloseButtonHover := (ToolbarInfo.CloseButtonState and CDBS_HOT) <> 0; + R2 := GetTBXDockedCloseButtonRect(ToolbarInfo); + Z := 2; + if USE_THEMES then Z := 1; + if Horz then + begin + Dec(R2.Bottom, Z); + Dec(R2.Right, Z); + end + else + begin + Dec(R2.Bottom, Z); + Inc(R2.Left, Z); + end; + if USE_THEMES then + begin + Flags := TS_NORMAL; + if CloseButtonDown then Flags := TS_PRESSED + else if CloseButtonHover then Flags := TS_HOT; + DrawThemeBackground(TOOLBAR_THEME, Canvas.Handle, TP_BUTTON, Flags, R2, nil); + if CloseButtonDown then OffsetRect(R2, 1, 1); + DrawGlyph(Canvas.Handle, R2, 7, 7, Pattern[0], clBtnText); + end + else + begin + if CloseButtonDown then + begin + Windows.DrawEdge(Canvas.Handle, R2, BDR_SUNKENOUTER, BF_RECT); + OffsetRect(R2, 1, 1); + end + else if CloseButtonHover then + Windows.DrawEdge(Canvas.Handle, R2, BDR_RAISEDINNER, BF_RECT); + DrawGlyph(Canvas.Handle, R2, 7, 7, Pattern[0], clBtnText); + end; + end; +end; + +procedure TTBXDefaultTheme.PaintDock(Canvas: TCanvas; const ClientRect, DockRect: TRect; DockPosition: Integer); +var + R: TRect; +begin + if not USE_THEMES then Exit; + if DockPosition in [DP_LEFT, DP_RIGHT] then + begin + R := DockRect; + Inc(R.Bottom, 1); + DrawThemeBackground(REBAR_THEME, Canvas.Handle, 0, 0, R, nil); + end + else DrawThemeBackground(REBAR_THEME, Canvas.Handle, 0, 0, DockRect, nil); +end; + +procedure TTBXDefaultTheme.PaintDockPanelNCArea(Canvas: TCanvas; R: TRect; const DockPanelInfo: TTBXDockPanelInfo); +var + DC: HDC; + Sz: Integer; + R2: TRect; + Flags: Integer; + CloseButtonDown, CloseButtonHover: Boolean; + + procedure CaptionFill(R: TRect); + const + GRAD: array [Boolean] of TGradientKind = (gkHorz, gkVert); + begin + if USE_THEMES then + GradFill(DC, R, Lighten(ToolbarColor, 12), Lighten(ToolbarColor, -12), GRAD[DockPanelInfo.IsVertical]) + else + FillRectEx(DC, R, ToolbarColor); + end; + +begin + DC := Canvas.Handle; + with Canvas, DockPanelInfo do + begin + Sz := GetSystemMetrics(SM_CYSMCAPTION); + + { Border } + FrameRectEx(DC, R, ToolbarColor, True); + R2 := R; + if ShowCaption then + if IsVertical then Inc(R2.Top, Sz) + else Inc(R2.Left, Sz); + FrameRectEx(DC, R2, clWindow, False); + + if not ShowCaption then Exit; + + { Caption area } + if IsVertical then R.Bottom := R.Top + Sz + else R.Right := R.Left + Sz; + Windows.DrawEdge(Handle, R, BDR_RAISEDINNER, BF_RECT or BF_ADJUST); + + { Close button } + if (CDBS_VISIBLE and CloseButtonState) <> 0 then + begin + CloseButtonDown := (CloseButtonState and CDBS_PRESSED) <> 0; + CloseButtonHover := (CloseButtonState and CDBS_HOT) <> 0; + R2 := R; + Brush.Color := ToolbarColor; + if IsVertical then + begin + R2.Left := R2.Right - Sz; + R.Right := R2.Left; + CaptionFill(R2); + InflateRect(R2, -1, -1); + Inc(R2.Left); + end + else + begin + R2.Top := R2.Bottom - Sz; + R.Bottom := R2.Top; + CaptionFill(R2); + InflateRect(R2, -1, -1); + Dec(R2.Bottom); + end; + + if USE_THEMES then + begin + Flags := TS_NORMAL; + if CloseButtonDown then Flags := TS_PRESSED + else if CloseButtonHover then Flags := TS_HOT; + DrawThemeBackground(TOOLBAR_THEME, DC, TP_BUTTON, Flags, R2, nil); + if CloseButtonDown then OffsetRect(R2, 1, 1); + InflateRect(R2, -2, -2); + end + else + begin + if CloseButtonDown then + begin + Windows.DrawEdge(DC, R2, BDR_SUNKENOUTER, BF_RECT); + OffsetRect(R2, 1, 1); + end + else if CloseButtonHover then + Windows.DrawEdge(DC, R2, BDR_RAISEDINNER, BF_RECT); + InflateRect(R2, -2, -2); + end; + DrawButtonBitmap(Canvas, R2); + end; + + { Caption } + CaptionFill(R); + if IsVertical then InflateRect(R, -2, 0) + else Inflaterect(R, 0, -2); + Font.Assign(SmCaptionFont); + Font.Color := clBtnText; + Brush.Style := bsClear; + Flags := DT_SINGLELINE or DT_VCENTER or DT_END_ELLIPSIS or DT_NOPREFIX; + if IsVertical then DrawText(Canvas.Handle, Caption, -1, R, Flags) + else DrawRotatedText(Canvas.Handle, string(Caption), R, Flags); + Brush.Style := bsSolid; + end; +end; + +function TTBXDefaultTheme.GetPopupShadowType: Integer; +begin + Result := PST_WINDOWSXP; +end; + +procedure TTBXDefaultTheme.GetViewMargins(ViewType: Integer; out Margins: TTBXMargins); +begin + with Margins do + if ((ViewType and VT_TOOLBAR) = VT_TOOLBAR) and + ((ViewType and TVT_FLOATING) = TVT_FLOATING) then + begin + LeftWidth := 4; + TopHeight := 2; + RightWidth := 4; + BottomHeight := 1; + end + else + begin + LeftWidth := 0; + TopHeight := 0; + RightWidth := 0; + BottomHeight := 0; + end; +end; + +procedure TTBXDefaultTheme.PaintPageScrollButton(Canvas: TCanvas; + const ARect: TRect; ButtonType: Integer; Hot: Boolean); +var + R: TRect; + Flags: Integer; + X, Y, Sz: Integer; +begin + R := ARect; + if USE_THEMES then + begin + if Hot then Flags := TS_PRESSED + else Flags := TS_HOT; + DrawThemeBackground(TOOLBAR_THEME, Canvas.Handle, TP_BUTTON, Flags, ARect, nil); + X := (R.Left + R.Right) div 2; + Y := (R.Top + R.Bottom) div 2; + Sz := Min(X - R.Left, Y - R.Top) * 3 div 4; + if Hot then Canvas.Pen.Color := clBtnText; + Canvas.Brush.Color := Canvas.Pen.Color; + case ButtonType of + PSBT_UP: + begin + Inc(Y, Sz div 2); + Canvas.Polygon([Point(X + Sz, Y), Point(X, Y - Sz), Point(X - Sz, Y)]); + end; + PSBT_DOWN: + begin + Y := (R.Top + R.Bottom - 1) div 2; + Dec(Y, Sz div 2); + Canvas.Polygon([Point(X + Sz, Y), Point(X, Y + Sz), Point(X - Sz, Y)]); + end; + PSBT_LEFT: + begin + Inc(X, Sz div 2); + Canvas.Polygon([Point(X, Y + Sz), Point(X - Sz, Y), Point(X, Y - Sz)]); + end; + PSBT_RIGHT: + begin + X := (R.Left + R.Right - 1) div 2; + Dec(X, Sz div 2); + Canvas.Polygon([Point(X, Y + Sz), Point(X + Sz, Y), Point(X, Y - Sz)]); + end; + end; + end + else + begin + if Hot then Flags := DFCS_FLAT + else Flags := 0; + case ButtonType of + PSBT_UP: Flags := Flags or DFCS_SCROLLUP; + PSBT_DOWN: Flags := Flags or DFCS_SCROLLDOWN; + PSBT_LEFT: Flags := Flags or DFCS_SCROLLLEFT; + PSBT_RIGHT: Flags := Flags or DFCS_SCROLLRIGHT; + end; + Windows.DrawFrameControl(Canvas.Handle, R, DFC_SCROLL, Flags); + end; +end; + +procedure TTBXDefaultTheme.PaintFrameControl(Canvas: TCanvas; R: TRect; Kind, State: Integer; Params: Pointer); +var + DC: HDC; + X, Y, Flags: Integer; + C: TColor; + Pen, OldPen: HPen; + Brush, OldBrush: HBrush; + + function FrameColor: TColor; + begin + if Boolean(State and PFS_DISABLED) then Result := clBtnShadow + else if Boolean(State and (PFS_PUSHED or PFS_HOT)) then Result := clNone + else Result := clBtnShadow; + end; + + procedure DiagLine(C: TColor); + begin + with R do + DrawLineEx(DC, Right - 2 - X, Bottom - 2, Right - 1, Bottom - X - 3, C); + Inc(X); + end; + +begin + DC := Canvas.Handle; + case Kind of + PFC_CHECKBOX: + begin + if USE_THEMES then + begin + if Boolean(State and PFS_CHECKED) then Flags := CBS_CHECKEDNORMAL + else if Boolean(State and PFS_MIXED) then Flags := CBS_MIXEDNORMAL + else Flags := CBS_UNCHECKEDNORMAL; + if Boolean(State and PFS_DISABLED) then Inc(Flags, 3) + else if Boolean(State and PFS_PUSHED) then Inc(Flags, 2) + else if Boolean(State and PFS_HOT) then Inc(Flags); + DrawThemeBackground(BUTTON_THEME, DC, BP_CHECKBOX, Flags, R, nil); + end + else + begin + C := FrameColor; + if C = clNone then + begin + if Boolean(State and PFS_MIXED) then Flags := DFCS_BUTTON3STATE or DFCS_CHECKED + else Flags := DFCS_BUTTONCHECK; + if Boolean(State and PFS_CHECKED) then Flags := Flags or DFCS_CHECKED; + if Boolean(State and PFS_PUSHED) then Flags := Flags or DFCS_PUSHED; + DrawFrameControl(DC, R, DFC_BUTTON, Flags); + end + else + begin + InflateRect(R, -1, -1); + FrameRectEx(DC, R, C, True); + if Boolean(State and (PFS_DISABLED or PFS_PUSHED)) then FillRectEx(DC, R, clBtnFace) + else if Boolean(State and PFS_MIXED) then DitherRect(DC, R, clWindow, clBtnFace) + else FillRectEx(DC, R, clWindow); + + if Boolean(State and (PFS_CHECKED or PFS_MIXED)) then + begin + X := (R.Left + R.Right) div 2 - 1; + Y := (R.Top + R.Bottom) div 2 + 1; + if Boolean(State and PFS_DISABLED) then C := clGrayText + else if Boolean(State and PFS_MIXED) then C := clBtnShadow + else C := clBtnText; + PolygonEx(DC, [Point(X-2, Y), Point(X, Y+2), Point(X+4, Y-2), + Point(X+4, Y-4), Point(X, Y), Point(X-2, Y-2), Point(X-2, Y)], C, C); + end; + end; + end; + end; + PFC_RADIOBUTTON: + begin + if USE_THEMES then + begin + if Boolean(State and PFS_CHECKED) then Flags := RBS_CHECKEDNORMAL + else Flags := RBS_UNCHECKEDNORMAL; + if Boolean(State and PFS_DISABLED) then Inc(Flags, 3) + else if Boolean(State and PFS_PUSHED) then Inc(Flags, 2) + else if Boolean(State and PFS_HOT) then Inc(Flags); + DrawThemeBackground(BUTTON_THEME, DC, BP_RADIOBUTTON, Flags, R, nil); + end + else + begin + C := FrameColor; + if C = clNone then + begin + Flags := DFCS_BUTTONRADIO; + if Boolean(State and PFS_CHECKED) then Flags := Flags or DFCS_CHECKED; + if Boolean(State and PFS_PUSHED) then Flags := Flags or DFCS_PUSHED; + DrawFrameControl(DC, R, DFC_BUTTON, Flags); + end + else + begin + Pen := CreatePenEx(C); + if Boolean(State and (PFS_DISABLED or PFS_PUSHED)) then C := clBtnFace + else C := clWindow; + Brush := CreateBrushEx(C); + + InflateRect(R, -1, -1); Inc(R.Left); Dec(R.Bottom); + OldPen := SelectObject(DC, Pen); + OldBrush := SelectObject(DC, Brush); + with R do + Windows.RoundRect(DC, Left, Top, Right, Bottom, Right - Left - 2, Bottom - Top - 2); + SelectObject(DC, OldPen); + SelectObject(DC, OldBrush); + DeleteObject(Pen); + DeleteObject(Brush); + + if Boolean(State and PFS_CHECKED) then + begin + InflateRect(R, -3, -3); + Pen := CreatePenEx(clBtnText); + Brush := CreateBrushEx(clBtnText); + OldPen := SelectObject(DC, Pen); + OldBrush := SelectObject(DC, Brush); + with R do Windows.RoundRect(DC, Left, Top, Right, Bottom, Right - Left, Bottom - Top); + SelectObject(DC, OldPen); + SelectObject(DC, OldBrush); + DeleteObject(Pen); + DeleteObject(Brush); + end; + end; + end; + end; + end; +end; + +procedure TTBXDefaultTheme.PaintStatusBar(Canvas: TCanvas; R: TRect; Part: Integer); +var + DC: HDC; + D, Sz, I, Flags: Integer; + + procedure DiagLine(C: TColor); + begin + with R do + DrawLineEx(DC, Right - 2 - D, Bottom - 2, Right - 1, Bottom - D - 3, C); + Inc(D); + end; + +begin + DC := Canvas.Handle; + case Part of + SBP_BODY: + begin + if USE_THEMES then + DrawThemeBackground(STATUSBAR_THEME, DC, 0, 0, R, nil) + else + FillRectEx(DC, R, StatusBarColor); + end; + SBP_PANE, SBP_LASTPANE: + begin + if USE_THEMES then + begin + if Part = SBP_LASTPANE then Flags := SP_GRIPPERPANE + else Flags := SP_PANE; + DrawThemeBackground(STATUSBAR_THEME, DC, Flags, 0, R, nil); + end + else + begin + if Part = SBP_PANE then Dec(R.Right, 2); + Frame3D(DC, R, clBtnShadow, clBtnHighlight, False); + end; + end; + SBP_GRIPPER: + begin + if USE_THEMES then + DrawThemeBackground(STATUSBAR_THEME, DC, SP_GRIPPER, 0, R, nil) + else + begin + D := 0; + Sz := Min(R.Right - R.Left, R.Bottom - R.Top); + for I := 1 to 3 do + case Sz of + 0..8: + begin + DiagLine(clBtnShadow); + DiagLine(clBtnHighlight); + end; + 9..11: + begin + DiagLine(StatusBarColor); + DiagLine(clBtnShadow); + DiagLine(clBtnHighlight); + end; + 12..14: + begin + DiagLine(clBtnShadow); + DiagLine(clBtnShadow); + DiagLine(clBtnHighlight); + end; + else + DiagLine(StatusBarColor); + DiagLine(clBtnShadow); + DiagLine(clBtnShadow); + DiagLine(clBtnHighlight); + end; + + with Canvas, R do + begin + Pen.Color := StatusBarColor; + PolylineEx(DC, [ + Point(Right - D - 1, Bottom - 1), + Point(Right - 1, Bottom - 1), + Point(Right - 1, Bottom - D - 2)], + StatusBarColor); + end; + end; + end; + end; +end; + +procedure TTBXDefaultTheme.SetupColorCache; +begin + ToolbarColor := clBtnFace; + ToolbarText := clBtnText; + StatusBarColor := clBtnFace; + if USE_THEMES then + begin + GetThemeColor(TOOLBAR_THEME, 0, 0, TMT_FILLCOLOR, Cardinal(ToolbarColor)); + GetThemeColor(TOOLBAR_THEME, 0, 0, TMT_TEXTCOLOR, Cardinal(ToolbarText)); + GetThemeColor(STATUSBAR_THEME, 0, 0, TMT_FILLCOLOR, Cardinal(StatusBarColor)); + end; + DockPanelColor := NearestMixedColor(ToolbarColor, clWindow, 64); +end; + +procedure TTBXDefaultTheme.TBXSysCommand(var Message: TMessage); +begin + if Message.WParam = TSC_VIEWCHANGE then SetupColorCache; +end; + +initialization + InitializeStock; + +finalization + FinalizeStock; + +end. diff --git a/official/2.1.6+2.1.beta1/TBX/TBXDkPanels.pas b/official/2.1.6+2.1.beta1/TBX/TBXDkPanels.pas new file mode 100644 index 0000000..c1924f6 --- /dev/null +++ b/official/2.1.6+2.1.beta1/TBX/TBXDkPanels.pas @@ -0,0 +1,5552 @@ +unit TBXDkPanels; + +// TBX Package +// Copyright 2001-2004 Alex A. Denisov. All Rights Reserved +// See TBX.chm for license and installation instructions +// +// $Id: TBXDkPanels.pas 21 2004-05-29 22:16:01Z Alex@ZEISS $ + +interface + +{$I ..\..\Source\TB2Ver.inc} +{$I TBX.inc} + +uses + Windows, Messages, Classes, Graphics, Controls, StdCtrls, ExtCtrls, Forms, + TB2Dock, TB2Item, TBX, TBXThemes, ImgList, Menus; + +const + { New hit test constants for page scrollers } + HTSCROLLPREV = 30; + HTSCROLLNEXT = 31; + +type + { TTBXControlMargins } + + TTBXControlMargins = class(TPersistent) + private + FLeft, FTop, FRight, FBottom: Integer; + FOnChange: TNotifyEvent; + procedure SetBottom(Value: Integer); + procedure SetLeft(Value: Integer); + procedure SetRight(Value: Integer); + procedure SetTop(Value: Integer); + public + procedure Assign(Src: TPersistent); override; + procedure Modified; dynamic; + property OnChange: TNotifyEvent read FOnChange write FOnChange; + published + property Left: Integer read FLeft write SetLeft default 0; + property Top: Integer read FTop write SetTop default 0; + property Right: Integer read FRight write SetRight default 0; + property Bottom: Integer read FBottom write SetBottom default 0; + end; + + { TTBXMultiDock } + + TTBXMultiDock = class(TTBDock) + protected + LastValidRowSize: Integer; + function Accepts(ADockableWindow: TTBCustomDockableWindow): Boolean; override; + procedure ValidateInsert(AComponent: TComponent); override; + public + procedure ArrangeToolbars; override; + procedure Paint; override; + procedure ResizeVisiblePanels(NewSize: Integer); + end; + + + { TTBXCustomDockablePanel } + + TDPCaptionRotation = (dpcrAuto, dpcrAlwaysHorz, dpcrAlwaysVert); + TTBXResizingStage = (rsBeginResizing, rsResizing, rsEndResizing); + TTBXDockedResizing = procedure(Sender: TObject; Vertical: Boolean; + var NewSize: Integer; Stage: TTBXResizingStage; var AllowResize: Boolean) of object; + TDockKinds = set of (dkStandardDock, dkMultiDock); + + {TTBXDockablePanel = class(TTBCustomDockableWindow)} {vb-} + TTBXCustomDockablePanel = class(TTBCustomDockableWindow) {vb+} + private + FBorderSize: Integer; + FCaptionRotation: TDPCaptionRotation; + FDockedWidth: Integer; + FDockedHeight: Integer; + FEffectiveColor: TColor; + FFloatingWidth: Integer; + FFloatingHeight: Integer; + FHorzResizeCursor: TCursor; {vb+} + FHorzSplitCursor : TCursor; {vb+} + FIsResizing: Boolean; + FIsSplitting: Boolean; + FMinClientWidth: Integer; + FMinClientHeight: Integer; + FMaxClientWidth: Integer; + FMaxClientHeight: Integer; + FSmoothDockedResize: Boolean; + FSnapDistance: Integer; + FShowCaptionWhenDocked: Boolean; + FSplitHeight: Integer; + FSplitWidth: Integer; + FSupportedDocks: TDockKinds; + FVertResizeCursor: TCursor; {vb+} + FVertSplitCursor : TCursor; {vb+} + FOnDockedResizing: TTBXDockedResizing; + function CalcSize(ADock: TTBDock): TPoint; + procedure SetBorderSize(Value: Integer); + procedure SetCaptionRotation(Value: TDPCaptionRotation); + procedure SetDockedHeight(Value: Integer); + procedure SetDockedWidth(Value: Integer); + procedure SetFloatingHeight(Value: Integer); + procedure SetFloatingWidth(Value: Integer); + procedure SetMinClientHeight(Value: Integer); + procedure SetMinClientWidth(Value: Integer); + procedure SetShowCaptionWhenDocked(Value: Boolean); + procedure SetSnapDistance(Value: Integer); + procedure CMColorChanged(var Message: TMessage); message CM_COLORCHANGED; + procedure CMControlChange(var Message: TCMControlChange); message CM_CONTROLCHANGE; + procedure CMTextChanged(var Message: TMessage); message CM_TEXTCHANGED; + procedure TBMGetEffectiveColor(var Message: TMessage); message TBM_GETEFFECTIVECOLOR; + procedure TBMGetViewType(var Message: TMessage); message TBM_GETVIEWTYPE; + procedure TBMThemeChange(var Message: TMessage); message TBM_THEMECHANGE; + procedure WMEraseBkgnd(var Message: TWMEraseBkgnd); message WM_ERASEBKGND; + procedure WMNCHitTest(var Message: TWMNCHitTest); message WM_NCHITTEST; + procedure WMNCCalcSize(var Message: TWMNCCalcSize); message WM_NCCALCSIZE; + procedure WMNCLButtonDown(var Message: TWMNCLButtonDown); message WM_NCLBUTTONDOWN; + procedure WMSetCursor(var Message: TWMSetCursor); message WM_SETCURSOR; + procedure WMWindowPosChanged(var Message: TWMWindowPosChanged); message WM_WINDOWPOSCHANGED; + procedure SetSplitHeight(Value: Integer); + procedure SetSplitWidth(Value: Integer); + protected + BlockSizeUpdate: Boolean; + procedure AdjustClientRect(var Rect: TRect); override; + procedure BeginDockedSizing(HitTest: Integer); + procedure BeginSplitResizing(HitTest: Integer); + function CalcNCSizes: TPoint; override; + function CanAutoSize(var NewWidth, NewHeight: Integer): Boolean; override; + function CanDockTo(ADock: TTBDock): Boolean; override; + function CanSplitResize(EdgePosition: TTBDockPosition): Boolean; + procedure ConstrainedResize(var MinWidth, MinHeight, MaxWidth, MaxHeight: Integer); override; + function DoArrange(CanMoveControls: Boolean; PreviousDockType: TTBDockType; NewFloating: Boolean; NewDock: TTBDock): TPoint; override; + function DoBeginDockedResizing(Vertical: Boolean): Boolean; virtual; + function DoDockedResizing(Vertical: Boolean; var NewSize: Integer): Boolean; virtual; + function DoEndDockedResizing(Vertical: Boolean): Boolean; virtual; + procedure DrawNCArea(const DrawToDC: Boolean; const ADC: HDC; const Clip: HRGN); override; + procedure GetBaseSize(var ASize: TPoint); override; + function GetDockedCloseButtonRect(LeftRight: Boolean): TRect; override; + procedure GetDockPanelInfo(out DockPanelInfo: TTBXDockPanelInfo); virtual; + function GetFloatingWindowParentClass: TTBFloatingWindowParentClass; override; + procedure GetMinMaxSize(var AMinClientWidth, AMinClientHeight, AMaxClientWidth, AMaxClientHeight: Integer); override; + function GetViewType: Integer; + function IsVertCaption: Boolean; virtual; + procedure Loaded; override; + procedure Paint; override; + procedure SetParent(AParent: TWinControl); override; + procedure SizeChanging(const AWidth, AHeight: Integer); override; + procedure UpdateEffectiveColor; + property IsResizing: Boolean read FIsResizing; + property IsSplitting: Boolean read FIsSplitting; + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + function GetFloatingBorderSize: TPoint; override; + procedure ReadPositionData(const Data: TTBReadPositionData); override; + procedure SetBounds(ALeft, ATop, AWidth, AHeight: Integer); override; + procedure UpdateChildColors; + procedure WritePositionData(const Data: TTBWritePositionData); override; + property EffectiveColor: TColor read FEffectiveColor; + property CaptionRotation: TDPCaptionRotation read FCaptionRotation write SetCaptionRotation default dpcrAuto; + property Color default clNone; + property CloseButtonWhenDocked default True; + property DblClickUndock default False; + { client size constraints should be restored before other size related properties } + property MaxClientHeight: Integer read FMaxClientHeight write FMaxClientHeight default 0; + property MaxClientWidth: Integer read FMaxClientWidth write FMaxClientWidth default 0; + property MinClientHeight: Integer read FMinClientHeight write SetMinClientHeight default 32; + property MinClientWidth: Integer read FMinClientWidth write SetMinClientWidth default 32; + property BorderSize: Integer read FBorderSize write SetBorderSize default 0; + property DockedWidth: Integer read FDockedWidth write SetDockedWidth default 128; + property DockedHeight: Integer read FDockedHeight write SetDockedHeight default 128; + property FloatingWidth: Integer read FFloatingWidth write SetFloatingWidth default 0; + property FloatingHeight: Integer read FFloatingHeight write SetFloatingHeight default 0; + property Height stored False; + property HorzResizeCursor: TCursor read FHorzResizeCursor write FHorzResizeCursor default crSizeWE; {vb+} + property HorzSplitCursor: TCursor read FHorzSplitCursor write FHorzSplitCursor default crHSplit; {vb+} + property ShowCaptionWhenDocked: Boolean read FShowCaptionWhenDocked write SetShowCaptionWhenDocked default True; + property SplitHeight: Integer read FSplitHeight write SetSplitHeight default 0; + property SplitWidth: Integer read FSplitWidth write SetSplitWidth default 0; + property SupportedDocks: TDockKinds read FSupportedDocks write FSupportedDocks; + property SmoothDockedResize: Boolean read FSmoothDockedResize write FSmoothDockedResize default True; + property SnapDistance: Integer read FSnapDistance write SetSnapDistance default 0; + property VertResizeCursor: TCursor read FVertResizeCursor write FVertResizeCursor default crSizeNS; {vb+} + property VertSplitCursor: TCursor read FVertSplitCursor write FVertSplitCursor default crVSplit; {vb+} + property Width stored False; + property OnDockedResizing: TTBXDockedResizing read FOnDockedResizing write FOnDockedResizing; + end; {vb+} + + { TTBXDockablePanel } + + TTBXDockablePanel = class(TTBXCustomDockablePanel) {vb+} + published + { client size constraints should be restored before other size related properties } + property MaxClientHeight; + property MaxClientWidth; + property MinClientHeight; + property MinClientWidth; + + property ActivateParent; + property Align; + property Anchors; + property BorderSize; + property BorderStyle; + property Caption; + property CaptionRotation; + property Color; + property CloseButton; + property CloseButtonWhenDocked; + property CurrentDock; + property DblClickUndock; + property DefaultDock; + property DockableTo; + property DockedWidth; + property DockedHeight; + property DockMode; + property DockPos; + property DockRow; + property FloatingWidth; + property FloatingHeight; + property FloatingMode; + property Font; + property Height; + property HideWhenInactive; + property HorzResizeCursor; {vb+} + property HorzSplitCursor; {vb+} + property LastDock; + property ParentFont; + property ParentShowHint; + property PopupMenu; + property Resizable; + property ShowCaption; + property ShowCaptionWhenDocked; + property ShowHint; + property SplitHeight; + property SplitWidth; + property SupportedDocks; + property SmoothDrag; + property SmoothDockedResize; + property SnapDistance; + property TabOrder; + property UseLastDock; + property VertResizeCursor; {vb+} + property VertSplitCursor; {vb+} + property Visible; + property Width stored False; + + property OnClose; + property OnCloseQuery; + {$IFDEF JR_D5} + property OnContextPopup; + {$ENDIF} + property OnDragDrop; + property OnDragOver; + property OnDockChanged; + property OnDockChanging; + property OnDockChangingHidden; + property OnDockedResizing; + property OnMouseDown; + property OnMouseMove; + property OnMouseUp; + property OnMove; + property OnRecreated; + property OnRecreating; + property OnResize; + property OnVisibleChanged; + end; + + { TTBXPanelObject } + + TControlPaintOptions = set of (cpoDoubleBuffered); + + TTBXPanelObject = class(TCustomControl) + private + FDisableScroll: Boolean; + FMouseInControl: Boolean; + FPaintOptions: TControlPaintOptions; + FPushed: Boolean; + FSmartFocus: Boolean; + FSpaceAsClick: Boolean; + FOnMouseEnter: TNotifyEvent; + FOnMouseLeave: TNotifyEvent; + procedure CMParentColorChanged(var Message: TMessage); message CM_PARENTCOLORCHANGED; + procedure CMEnabledChanged(var Message: TMessage); message CM_ENABLEDCHANGED; + procedure MouseTimerHandler(Sender: TObject); + procedure RemoveMouseTimer; + procedure SetPaintOptions(Value: TControlPaintOptions); + procedure TBMThemeChange(var Message); message TBM_THEMECHANGE; + procedure WMEraseBkgnd(var Message: TMessage); message WM_ERASEBKGND; + procedure WMKillFocus(var Message: TMessage); message WM_KILLFOCUS; + procedure WMSetFocus(var Message: TMessage); message WM_SETFOCUS; + protected + procedure CreateParams(var Params: TCreateParams); override; + procedure DoMouseEnter; virtual; + procedure DoMouseLeave; virtual; + procedure KeyDown(var Key: Word; Shift: TShiftState); override; + procedure KeyUp(var Key: Word; Shift: TShiftState); override; + procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override; + procedure MouseMove(Shift: TShiftState; X, Y: Integer); override; + procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override; + function GetMinHeight: Integer; virtual; + function GetMinWidth: Integer; virtual; + property Color default clNone; + property MouseInControl: Boolean read FMouseInControl; + property PaintOptions: TControlPaintOptions read FPaintOptions write SetPaintOptions; + property ParentColor default False; + property Pushed: Boolean read FPushed; + property SpaceAsClick: Boolean read FSpaceAsClick write FSpaceAsClick default False; + property SmartFocus: Boolean read FSmartFocus write FSmartFocus default False; + property OnMouseEnter: TNotifyEvent read FOnMouseEnter write FOnMouseEnter; + property OnMouseLeave: TNotifyEvent read FOnMouseLeave write FOnMouseLeave; + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + procedure MakeVisible; + procedure MouseEntered; + procedure MouseLeft; + end; + + { TTBXAlignmentPanel } + + TTBXAlignmentPanel = class(TTBXPanelObject) + private + FMargins: TTBXControlMargins; + procedure MarginsChangeHandler(Sender: TObject); + procedure SetMargins(Value: TTBXControlMargins); + protected + procedure AdjustClientRect(var Rect: TRect); override; + procedure Paint; override; + function GetMinHeight: Integer; override; + function GetMinWidth: Integer; override; + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + published + property ParentColor; + property Align; + property Anchors; + property AutoSize; + property Color; + property Constraints; + property DragCursor; + property DragKind; + property DragMode; + property Enabled; + property Font; + property Margins: TTBXControlMargins read FMargins write SetMargins; + property ParentFont; + property ShowHint; + property TabOrder; + property TabStop; + property Visible; + property OnClick; +{$IFDEF JR_D5} + property OnContextPopup; +{$ENDIF} + property OnDblClick; + property OnDragDrop; + property OnDragOver; + property OnEndDock; + property OnEndDrag; + property OnMouseDown; + property OnMouseEnter; + property OnMouseLeave; + property OnMouseMove; + property OnMouseUp; + property OnStartDock; + property OnStartDrag; + end; + + { TTBXTextObject } + + TTBXTextObject = class(TTBXPanelObject) + private + FAlignment: TLeftRight; + FMargins: TTBXControlMargins; + FWrapping: TTextWrapping; + FShowAccelChar: Boolean; + FUpdating: Boolean; + procedure CMEnabledChanged(var Message: TMessage); message CM_ENABLEDCHANGED; + procedure CMFontChanged(var Message: TMessage); message CM_FONTCHANGED; + procedure CMTextChanged(var Message: TMessage); message CM_TEXTCHANGED; + procedure MarginsChangeHandler(Sender: TObject); + procedure SetAlignment(Value: TLeftRight); + procedure SetMargins(Value: TTBXControlMargins); + procedure SetShowAccelChar(Value: Boolean); + procedure SetWrapping(Value: TTextWrapping); + protected + procedure AdjustFont(AFont: TFont); virtual; + procedure AdjustHeight; + procedure CreateParams(var Params: TCreateParams); override; + function CanAutoSize(var NewWidth, NewHeight: Integer): Boolean; override; + procedure DoAdjustHeight(ACanvas: TCanvas; var NewHeight: Integer); virtual; + function DoDrawText(ACanvas: TCanvas; var Rect: TRect; Flags: Longint): Integer; virtual; + procedure DoMarginsChanged; virtual; + function GetFocusRect(const R: TRect): TRect; virtual; + function GetLabelText: string; virtual; + function GetTextAlignment: TAlignment; virtual; + function GetTextMargins: TRect; virtual; + procedure Loaded; override; + procedure Paint; override; + property Alignment: TLeftRight read FAlignment write SetAlignment default taLeftJustify; + property AutoSize default True; + property PaintOptions default [cpoDoubleBuffered]; + property ShowAccelChar: Boolean read FShowAccelChar write SetShowAccelChar default True; + property Margins: TTBXControlMargins read FMargins write SetMargins; + property Wrapping: TTextWrapping read FWrapping write SetWrapping default twNone; + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + function GetControlsAlignment: TAlignment; override; + end; + + { TTBXCustomLabel } + + TTBXCustomLabel = class(TTBXTextObject) + private + FFocusControl: TWinControl; + FUnderline: Boolean; + FUnderlineColor: TColor; + procedure CMDialogChar(var Message: TCMDialogChar); message CM_DIALOGCHAR; + procedure SetUnderline(Value: Boolean); + procedure SetUnderlineColor(Value: TColor); + procedure SetFocusControl(Value: TWinControl); + protected + function GetTextMargins: TRect; override; + procedure Notification(AComponent: TComponent; Operation: TOperation); override; + procedure Paint; override; + property FocusControl: TWinControl read FFocusControl write SetFocusControl; + property Underline: Boolean read FUnderline write SetUnderline default False; + property UnderlineColor: TColor read FUnderlineColor write SetUnderlineColor default clBtnShadow; + property Wrapping default twWrap; + public + constructor Create(AOwner: TComponent); override; + end; + + { TTBXLabel } + + TTBXLabel = class(TTBXCustomLabel) + published + property Action; {vb+} + property Align; + property Alignment; + property Anchors; + property AutoSize; + property BiDiMode; + property Caption; + property Color; + property Constraints; + property DragCursor; + property DragKind; + property DragMode; + property Enabled; + property FocusControl; + property Font; + property Margins; +// property PaintOptions; + property ParentBiDiMode; + property ParentColor; + property ParentFont; + property ParentShowHint; + property PopupMenu; + property ShowAccelChar; + property ShowHint; + property Underline; + property UnderlineColor; + property Visible; + property Wrapping; + property OnClick; +{$IFDEF JR_D5} + property OnContextPopup; +{$ENDIF} + property OnDblClick; + property OnDragDrop; + property OnDragOver; + property OnEndDock; + property OnEndDrag; + property OnMouseDown; + property OnMouseEnter; + property OnMouseLeave; + property OnMouseMove; + property OnMouseUp; + property OnStartDock; + property OnStartDrag; + end; + + { TTBXCustomLink } + + TTBXCustomLink = class(TTBXTextObject) + private + FImageChangeLink: TChangeLink; + FImageIndex: TImageIndex; + FImages: TCustomImageList; + procedure ImageListChange(Sender: TObject); + procedure SetImageIndex(Value: TImageIndex); + procedure SetImages(Value: TCustomImageList); + procedure CMDialogChar(var Message: TCMDialogChar); message CM_DIALOGCHAR; + procedure CMDialogKey(var Message: TCMDialogKey); message CM_DIALOGKEY; + procedure WMNCHitTest(var Message: TWMNCHitTest); message WM_NCHITTEST; + protected + procedure AdjustFont(AFont: TFont); override; + procedure DoAdjustHeight(ACanvas: TCanvas; var NewHeight: Integer); override; + procedure DoMouseEnter; override; + procedure DoMouseLeave; override; + function GetFocusRect(const R: TRect): TRect; override; + function GetTextAlignment: TAlignment; override; + function GetTextMargins: TRect; override; + procedure Paint; override; + procedure Notification(AComponent: TComponent; Operation: TOperation); override; + property Cursor default crHandPoint; + property ImageIndex: TImageIndex read FImageIndex write SetImageIndex; + property Images: TCustomImageList read FImages write SetImages; + property SmartFocus default True; + property TabStop default True; + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + function GetControlsAlignment: TAlignment; override; + end; + + { TTBXLink } + + TTBXLink = class(TTBXCustomLink) + published + property Action; {vb+} + property Align; + property Alignment; + property Anchors; + property AutoSize; + property BiDiMode; + property Caption; + property Color; + property Constraints; + property DragCursor; + property DragKind; + property DragMode; + property Enabled; + property Font; + property ImageIndex; + property Images; + property Margins; +// property PaintOptions; + property ParentBiDiMode; + property ParentColor; + property ParentFont; + property ParentShowHint; + property PopupMenu; + property ShowAccelChar; + property ShowHint; + property SmartFocus; + property TabOrder; + property TabStop; + property Visible; + property Wrapping; + property OnClick; +{$IFDEF JR_D5} + property OnContextPopup; +{$ENDIF} + property OnDblClick; + property OnDragDrop; + property OnDragOver; + property OnEndDock; + property OnEndDrag; + property OnEnter; + property OnExit; + property OnMouseDown; + property OnMouseEnter; + property OnMouseLeave; + property OnMouseMove; + property OnMouseUp; + property OnStartDock; + property OnStartDrag; + end; + + { TTBXCustomButton } + TTBXCustomButton = class; + TButtonLayout = (blGlyphLeft, blGlyphTop, blGlyphRight, blGlyphBottom); + TButtonStyle = (bsNormal, bsFlat); + TDropDownEvent = procedure(Sender: TTBXCustomButton; var AllowDropDown: Boolean) of object; + + TTBXCustomButton = class(TTBXTextObject) + private + FAlignment: TAlignment; + FAllowAllUnchecked: Boolean; + FBorderSize: Integer; + FChecked: Boolean; + FDropdownCombo: Boolean; + FDropdownMenu: TPopupMenu; + FButtonStyle: TButtonStyle; + FGlyphSpacing: Integer; + FGroupIndex: Integer; + FImageChangeLink: TChangeLink; + FImageIndex: TImageIndex; + FImages: TCustomImageList; + FInClick: Boolean; + FLayout: TButtonLayout; + FMenuVisible: Boolean; + FModalResult: TModalResult; + FRepeating: Boolean; + FRepeatDelay: Integer; + FRepeatInterval: Integer; + FRepeatTimer: TTimer; + FOnDropDown: TDropDownEvent; + procedure ImageListChange(Sender: TObject); + procedure RepeatTimerHandler(Sender: TObject); + procedure SetAlignment(Value: TAlignment); + procedure SetAllowAllUnchecked(Value: Boolean); + procedure SetBorderSize(Value: Integer); + procedure SetButtonStyle(Value: TButtonStyle); + procedure SetChecked(Value: Boolean); + procedure SetDropdownCombo(Value: Boolean); + procedure SetDropdownMenu(Value: TPopupMenu); + procedure SetGlyphSpacing(Value: Integer); + procedure SetGroupIndex(Value: Integer); + procedure SetImageIndex(Value: TImageIndex); + procedure SetImages(Value: TCustomImageList); + procedure SetLayout(Value: TButtonLayout); + procedure CMDialogChar(var Message: TCMDialogChar); message CM_DIALOGCHAR; + procedure CMDialogKey(var Message: TCMDialogKey); message CM_DIALOGKEY; + procedure WMCancelMode(var Message: TWMCancelMode); message WM_CANCELMODE; + procedure WMLButtonDblClk(var Message: TWMLButtonDblClk); message WM_LBUTTONDBLCLK; + procedure WMNCHitTest(var Message: TWMNCHitTest); message WM_NCHITTEST; + protected + function ArrowVisible: Boolean; + procedure DoAdjustHeight(ACanvas: TCanvas; var NewHeight: Integer); override; + function DoDrawText(ACanvas: TCanvas; var Rect: TRect; Flags: Longint): Integer; override; + function DoDropDown: Boolean; virtual; + procedure DoMouseEnter; override; + procedure DoMouseLeave; override; + function GetFocusRect(const R: TRect): TRect; override; + procedure GetItemInfo(out ItemInfo: TTBXItemInfo); virtual; + function GetTextAlignment: TAlignment; override; + function GetTextMargins: TRect; override; + procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override; + procedure MouseMove(Shift: TShiftState; X, Y: Integer); override; + procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override; + procedure Paint; override; + function PtInButtonPart(const Pt: TPoint): Boolean; virtual; + procedure Notification(AComponent: TComponent; Operation: TOperation); override; + procedure UpdateCheckedState; + property Alignment: TAlignment read FAlignment write SetAlignment default taCenter; + property AllowAllUnchecked: Boolean read FAllowAllUnchecked write SetAllowAllUnchecked default False; + property BorderSize: Integer read FBorderSize write SetBorderSize default 4; + property ButtonStyle: TButtonStyle read FButtonStyle write SetButtonStyle default bsNormal; + property Checked: Boolean read FChecked write SetChecked default False; + property DropdownCombo: Boolean read FDropdownCombo write SetDropdownCombo default False; + property DropdownMenu: TPopupMenu read FDropdownMenu write SetDropdownMenu; + property GlyphSpacing: Integer read FGlyphSpacing write SetGlyphSpacing default 4; + property GroupIndex: Integer read FGroupIndex write SetGroupIndex default 0; + property ImageIndex: TImageIndex read FImageIndex write SetImageIndex; + property Images: TCustomImageList read FImages write SetImages; + property Layout: TButtonLayout read FLayout write SetLayout default blGlyphLeft; + property ModalResult: TModalResult read FModalResult write FModalResult default 0; + property Repeating: Boolean read FRepeating write FRepeating default False; + property RepeatDelay: Integer read FRepeatDelay write FRepeatDelay default 400; + property RepeatInterval: Integer read FRepeatInterval write FRepeatInterval default 100; + property SmartFocus default True; + property TabStop default True; + property OnDropDown: TDropDownEvent read FOnDropDown write FOnDropDown; + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + procedure Click; override; + function GetControlsAlignment: TAlignment; override; + end; + + { TTBXButton } + TTBXButton = class(TTBXCustomButton) + published + property Action; {vb+} + property Align; + property Alignment; + property GroupIndex; + property AllowAllUnchecked; + property Anchors; + property AutoSize; + property BiDiMode; + property BorderSize; + property ButtonStyle; + property Caption; + property Checked; + property Constraints; + property DragCursor; + property DragKind; + property DragMode; + property DropDownCombo; + property DropDownMenu; + property Enabled; + property Font; + property GlyphSpacing; + property ImageIndex; + property Images; + property Layout; + property Margins; + property ModalResult; +// property PaintOptions; + property ParentBiDiMode; + property ParentFont; + property ParentShowHint; + property PopupMenu; + property Repeating; + property RepeatDelay; + property RepeatInterval; + property ShowAccelChar; + property ShowHint; + property SmartFocus; + property TabOrder; + property TabStop; + property Visible; + property Wrapping; + property OnClick; +{$IFDEF JR_D5} + property OnContextPopup; +{$ENDIF} + property OnDblClick; + property OnDragDrop; + property OnDragOver; + property OnDropDown; + property OnEndDock; + property OnEndDrag; + property OnMouseDown; + property OnMouseEnter; + property OnMouseLeave; + property OnMouseMove; + property OnMouseUp; + property OnStartDock; + property OnStartDrag; + end; + + { TTBXCustomCheckBox } + + TTBXCustomCheckBox = class(TTBXTextObject) + private + FAllowGrayed: Boolean; + FState: TCheckBoxState; + FOnChange: TNotifyEvent; + function GetChecked: Boolean; + procedure CMDialogChar(var Message: TCMDialogChar); message CM_DIALOGCHAR; + procedure CMDialogKey(var Message: TCMDialogKey); message CM_DIALOGKEY; + procedure CNCommand(var Message: TWMCommand); message CN_COMMAND; + procedure SetChecked(Value: Boolean); + procedure SetState(Value: TCheckBoxState); + procedure WMNCHitTest(var Message: TWMNCHitTest); message WM_NCHITTEST; + protected + procedure Click; override; + procedure DoAdjustHeight(ACanvas: TCanvas; var NewHeight: Integer); override; + procedure DoChange; virtual; + procedure DoMouseEnter; override; + procedure DoMouseLeave; override; + function DoSetState(var NewState: TCheckBoxState): Boolean; virtual; + function GetGlyphSize: Integer; + function GetFocusRect(const R: TRect): TRect; override; + function GetTextAlignment: TAlignment; override; + function GetTextMargins: TRect; override; + procedure Paint; override; + procedure Toggle; virtual; + property AllowGrayed: Boolean read FAllowGrayed write FAllowGrayed default False; + property Checked: Boolean read GetChecked write SetChecked stored False; + property SmartFocus default True; + property State: TCheckBoxState read FState write SetState default cbUnchecked; + property TabStop default True; + property OnChange: TNotifyEvent read FOnChange write FOnChange; + public + constructor Create(AOwner: TComponent); override; + end; + + TTBXCheckBox = class(TTBXCustomCheckBox) + published + property Action; {vb+} + property Align; + property Alignment; + property AllowGrayed; + property Anchors; + property AutoSize; + property BiDiMode; + property Caption; + property Checked; + property Color; + property Constraints; + property DragCursor; + property DragKind; + property DragMode; + property Enabled; + property Font; + property Margins; +// property PaintOptions; + property ParentBiDiMode; + property ParentColor; + property ParentFont; + property ParentShowHint; + property PopupMenu; + property ShowAccelChar; + property ShowHint; + property SmartFocus; + property State; + property TabOrder; + property TabStop; + property Visible; + property Wrapping; + property OnChange; + property OnClick; +{$IFDEF JR_D5} + property OnContextPopup; +{$ENDIF} + property OnDblClick; + property OnDragDrop; + property OnDragOver; + property OnEndDock; + property OnEndDrag; + property OnMouseDown; + property OnMouseEnter; + property OnMouseLeave; + property OnMouseMove; + property OnMouseUp; + property OnStartDock; + property OnStartDrag; + end; + + { TTBXCustomRadioButton } + + TTBXCustomRadioButton = class(TTBXTextObject) + private + FChecked: Boolean; + FGroupIndex: Integer; + FOnChange: TNotifyEvent; + procedure SetChecked(Value: Boolean); + procedure CMDialogChar(var Message: TCMDialogChar); message CM_DIALOGCHAR; + procedure CNCommand(var Message: TWMCommand); message CN_COMMAND; + procedure SetGroupIndex(Value: Integer); + procedure TurnSiblingsOff; + procedure WMNCHitTest(var Message: TWMNCHitTest); message WM_NCHITTEST; + protected + procedure Click; override; + procedure DoAdjustHeight(ACanvas: TCanvas; var NewHeight: Integer); override; + procedure DoChange; virtual; + procedure DoMouseEnter; override; + procedure DoMouseLeave; override; + function DoSetChecked(var Value: Boolean): Boolean; virtual; + function GetGlyphSize: Integer; + function GetFocusRect(const R: TRect): TRect; override; + function GetTextAlignment: TAlignment; override; + function GetTextMargins: TRect; override; + procedure Paint; override; + property Checked: Boolean read FChecked write SetChecked default False; + property GroupIndex: Integer read FGroupIndex write SetGroupIndex default 0; + property SmartFocus default True; + property TabStop default True; + property OnChange: TNotifyEvent read FOnChange write FOnChange; + public + constructor Create(AOwner: TComponent); override; + end; + + TTBXRadioButton = class(TTBXCustomRadioButton) + published + property Action; {vb+} + property Align; + property Alignment; + property Anchors; + property AutoSize; + property BiDiMode; + property Caption; + property Checked; + property Color; + property Constraints; + property DragCursor; + property DragKind; + property DragMode; + property Enabled; + property Font; + property GroupIndex; + property Margins; +// property PaintOptions; + property ParentBiDiMode; + property ParentColor; + property ParentFont; + property ParentShowHint; + property PopupMenu; + property ShowAccelChar; + property ShowHint; + property SmartFocus; + property TabOrder; + property TabStop; + property Visible; + property Wrapping; + property OnChange; + property OnClick; +{$IFDEF JR_D5} + property OnContextPopup; +{$ENDIF} + property OnDblClick; + property OnDragDrop; + property OnDragOver; + property OnEndDock; + property OnEndDrag; + property OnMouseDown; + property OnMouseEnter; + property OnMouseLeave; + property OnMouseMove; + property OnMouseUp; + property OnStartDock; + property OnStartDrag; + end; + + { TTBXPageScroller } + + TTBXPageScrollerOrientation = (tpsoVertical, tpsoHorizontal); + TTBXPageScrollerButtons = set of (tpsbPrev, tpsbNext); + + TTBXCustomPageScroller = class(TWinControl) + private + FAutoRangeCount: Integer; + FAutoRange: Boolean; + FAutoScroll: Boolean; + FButtonSize: Integer; + FMargin: Integer; + FOrientation: TTBXPageScrollerOrientation; + FPosition: Integer; + FPosRange: Integer; + FRange: Integer; + FScrollDirection: Integer; + FScrollCounter: Integer; + FScrollPending: Boolean; + FScrollTimer: TTimer; + FUpdatingButtons: Boolean; + FVisibleButtons: TTBXPageScrollerButtons; + procedure CalcAutoRange; + function IsRangeStored: Boolean; + procedure ScrollTimerTimer(Sender: TObject); + procedure SetButtonSize(Value: Integer); + procedure SetAutoRange(Value: Boolean); + procedure SetOrientation(Value: TTBXPageScrollerOrientation); + procedure SetPosition(Value: Integer); + procedure SetRange(Value: Integer); + procedure StopScrolling; + procedure ValidatePosition(var NewPos: Integer); + procedure CMParentColorChanged(var Message: TMessage); message CM_PARENTCOLORCHANGED; + procedure WMMouseMove(var Message: TWMMouseMove); message WM_MOUSEMOVE; + procedure WMNCCalcSize(var Message: TWMNCCalcSize); message WM_NCCALCSIZE; + procedure WMEraseBkgnd(var Message: TWmEraseBkgnd); message WM_ERASEBKGND; + procedure WMNCHitTest(var Message: TWMNCHitTest); message WM_NCHITTEST; + procedure WMNCLButtonDown(var Message: TWMNCLButtonDown); message WM_NCLBUTTONDOWN; + procedure WMNCMouseLeave(var Message: TMessage); message $2A2 {WM_NCMOUSELEAVE}; + procedure WMNCMouseMove(var Message: TWMNCMouseMove); message WM_NCMOUSEMOVE; + procedure WMNCPaint(var Message: TMessage); message WM_NCPAINT; + procedure WMSize(var Message: TWMSize); message WM_SIZE; + protected + procedure AdjustClientRect(var Rect: TRect); override; + procedure AlignControls(AControl: TControl; var ARect: TRect); override; + function AutoScrollEnabled: Boolean; virtual; + procedure BeginScrolling(HitTest: Integer); + function CalcClientArea: TRect; + function CanAutoSize(var NewWidth, NewHeight: Integer): Boolean; override; + procedure ConstrainedResize(var MinWidth, MinHeight, MaxWidth, MaxHeight: Integer); override; + procedure CreateParams(var Params: TCreateParams); override; + procedure DoSetRange(Value: Integer); virtual; + procedure DrawNCArea(const DrawToDC: Boolean; const ADC: HDC; const Clip: HRGN); virtual; + procedure HandleScrollTimer; virtual; + procedure Loaded; override; + procedure RecalcNCArea; + procedure Resizing; virtual; + procedure UpdateButtons; + property AutoScroll: Boolean read FAutoScroll write FAutoScroll default True; + property ButtonSize: Integer read FButtonSize write SetButtonSize default 10; + property Orientation: TTBXPageScrollerOrientation read FOrientation write SetOrientation default tpsoVertical; + property Position: Integer read FPosition write SetPosition default 0; + property Margin: Integer read FMargin write FMargin default 0; + property Range: Integer read FRange write SetRange stored IsRangeStored; + public + constructor Create(AOwner: TComponent); override; + procedure DisableAutoRange; + procedure EnableAutoRange; + procedure ScrollToCenter(ARect: TRect); overload; + procedure ScrollToCenter(AControl: TControl); overload; + property AutoRange: Boolean read FAutoRange write SetAutoRange default False; + end; + + TTBXPageScroller = class(TTBXCustomPageScroller) + public + property Position; + published + property Align; + property Anchors; + property AutoRange; + property AutoScroll; + property ButtonSize; + property Color; + property Constraints; + property DockSite; + property DragCursor; + property DragKind; + property DragMode; + property DoubleBuffered; + property Enabled; + property Ctl3D; + property Font; + property Margin; + property Orientation; + property ParentBiDiMode; + property ParentColor; + property ParentCtl3D; + property ParentFont; + property ParentShowHint; + property PopupMenu; + property Range; + property ShowHint; + property TabOrder; + property TabStop; + property Visible; + property OnCanResize; + property OnClick; + property OnConstrainedResize; +{$IFDEF JR_D5} + property OnContextPopup; +{$ENDIF} + property OnDblClick; + property OnDockDrop; + property OnDockOver; + property OnDragDrop; + property OnDragOver; + property OnEndDock; + property OnEndDrag; + property OnEnter; + property OnExit; + property OnGetSiteInfo; + property OnMouseDown; + property OnMouseMove; + property OnMouseUp; + property OnMouseWheel; + property OnMouseWheelDown; + property OnMouseWheelUp; + property OnResize; + property OnStartDock; + property OnStartDrag; + property OnUnDock; + end; + +implementation + +uses + TB2Common, TBXUtils, SysUtils; + +type + TWinControlAccess = class(TWinControl); + TDockAccess = class(TTBXMultiDock); + TTBDockableWindowAccess = class(TTBCustomDockableWindow); + +const + { Constants for TTBXDockablePanel-specific registry values. Do not localize! } + rvDockedWidth = 'DPDockedWidth'; + rvDockedHeight = 'DPDockedHeight'; + rvFloatingWidth = 'DPFloatingWidth'; + rvFloatingHeight = 'DPFloatingHeight'; + rvSplitWidth = 'DPSplitWidth'; + rvSplitHeight = 'DPSplitHeight'; + + HT_TB2k_Border = 2000; + HT_TB2k_Close = 2001; + HT_TB2k_Caption = 2002; + HT_TBX_SPLITRESIZELEFT = 86; + HT_TBX_SPLITRESIZERIGHT = 87; + HT_TBX_SPLITRESIZETOP = 88; + HT_TBX_SPLITRESIZEBOTTOM = 89; + DockedBorderSize = 2; + ScrollDelay = 300; + ScrollInterval = 75; + +var + MouseTimer: TTimer = nil; + MouseInObject: TTBXPanelObject = nil; + ObjectCount: Integer = 0; + + +procedure UpdateNCArea(Control: TWinControl; ViewType: Integer); +var + W, H: Integer; +begin + with Control do + begin + { Keep the client rect at the same position relative to screen } + W := ClientWidth; + H := ClientHeight; + SetWindowPos(Handle, 0, 0, 0, 0, 0, + SWP_FRAMECHANGED or SWP_NOACTIVATE or SWP_NOZORDER or SWP_NOREDRAW or SWP_NOMOVE or SWP_NOSIZE); + W := W - ClientWidth; + H := H - ClientHeight; + if (W <> 0) or (H <> 0) then + SetWindowPos(Handle, 0, Left - W div 2, Top - H div 2, Width + W, Height + H, + SWP_FRAMECHANGED or SWP_NOACTIVATE or SWP_NOZORDER); + RedrawWindow(Handle, nil, 0, RDW_FRAME or RDW_INVALIDATE or + RDW_ERASE or RDW_UPDATENOW or RDW_ALLCHILDREN); + end; +end; + +function GetMinControlHeight(Control: TControl): Integer; +begin + if Control.Align = alClient then + begin + if Control is TTBXPanelObject then Result := TTBXPanelObject(Control).GetMinHeight + else Result := Control.Constraints.MinHeight; + end + else Result := Control.Height; +end; + +function GetMinControlWidth(Control: TControl): Integer; +begin + if Control.Align = alClient then + begin + if Control is TTBXPanelObject then Result := TTBXPanelObject(Control).GetMinWidth + else Result := Control.Constraints.MinWidth; + end + else Result := Control.Width; +end; + +function IsActivated(AWinControl: TWinControl): Boolean; +var + C: TWinControl; +begin + { Returns true if AWinControl contains a focused control } + C := Screen.ActiveControl; + Result := True; + while C <> nil do + if C = AWinControl then Exit + else C := C.Parent; + Result := False; +end; + +procedure ApplyMargins(var R: TRect; const Margins: TTBXControlMargins); overload; +begin + with Margins do + begin + Inc(R.Left, Left); Inc(R.Top, Top); + Dec(R.Right, Right); Dec(R.Bottom, Bottom); + end; +end; + +procedure ApplyMargins(var R: TRect; const Margins: TRect); overload; +begin + with Margins do + begin + Inc(R.Left, Left); Inc(R.Top, Top); + Dec(R.Right, Right); Dec(R.Bottom, Bottom); + end; +end; + +procedure DrawFocusRect2(Canvas: TCanvas; const R: TRect); +var + DC: HDC; + C1, C2: TColor; +begin + DC := Canvas.Handle; + C1 := SetTextColor(DC, clBlack); + C2 := SetBkColor(DC, clWhite); + Canvas.DrawFocusRect(R); + SetTextColor(DC, C1); + SetBkColor(DC, C2); +end; + +function GetRealAlignment(Control: TControl): TAlignment; +const + ReverseAlignment: array [TAlignment] of TAlignment = (taRightJustify, taLeftJustify, taCenter); +begin + Result := Control.GetControlsAlignment; + if Control.UseRightToLeftAlignment then Result := ReverseAlignment[Result]; +end; + +function CompareEffectiveDockPos(const Item1, Item2, ExtraData: Pointer): Integer; far; +begin + Result := TTBCustomDockableWindow(Item1).EffectiveDockPos - TTBCustomDockableWindow(Item2).EffectiveDockPos; +end; + +function CompareDockPos(const Item1, Item2, ExtraData: Pointer): Integer; far; +var + P1, P2: Integer; +begin + P1 := TTBCustomDockableWindow(Item1).DockPos; + P2 := TTBCustomDockableWindow(Item2).DockPos; + if csLoading in TTBCustomDockableWindow(Item1).ComponentState then + begin + if P1 < 0 then P1 := MaxInt; + if P2 < 0 then P2 := MaxInt; + end; + Result := P1 - P2; +end; + + +//----------------------------------------------------------------------------// + +{ TTBXControlMargins } + +procedure TTBXControlMargins.Assign(Src: TPersistent); +begin + inherited; + Modified; +end; + +procedure TTBXControlMargins.Modified; +begin + if Assigned(FOnChange) then FOnChange(Self); +end; + +procedure TTBXControlMargins.SetBottom(Value: Integer); +begin + if FBottom <> Value then + begin + FBottom := Value; + Modified; + end; +end; + +procedure TTBXControlMargins.SetLeft(Value: Integer); +begin + if FLeft <> Value then + begin + FLeft := Value; + Modified; + end; +end; + +procedure TTBXControlMargins.SetRight(Value: Integer); +begin + if FRight <> Value then + begin + FRight := Value; + Modified; + end; +end; + +procedure TTBXControlMargins.SetTop(Value: Integer); +begin + if FTop <> Value then + begin + FTop := Value; + Modified; + end; +end; + +//----------------------------------------------------------------------------// + +{ TTBXMultiDock } + +function TTBXMultiDock.Accepts(ADockableWindow: TTBCustomDockableWindow): Boolean; +begin + Result := ADockableWindow is TTBXDockablePanel; +end; + +procedure TTBXMultiDock.ArrangeToolbars; +const + DSGN_DROPZONESIZE = 16; +type + TPosRec = record + Panel: TTBXDockablePanel; + MinSize, MaxSize, Size, Pos: Integer; + CanStretch: Boolean; + end; +var + NewDockList: TList; + PosData: array of TPosRec; + LeftRight: Boolean; + I, J, K, L, DragIndex, ResizeIndex, ForcedWidth: Integer; + EmptySize, ClientW, ClientH, DockSize, TotalSize, TotalMinimumSize, TotalMaximumSize: Integer; + {DragIndexPos: Integer;} {vb-} + T: TTBXDockablePanel; + S: TPoint; + CurRowPixel, CurRowSize: Integer; + StretchPanelCount: Integer; + Stretching: Boolean; + AccDelta, Acc: Extended; + Delta, IntAcc: Integer; + MinWidth, MaxWidth, EffectiveMinWidth, EffectiveMaxWidth: Integer; + R: TRect; + + function IndexOfDraggingToolbar(const List: TList): Integer; {vb+} + { Returns index of toolbar in List that's currently being dragged, or -1 } + var + I: Integer; + begin + for I := 0 to List.Count-1 do + if TTBCustomDockableWindow(List[I]).DragMode then begin + Result := I; + Exit; + end; + Result := -1; + end; + + procedure GetSizes(Panel: TTBXDockablePanel; out Size, MinSize, MaxSize: Integer); + var + Sz: TPoint; + MinWidth, MinHeight, MaxWidth, MaxHeight: Integer; + begin + Panel.GetBaseSize(Sz); + if LeftRight then + begin + Size := Panel.SplitHeight; + end + else + begin + Size := Panel.SplitWidth; + end; + MinWidth := 0; MaxWidth := 0; MinHeight := 0; MaxHeight := 0; + Panel.ConstrainedResize(MinWidth, MinHeight, MaxWidth, MaxHeight); + if not LeftRight then begin MinSize := MinWidth; MaxSize := MaxWidth end + else begin MinSize := MinHeight; MaxSize := MaxHeight end; + if MaxSize < MinSize then + begin + MaxSize := DockSize; + if MaxSize < MinSize then MaxSize := MinSize; + end; + if Size < MinSize then Size := MinSize + else if Size > MaxSize then Size := MaxSize; + end; + + procedure GetMinMaxWidth(Panel: TTBXDockablePanel; out Min, Max: Integer); + var + MinWidth, MinHeight, MaxWidth, MaxHeight: Integer; + begin + MinWidth := 0; MaxWidth := 0; MinHeight := 0; MaxHeight := 0; + Panel.ConstrainedResize(MinWidth, MinHeight, MaxWidth, MaxHeight); + if LeftRight then begin Min := MinWidth; Max := MaxWidth end + else begin Min := MinHeight; Max := MaxHeight end; + end; + +begin + if (DisableArrangeToolbars > 0) or (csLoading in ComponentState) then + begin + ArrangeToolbarsNeeded := True; + Exit; + end; + NewDockList := nil; + PosData := nil; + DisableArrangeToolbars := DisableArrangeToolbars + 1; + try + LeftRight := Position in [dpLeft, dpRight]; + + if not HasVisibleToolbars then + begin + EmptySize := Ord(FixAlign); + if csDesigning in ComponentState then EmptySize := 7; + if not LeftRight then ChangeWidthHeight(Width, EmptySize) + else ChangeWidthHeight(EmptySize, Height); + Exit; + end; + + ClientW := Width - NonClientWidth; + if ClientW < 0 then ClientW := 0; + ClientH := Height - NonClientHeight; + if ClientH < 0 then ClientH := 0; + if not LeftRight then DockSize := ClientW + else DockSize := ClientH; + + { Leave some space for dropping other panels in design time } + if csDesigning in ComponentState then Dec(DockSize, DSGN_DROPZONESIZE); + if DockSize < 0 then DockSize := 0; + + + for I := DockList.Count - 1 downto 0 do + begin + T := DockList[I]; + if csDestroying in T.ComponentState then + begin + DockList.Delete(I); + DockVisibleList.Remove(T); + end; + end; + + { always limit to one row } + for I := 0 to DockList.Count - 1 do + with TTBCustomDockableWindow(DockList[I]) do DockRow := 0; + + { Copy DockList to NewDockList, and ensure it is in correct ordering + according to DockRow/DockPos } + NewDockList := TList.Create; + NewDockList.Count := DockList.Count; + for I := 0 to NewDockList.Count - 1 do NewDockList[I] := DockList[I]; + {I := NewDockList.IndexOf(DragToolbar); {vb-} + I := IndexOfDraggingToolbar(NewDockList); {vb+} + ListSortEx(NewDockList, CompareDockPos, nil); + {DragIndex := NewDockList.IndexOf(DragToolbar); {vb-} + DragIndex := IndexOfDraggingToolbar(NewDockList); {vb+} + {if (I <> -1) and DragSplitting then {vb-} + if (I <> -1) and + TTBCustomDockableWindow(NewDockList[DragIndex]).DragSplitting then {vb+} + begin + { When splitting, don't allow the toolbar being dragged to change + positions in the dock list } + NewDockList.Move(DragIndex, I); + DragIndex := I; + end; + ListSortEx(DockVisibleList, CompareDockPos, nil); + + { Create a temporary array that holds new position data for the toolbars + and get size info } + SetLength(PosData, 0); + for I := 0 to NewDockList.Count - 1 do + begin + T := NewDockList[I]; + if ToolbarVisibleOnDock(T) then + begin + SetLength(PosData, Length(PosData) + 1); + with PosData[Length(PosData) - 1] do + begin + Panel := T as TTBXDockablePanel; + Pos := Panel.DockPos; + GetSizes(Panel, Size, MinSize, MaxSize{, OrigWidth}); + end; + end; + end; + + { Update drag index... } + if DragIndex >= 0 then + for I := 0 to Length(PosData) - 1 do + if NewDockList.IndexOf(PosData[I].Panel) = DragIndex then + begin + DragIndex := I; + Break; + end; + + { Count total sizes and set initial positions } + {DragIndexPos := 0;} {vb-} + TotalSize := 0; TotalMinimumSize := 0; TotalMaximumSize := 0; + for I := 0 to Length(PosData) - 1 do + with PosData[I] do + begin + {if I = DragIndex then DragIndexPos := Panel.DockPos;} {vb-} + Pos := TotalSize; + Inc(TotalSize, Size); + Inc(TotalMinimumSize, MinSize); + Inc(TotalMaximumSize, MaxSize); + end; + + if DockSize <> TotalSize then + begin + begin + { Proportionally stretch and shrink toolbars } + + if TotalMinimumSize >= DockSize then + for I := 0 to Length(PosData) - 1 do PosData[I].Size := PosData[I].MinSize + else if TotalMaximumSize <= DockSize then + for I := 0 to Length(PosData) - 1 do PosData[I].Size := PosData[I].MaxSize + else + begin + Delta := DockSize - TotalSize; + StretchPanelCount := 0; + Stretching := TotalSize < DockSize; // otherwise, shrinking + + for I := 0 to Length(PosData) - 1 do + with PosData[I] do + begin + if Stretching then CanStretch := Size < MaxSize + else CanStretch := Size > MinSize; + if CanStretch then Inc(StretchPanelCount); + end; + Assert(StretchPanelCount > 0); + + while Delta <> 0 do + begin + Assert(StretchPanelCount <> 0); + AccDelta := Delta / StretchPanelCount; + Acc := 0; IntAcc := 0; + for I := 0 to Length(PosData) - 1 do + with PosData[I] do if CanStretch then + begin + Acc := Acc + AccDelta; + Inc(Size, Round(Acc) - IntAcc); + IntAcc := Round(Acc); + end; + + TotalSize := 0; + for I := 0 to Length(PosData) - 1 do + with PosData[I] do + begin + if CanStretch then + if Stretching then + begin + if Size > MaxSize then + begin + Size := MaxSize; + CanStretch := False; + Dec(StretchPanelCount); + end; + end + else + begin + if Size < MinSize then + begin + Size := MinSize; + CanStretch := False; + Dec(StretchPanelCount); + end; + end; + Inc(TotalSize, Size); + end; + Delta := DockSize - TotalSize; + end; + end; + + TotalSize := 0; + for I := 0 to Length(PosData) - 1 do + with PosData[I] do + begin + Pos := TotalSize; + Inc(TotalSize, Size); + end; + end + end; + + for I := 0 to NewDockList.Count - 1 do + begin + for J := 0 to Length(PosData) - 1 do + with PosData[J] do + begin + if Panel = NewDockList[I] then + begin + Panel.EffectiveDockRowAccess := 0; + Panel.EffectiveDockPosAccess := PosData[J].Pos; + end; + end; + if CommitNewPositions then + begin + T := NewDockList[I]; + T.DockRow := T.EffectiveDockRow; + T.DockPos := T.EffectiveDockPos; + DockList[I] := NewDockList[I]; + end; + end; + + ResizeIndex := -1; + for I := 0 to Length(PosData) - 1 do + with PosData[I] do + if Panel is TTBXDockablePanel and Panel.IsResizing then + begin + ResizeIndex := I; + Break; + end; + + { Calculate the size of the dock } + if ResizeIndex < 0 then + begin + CurRowSize := 0; + for I := 0 to Length(PosData) - 1 do + with PosData[I] do + begin + Panel.CurrentSize := Size; + Panel.GetBaseSize(S); + if LeftRight then K := S.X + Panel.CalcNCSizes.X else K := S.Y + Panel.CalcNCSizes.Y; + if (DragIndex = I) and (Length(PosData) > 1) and (LastValidRowSize > 0) then K := 0; + if K > CurRowSize then CurRowSize := K; + end; + end + else + begin + EffectiveMinWidth := 0; + EffectiveMaxWidth := 0; + for I := 0 to Length(PosData) - 1 do + begin + GetMinMaxWidth(PosData[I].Panel, MinWidth, MaxWidth); + if MinWidth > EffectiveMinWidth then EffectiveMinWidth := MinWidth; + if (MaxWidth >= MinWidth) and (MaxWidth < EffectiveMaxWidth) then EffectiveMaxWidth := MaxWidth; + end; + if LeftRight then CurRowSize := PosData[ResizeIndex].Panel.Width + else CurRowSize := PosData[ResizeIndex].Panel.Height; + if (EffectiveMaxWidth > EffectiveMinWidth) and (CurRowSize > EffectiveMaxWidth) then CurRowSize := EffectiveMaxWidth; + if CurRowSize < EffectiveMinWidth then CurRowSize := EffectiveMinWidth; + end; + if CurRowSize > 0 then LastValidRowSize := CurRowSize; + + { Now actually move the toolbars } + for I := 0 to Length(PosData) - 1 do + with PosData[I] do + begin + if LeftRight then R := Bounds(0, Pos, CurRowSize, Size) + else R := Bounds(Pos, 0, Size, CurRowSize); + Panel.BoundsRect := R; + { This is to fix some weird behavior in design time } + if csDesigning in ComponentState then + with R do MoveWindow(Panel.Handle, Left, Top, Right - Left, Bottom - Top, True); + end; + + { Set the size of the dock } + if not LeftRight then ChangeWidthHeight(Width, CurRowSize + NonClientHeight) + else ChangeWidthHeight(CurRowSize + NonClientWidth, Height); + + finally + DisableArrangeToolbars := DisableArrangeToolbars - 1; + ArrangeToolbarsNeeded := False; + CommitNewPositions := False; + SetLength(PosData, 0); + NewDockList.Free; + end; +end; + +procedure TTBXMultiDock.Paint; +var + R: TRect; +begin + { Draw dotted border in design mode } + if csDesigning in ComponentState then + begin + R := ClientRect; + with Canvas do + begin + Pen.Style := psSolid; + Pen.Color := clBtnHighlight; + Brush.Color := clBtnHighlight; + Brush.Style := bsFDiagonal; + Rectangle(R.Left, R.Top, R.Right, R.Bottom); + Pen.Style := psSolid; + end; + end; +end; + +procedure TTBXMultiDock.ResizeVisiblePanels(NewSize: Integer); +var + I: Integer; +begin + BeginUpdate; + try + for I := 0 to DockVisibleList.Count - 1 do + if Position in [dpLeft, dpRight] then + TTBXDockablePanel(DockVisibleList[I]).DockedWidth := NewSize + else + TTBXDockablePanel(DockVisibleList[I]).DockedHeight := NewSize; + finally + EndUpdate; + end; +end; + +procedure TTBXMultiDock.ValidateInsert(AComponent: TComponent); +begin + if not (AComponent is TTBXDockablePanel) then + raise EInvalidOperation.CreateFmt('Cannot insert %s into TTBXMultiDock', [AComponent.ClassName]); +end; + +//----------------------------------------------------------------------------// + +{ TTBXPanelObject } + +procedure TTBXPanelObject.CMEnabledChanged(var Message: TMessage); +begin + inherited; + if not Enabled and FMouseInControl then + begin + FMouseInControl := False; + RemoveMouseTimer; + DoMouseLeave; + Invalidate; + Perform(WM_CANCELMODE, 0, 0); + end; +end; + +procedure TTBXPanelObject.CMParentColorChanged(var Message: TMessage); +begin + if Message.WParam = 0 then + begin + Message.WParam := 1; + Message.LParam := GetEffectiveColor(Parent); + end; + inherited; + Invalidate; +end; + +constructor TTBXPanelObject.Create(AOwner: TComponent); +begin + inherited; + ControlStyle := ControlStyle + [csAcceptsControls, csClickEvents, csDoubleClicks] - [csOpaque]; + if MouseTimer = nil then + begin + MouseTimer := TTimer.Create(nil); + MouseTimer.Enabled := False; + MouseTimer.Interval := 125; + end; + Inc(ObjectCount); + ParentColor := False; + Color := clNone; + AddThemeNotification(Self); +end; + +procedure TTBXPanelObject.CreateParams(var Params: TCreateParams); +begin + inherited CreateParams(Params); + if not (csDesigning in ComponentState) then + with Params.WindowClass do style := style and not (CS_HREDRAW or CS_VREDRAW); +// if cpoTransparent in PaintOptions then +// Params.ExStyle := Params.ExStyle or WS_EX_TRANSPARENT; +end; + +destructor TTBXPanelObject.Destroy; +begin + RemoveThemeNotification(Self); + RemoveMouseTimer; + Dec(ObjectCount); + if ObjectCount = 0 then + begin + MouseTimer.Free; + MouseTimer := nil; + end; + inherited; +end; + +procedure TTBXPanelObject.DoMouseEnter; +begin + if Assigned(FOnMouseEnter) then FOnMouseEnter(Self); +end; + +procedure TTBXPanelObject.DoMouseLeave; +begin + if Assigned(FOnMouseLeave) then FOnMouseLeave(Self); +end; + +function TTBXPanelObject.GetMinHeight: Integer; +begin + Result := Height; +end; + +function TTBXPanelObject.GetMinWidth: Integer; +begin + Result := Width; +end; + +procedure TTBXPanelObject.KeyDown(var Key: Word; Shift: TShiftState); +begin + inherited; + if SpaceAsClick and (Key = VK_SPACE) then + begin + FPushed := True; + Invalidate; + end; +end; + +procedure TTBXPanelObject.KeyUp(var Key: Word; Shift: TShiftState); +begin + if SpaceAsClick and Pushed and (Key = VK_SPACE) then + begin + FPushed := False; + Click; + Invalidate; + end; + inherited; +end; + +procedure TTBXPanelObject.MakeVisible; + + procedure HandleScroll(SW: TControl); + begin + if SW is TScrollingWinControl then TScrollingWinControl(SW).ScrollInView(Self) + else if SW is TTBXCustomPageScroller then TTBXCustomPageScroller(SW).ScrollToCenter(Self) + else if (Parent <> nil) and (Parent <> SW) then HandleScroll(Parent); + end; + +begin + HandleScroll(Parent); +end; + +procedure TTBXPanelObject.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); +begin + if (Button = mbLeft) and not FPushed then + begin + FPushed := True; + Invalidate; + end; + if Enabled then MouseEntered; + if not SmartFocus and CanFocus then SetFocus + else if SmartFocus and CanFocus and Assigned(Parent) and IsActivated(Parent) then + begin + FDisableScroll := True; + SetFocus; + FDisableScroll := False; + end; + inherited; +end; + +procedure TTBXPanelObject.MouseEntered; +begin + if Enabled and not FMouseInControl then + begin + FMouseInControl := True; + DoMouseEnter; + end; +end; + +procedure TTBXPanelObject.MouseLeft; +begin + if Enabled and FMouseInControl then + begin + FMouseInControl := False; + RemoveMouseTimer; + DoMouseLeave; + Invalidate; + end; +end; + +procedure TTBXPanelObject.MouseMove(Shift: TShiftState; X, Y: Integer); +var + P: TPoint; + DragTarget: TControl; +begin + P := ClientToScreen(Point(X, Y)); + DragTarget := FindDragTarget(P, True); + if (MouseInObject <> Self) and (DragTarget = Self) then + begin + if Assigned(MouseInObject) then MouseInObject.MouseLeft; + MouseInObject := Self; + MouseTimer.OnTimer := MouseTimerHandler; + MouseTimer.Enabled := True; + MouseEntered; + end + else if (DragTarget <> Self) and (Mouse.Capture = Handle) and FMouseInControl then + begin + MouseLeft; + end; + inherited; +end; + +procedure TTBXPanelObject.MouseTimerHandler(Sender: TObject); +var + P: TPoint; +begin + GetCursorPos(P); + if FindDragTarget(P, True) <> Self then MouseLeft; +end; + +procedure TTBXPanelObject.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); +begin + FPushed := False; + Invalidate; + inherited; +end; + +procedure TTBXPanelObject.RemoveMouseTimer; +begin + if MouseInObject = Self then + begin + MouseTimer.Enabled := False; + MouseInObject := nil; + end; +end; + +procedure TTBXPanelObject.SetPaintOptions(Value: TControlPaintOptions); +begin + if Value <> FPaintOptions then + begin + FPaintOptions := Value; + if cpoDoubleBuffered in Value then DoubleBuffered := True + else DoubleBuffered := False; + RecreateWnd; + end; +end; + +procedure TTBXPanelObject.TBMThemeChange(var Message); +var + R: TRect; +begin + if HandleAllocated then + begin + R := ClientRect; + InvalidateRect(Handle, @R, True); + end; +end; + +procedure TTBXPanelObject.WMEraseBkgnd(var Message: TMessage); +begin + if not DoubleBuffered or (Message.wParam = Message.lParam) then + begin + if Color = clNone then + DrawParentBackground(Self, TWMEraseBkgnd(Message).DC, ClientRect) + else + FillRectEx(TWMEraseBkgnd(Message).DC, ClientRect, Color); + end; + Message.Result := 1; +end; + +procedure TTBXPanelObject.WMKillFocus(var Message: TMessage); +begin + FPushed := False; + Invalidate; +end; + +procedure TTBXPanelObject.WMSetFocus(var Message: TMessage); +begin + inherited; + if not FDisableScroll then MakeVisible; + Invalidate; +end; + +//----------------------------------------------------------------------------// + +{ TTBXDockablePanel } + +procedure TTBXCustomDockablePanel.AdjustClientRect(var Rect: TRect); +begin + inherited AdjustClientRect(Rect); + if BorderSize <> 0 then InflateRect(Rect, -BorderSize, -BorderSize); +end; + +procedure TTBXCustomDockablePanel.BeginDockedSizing(HitTest: Integer); +var + OrigPos, OldPos: TPoint; + Msg: TMsg; + DockRect, DragRect, OrigDragRect, OldDragRect: TRect; + NCSizes: TPoint; + EdgeRect, OldEdgeRect: TRect; + ScreenDC: HDC; + EraseEdgeRect, CommitResizing: Boolean; + Form: TCustomForm; + LeftRight: Boolean; + + function RectToScreen(const R: TRect): TRect; + begin + Result := R; + Result.TopLeft := Parent.ClientToScreen(Result.TopLeft); + Result.BottomRight := Parent.ClientToScreen(Result.BottomRight); + end; + + function RectToClient(const R: TRect): TRect; + begin + Result := R; + Result.TopLeft := Parent.ScreenToClient(Result.TopLeft); + Result.BottomRight := Parent.ScreenToClient(Result.BottomRight); + end; + + function GetEdgeRect(const R: TRect): TRect; + begin + Result := DockRect; + case HitTest of + HTLEFT: begin Result.Left := R.Left - 1; Result.Right := R.Left + 1 end; + HTRIGHT: begin Result.Left := R.Right - 1; Result.Right := R.Right + 1 end; + HTTOP: begin Result.Top := R.Top - 1; Result.Bottom := R.Top + 1 end; + HTBOTTOM: begin Result.Top := R.Bottom - 1; Result.Bottom := R.Bottom + 1 end; + end; + end; + + procedure MouseMoved; + var + Pos: TPoint; + NewWidth: Integer; + NewHeight: Integer; + begin + GetCursorPos(Pos); + if (Pos.X = OldPos.X) and (Pos.Y = OldPos.Y) then Exit; + DragRect := OrigDragRect; + case HitTest of + HTLEFT: + begin + NewWidth := DragRect.Right - (DragRect.Left + Pos.X - OrigPos.X - 1); + if DoDockedResizing(False, NewWidth) then + DragRect.Left := DragRect.Right - NewWidth; + end; + HTRIGHT: + begin + NewWidth := (DragRect.Right + Pos.X - OrigPos.X) - DragRect.Left; + if DoDockedResizing(False, NewWidth) then + DragRect.Right := DragRect.Left + NewWidth; + end; + HTTOP: + begin + NewHeight := DragRect.Bottom - (DragRect.Top + Pos.Y - OrigPos.Y - 1); + if DoDockedResizing(True, NewHeight) then + DragRect.Top := DragRect.Bottom - NewHeight; + end; + HTBOTTOM: + begin + NewHeight := (DragRect.Bottom + Pos.Y - OrigPos.Y) - DragRect.Top; + if DoDockedResizing(True, NewHeight) then + DragRect.Bottom := DragRect.Top + NewHeight; + end; + end; + if not CompareMem(@OldDragRect, @DragRect, SizeOf(TRect)) then + begin + if SmoothDockedResize then + begin + CurrentDock.BeginUpdate; + if HitTest in [HTLEFT, HTRIGHT] then + begin + BlockSizeUpdate := True; + DockedWidth := DragRect.Right - DragRect.Left - NCSizes.X; + end + else + begin + BlockSizeUpdate := True; + DockedHeight := DragRect.Bottom - DragRect.Top - NCSizes.Y; + end; + BlockSizeUpdate := False; + CurrentDock.EndUpdate; + end + else + begin + EdgeRect := GetEdgeRect(DragRect); + DrawDraggingOutline(ScreenDC, EdgeRect, OldEdgeRect); + OldEdgeRect := EdgeRect; + EraseEdgeRect := True; + end; + OldPos := Pos; + OldDragRect := DragRect; + end; + end; + +begin + LeftRight := HitTest in [HTLEFT, HTRIGHT]; + if DoBeginDockedResizing(HitTest in [HTTOP, HTBOTTOM]) then + try + SetCapture(Handle); + ScreenDC := GetDC(0); + OrigDragRect := RectToScreen(BoundsRect); + DockRect := RectToScreen(CurrentDock.ClientRect); + OldDragRect := Rect(0, 0, 0, 0); + NCSizes := CalcNCSizes; + DragRect := OrigDragRect; + GetCursorPos(OrigPos); + OldPos := OrigPos; + FIsResizing := True; + + if not SmoothDockedResize then + begin + EdgeRect := GetEdgeRect(DragRect); + DrawDraggingOutline(ScreenDC, EdgeRect, Rect(0, 0, 0, 0)); + OldEdgeRect := EdgeRect; + EraseEdgeRect := True; + end + else EraseEdgeRect := False; + + while GetCapture = Handle do + begin + case Integer(GetMessage(Msg, 0, 0, 0)) of + -1: Break; + 0: begin + PostQuitMessage(Msg.WParam); + Break; + end; + end; + case Msg.Message of + WM_KEYDOWN, WM_KEYUP: if Msg.WParam = VK_ESCAPE then Break; + WM_MOUSEMOVE: MouseMoved; + WM_LBUTTONDOWN, WM_LBUTTONDBLCLK:Break; + WM_LBUTTONUP: Break; + WM_RBUTTONDOWN..WM_MBUTTONDBLCLK:; + else + TranslateMessage(Msg); + DispatchMessage(Msg); + end; + end; + finally + if GetCapture = Handle then ReleaseCapture; + CommitResizing := DoEndDockedResizing(HitTest in [HTTOP, HTBOTTOM]); + if EraseEdgeRect then + begin + DrawDraggingOutline(ScreenDC, Rect(0, 0, 0, 0), OldEdgeRect); + if CommitResizing and not IsRectEmpty(OldDragRect) then + with OldDragRect do + begin + BlockSizeUpdate := True; + if LeftRight then DockedWidth := Right - Left - NCSizes.X + else DockedHeight := Bottom - Top - NCSizes.Y; + BlockSizeUpdate := False; + end; + end + else if not CommitResizing then + begin + BlockSizeUpdate := True; + BoundsRect := RectToClient(OrigDragRect); + BlockSizeUpdate := False; + end; + ReleaseDC(0, ScreenDC); + FIsResizing := False; + if csDesigning in ComponentState then + begin + Form := GetParentForm(Self); + if (Form <> nil) and (Form.Designer <> nil) then Form.Designer.Modified; + end; + end; +end; + +procedure TTBXCustomDockablePanel.BeginSplitResizing(HitTest: Integer); +type + TPosRec = record + Panel: TTBXDockablePanel; + OrigPos, OrigSize, OrigWidth, Pos, Size, MinSize, MaxSize: Integer; + end; +var + Dock: TDockAccess; + PosData: array of TPosRec; + I: Integer; + LeftRight, Smooth, CommitResizing: Boolean; + DockSize, TotalSize, TotalMinSize, TotalMaxSize: Integer; + OrigCursorPos, OldCursorPos: TPoint; + Msg: TMsg; + EffectiveIndex: Integer; + {EffectivePanel: TTBXDockablePanel;} {vb-} + EffectivePanel: TTBXCustomDockablePanel; {vb+} + PanelRect, DockRect, EdgeRect, OrigEdgeRect, OldEdgeRect: TRect; + EdgePosition: TTBDockPosition; + ScreenDC: HDC; + EraseEdgeRect: Boolean; + Form: TCustomForm; + Delta: Integer; + + procedure GetSizes(Panel: TTBXDockablePanel; out Size, MinSize, MaxSize, W: Integer); + var + Sz: TPoint; + MinWidth, MinHeight, MaxWidth, MaxHeight: Integer; + begin + Panel.GetBaseSize(Sz); + if not LeftRight then + begin + Size := Panel.Width; + W := Panel.Height; + end + else + begin + Size := Panel.Height; + W := Panel.Width; + end; + MinWidth := 0; MaxWidth := 0; MinHeight := 0; MaxHeight := 0; + Panel.ConstrainedResize(MinWidth, MinHeight, MaxWidth, MaxHeight); + if not LeftRight then begin MinSize := MinWidth; MaxSize := MaxWidth; end + else begin MinSize := MinHeight; MaxSize := MaxHeight end; + if MaxSize < MinSize then + begin + MaxSize := DockSize; + if MaxSize < MinSize then MaxSize := MinSize; + end; + if Size < MinSize then Size := MinSize + else if Size > MaxSize then Size := MaxSize; + end; + + procedure BlockSizeUpdates(DoBlock: Boolean); + var + I: Integer; + begin + for I := 0 to Length(PosData) - 1 do + with PosData[I].Panel do BlockSizeUpdate := DoBlock; + end; + + procedure SetSizes(RestoreOriginal: Boolean = False); + var + I: Integer; + R: TRect; + begin + Dock.BeginUpdate; + BlockSizeUpdates(True); + for I := 0 to Length(PosData) - 1 do + with PosData[I] do + begin + if LeftRight then + begin + if RestoreOriginal then R := Bounds(0, OrigPos, OrigWidth, OrigSize) + else R := Bounds(0, Pos, OrigWidth, Size); + end + else + begin + if RestoreOriginal then R := Bounds(OrigPos, 0, OrigSize, OrigWidth) + else R := Bounds(Pos, 0, Size, OrigWidth); + end; + if LeftRight then Panel.SplitHeight := Size + else Panel.SplitWidth := Size; + Panel.BoundsRect := R; + + { This is to fix some weird behavior in design time } + if csDesigning in ComponentState then + with R do MoveWindow(Panel.Handle, Left, Top, Right - Left, Bottom - Top, True); + end; + BlockSizeUpdates(False); + Dock.EndUpdate; + end; + + function GetEdgeRect(R: TRect): TRect; + begin + Result := R; + case EdgePosition of + dpRight: begin Result.Left := Result.Right - 1; Inc(Result.Right); end; + dpBottom: begin Result.Top := Result.Bottom - 1; Inc(Result.Bottom); end; + end; + end; + + function RectToScreen(const R: TRect): TRect; + begin + Result := R; + Result.TopLeft := Parent.ClientToScreen(Result.TopLeft); + Result.BottomRight := Parent.ClientToScreen(Result.BottomRight); + end; + + function RectToClient(const R: TRect): TRect; + begin + Result := R; + Result.TopLeft := Parent.ScreenToClient(Result.TopLeft); + Result.BottomRight := Parent.ScreenToClient(Result.BottomRight); + end; + + procedure MouseMoved; + var + CursorPos: TPoint; + I, P, Acc: Integer; + begin + GetCursorPos(CursorPos); + if (CursorPos.X = OldCursorPos.X) and (CursorPos.Y = OldCursorPos.Y) then Exit; + case EdgePosition of + dpRight: Delta := CursorPos.X - OrigCursorPos.X; + dpBottom: Delta := CursorPos.Y - OrigCursorPos.Y; + end; + if Delta = 0 then Exit; + + for I := 0 to Length(PosData) - 1 do + with PosData[I] do + begin + Pos := OrigPos; + Size := OrigSize; + end; + + Acc := Delta; + for I := EffectiveIndex downto 0 do + with PosData[I] do + begin + Inc(Size, Acc); Acc := 0; + if Size > MaxSize then + begin + Acc := Size - MaxSize; + Size := MaxSize; + end + else if Size < MinSize then + begin + Acc := Size - MinSize; + Size := MinSize; + end; + if Acc = 0 then Break; + end; + + if Acc <> 0 then Dec(Delta, Acc); + + Acc := Delta; + for I := EffectiveIndex + 1 to Length(PosData) - 1 do + with PosData[I] do + begin + Dec(Size, Acc); Acc := 0; + if Size > MaxSize then + begin + Acc := MaxSize - Size; + Size := MaxSize; + end + else if Size < MinSize then + begin + Acc := MinSize - Size; + Size := MinSize; + end; + if Acc = 0 then Break; + end; + + if Acc <> 0 then + begin + Dec(Delta, Acc); + for I := 0 to EffectiveIndex do with PosData[I] do Size := OrigSize; + Acc := Delta; + for I := EffectiveIndex downto 0 do + with PosData[I] do + begin + Inc(Size, Acc); Acc := 0; + if Size > MaxSize then + begin + Acc := Size - MaxSize; + Size := MaxSize; + end + else if Size < MinSize then + begin + Acc := Size - MinSize; + Size := MinSize; + end; + if Acc = 0 then Break; + end; + end; + + P := 0; + for I := 0 to Length(PosData) - 1 do + with PosData[I] do begin Pos := P; Inc(P, Size); end; + + if Smooth then SetSizes + else + begin + EdgeRect := DockRect; + if LeftRight then + begin + Inc(EdgeRect.Top, PosData[EffectiveIndex + 1].Pos - 1); + EdgeRect.Bottom := EdgeRect.Top + 2; + end + else + begin + Inc(EdgeRect.Left, PosData[EffectiveIndex + 1].Pos - 1); + EdgeRect.Right := EdgeRect.Left + 2; + end; + DrawDraggingOutline(ScreenDC, EdgeRect, OldEdgeRect); + EraseEdgeRect := True; + end; + + OldCursorPos := CursorPos; + OldEdgeRect := EdgeRect; + end; + +begin + if not (CurrentDock is TTBXMultiDock) then Exit; + Dock := TDockAccess(CurrentDock); + + SetLength(PosData, Dock.DockVisibleList.Count); + for I := 0 to Dock.DockVisibleList.Count - 1 do + with PosData[I] do + begin + { only docks with TTBXDockablePanels can be resized } + if not (TTBCustomDockableWindow(Dock.DockVisibleList[I]) is TTBXDockablePanel) then Exit; + Panel := TTBXDockablePanel(Dock.DockVisibleList[I]); + end; + + LeftRight := Dock.Position in [dpLeft, dpRight]; + if not LeftRight then DockSize := Dock.Width - Dock.NonClientWidth + else DockSize := Dock.Height - Dock.NonClientHeight; + if DockSize < 0 then DockSize := 0; + + { See if we can actually resize anything } + TotalSize := 0; TotalMinSize := 0; TotalMaxSize := 0; + for I := 0 to Length(PosData) - 1 do + with PosData[I] do + begin + GetSizes(Panel, Size, MinSize, MaxSize, OrigWidth); + OrigSize := Size; + OrigPos := TotalSize; + Pos := OrigPos; + Inc(TotalSize, Size); + Inc(TotalMinSize, MinSize); + Inc(TotalMaxSize, MaxSize); + end; + if (TotalMinSize > DockSize) or (TotalMaxSize < DockSize) then Exit; + + { Get effective edge and panel } + case HitTest of + HT_TBX_SPLITRESIZETOP: EdgePosition := dpTop; + HT_TBX_SPLITRESIZEBOTTOM: EdgePosition := dpBottom; + HT_TBX_SPLITRESIZELEFT: EdgePosition := dpLeft; + else + EdgePosition := dpRight; + end; + Smooth := True; + EffectivePanel := Self; + for I := 0 to Length(PosData) - 1 do + with PosData[I] do + begin + if not Panel.SmoothDockedResize then Smooth := False; + if Panel = Self then + begin + EffectiveIndex := I; + if EdgePosition in [dpLeft, dpTop] then + begin + Assert(I > 0); + EffectivePanel := PosData[I - 1].Panel; + if EdgePosition = dpLeft then EdgePosition := dpRight + else EdgePosition := dpBottom; + Dec(EffectiveIndex); + end; + end; + end; + + try + SetCapture(Handle); + ScreenDC := GetDC(0); + with EffectivePanel do PanelRect := RectToScreen(BoundsRect); + DockRect := RectToScreen(Dock.ClientRect); + GetCursorPos(OrigCursorPos); + OldCursorPos := OrigCursorPos; + OrigEdgeRect := GetEdgeRect(PanelRect); + OldEdgeRect := Rect(0, 0, 0, 0); + EdgeRect := OrigEdgeRect; + FIsSplitting := True; + + if not Smooth then + begin + DrawDraggingOutline(ScreenDC, EdgeRect, Rect(0, 0, 0, 0)); + OldEdgeRect := EdgeRect; + EraseEdgeRect := True; + end + else EraseEdgeRect := False; + + while GetCapture = Handle do + begin + case Integer(GetMessage(Msg, 0, 0, 0)) of + -1: Break; + 0: begin + PostQuitMessage(Msg.WParam); + Break; + end; + end; + case Msg.Message of + WM_KEYDOWN, WM_KEYUP: if Msg.WParam = VK_ESCAPE then Break; + WM_MOUSEMOVE: MouseMoved; + WM_LBUTTONDOWN, WM_LBUTTONDBLCLK:Break; + WM_LBUTTONUP: Break; + WM_RBUTTONDOWN..WM_MBUTTONDBLCLK:; + else + TranslateMessage(Msg); + DispatchMessage(Msg); + end; + end; + finally + if GetCapture = Handle then ReleaseCapture; + CommitResizing := True; + if EraseEdgeRect then + begin + DrawDraggingOutline(ScreenDC, Rect(0, 0, 0, 0), OldEdgeRect); + if CommitResizing then SetSizes; + end + else if not CommitResizing then SetSizes(True); + ReleaseDC(0, ScreenDC); + FIsSplitting := False; + if csDesigning in ComponentState then + begin + Form := GetParentForm(Self); + if (Form <> nil) and (Form.Designer <> nil) then Form.Designer.Modified; + end; + end; +end; + +function TTBXCustomDockablePanel.CalcNCSizes: TPoint; +begin + if not Docked then + begin + Result.X := 0; + Result.Y := 0; + end + else + begin + Result.X := DockedBorderSize * 2; + Result.Y := DockedBorderSize * 2; + if ShowCaptionWhenDocked then + if IsVertCaption then Inc(Result.X, GetSystemMetrics(SM_CYSMCAPTION)) + else Inc(Result.Y, GetSystemMetrics(SM_CYSMCAPTION)); + end; +end; + +function TTBXCustomDockablePanel.CalcSize(ADock: TTBDock): TPoint; +begin + if Assigned(ADock) then + begin + if ADock.Position in [dpLeft, dpRight] then + begin + Result.X := FDockedWidth; + Result.Y := ADock.ClientHeight - CalcNCSizes.Y; + end + else + begin + Result.X := ADock.ClientWidth - CalcNCSizes.X; + Result.Y := FDockedHeight; + end; + end + else + begin + { if floating width and height are yet undefined, copy them from docked width and height } + if FFloatingWidth = 0 then + begin + if Docked and (CurrentDock.Position in [dpTop, dpBottom]) then + FFloatingWidth := Width {CurrentDock.ClientWidth} - CalcNCSizes.X + else + FFloatingWidth := FDockedWidth; + end; + + if FFloatingHeight = 0 then + begin + if Docked and (CurrentDock.Position in [dpLeft, dpRight]) then + FFloatingHeight := {CurrentDock.ClientHeight} Height - CalcNCSizes.Y + else + FFloatingHeight := FDockedHeight; + end; + + Result.X := FFloatingWidth; + Result.Y := FFloatingHeight; + end; +end; + +function TTBXCustomDockablePanel.CanAutoSize(var NewWidth, NewHeight: Integer): Boolean; +begin + Result := True; +end; + +function TTBXCustomDockablePanel.CanDockTo(ADock: TTBDock): Boolean; +begin + Result := inherited CanDockTo(ADock); + if Result then + begin + if ADock is TTBXMultiDock then + begin + Result := dkMultiDock in SupportedDocks; + end + else + begin + Result := dkStandardDock in SupportedDocks;; + end; + end; +end; + +function TTBXCustomDockablePanel.CanSplitResize(EdgePosition: TTBDockPosition): Boolean; +var + Dock: TDockAccess; +begin + Result := Docked and (CurrentDock is TTBXMultiDock) and HandleAllocated; + if not Result then Exit; + Dock := TDockAccess(CurrentDock); + ListSortEx(Dock.DockVisibleList, CompareEffectiveDockPos, nil); + if Dock.Position in [dpLeft, dpRight] then + begin + case EdgePosition of + dpTop: Result := EffectiveDockPos > 0; + dpBottom: Result := Dock.DockVisibleList.Last <> Self; + else + Result := False; + end; + end + else + begin + case EdgePosition of + dpLeft: Result := EffectiveDockPos > 0; + dpRight: Result := Dock.DockVisibleList.Last <> Self; + else + Result := False; + end; + end; +end; + +procedure TTBXCustomDockablePanel.CMColorChanged(var Message: TMessage); +begin + UpdateEffectiveColor; + Brush.Color := Color; + if Docked and HandleAllocated then + begin + RedrawWindow(Handle, nil, 0, RDW_FRAME or RDW_INVALIDATE or + RDW_ERASE or RDW_UPDATENOW or RDW_ALLCHILDREN); + end; + Invalidate; + UpdateChildColors; +end; + +procedure TTBXCustomDockablePanel.CMControlChange(var Message: TCMControlChange); +begin + inherited; + if Message.Inserting and (Color = clNone) then + Message.Control.Perform(CM_PARENTCOLORCHANGED, 1, EffectiveColor); +end; + +procedure TTBXCustomDockablePanel.CMTextChanged(var Message: TMessage); +begin + inherited; + if HandleAllocated then + begin + if Docked then RedrawWindow(Handle, nil, 0, RDW_FRAME or RDW_INVALIDATE) + else RedrawWindow(TTBXFloatingWindowParent(Parent).Handle, nil, 0, RDW_FRAME or RDW_INVALIDATE); + end; +end; + +procedure TTBXCustomDockablePanel.ConstrainedResize(var MinWidth, MinHeight, MaxWidth, MaxHeight: Integer); +var + Sz: TPoint; +begin + Sz := CalcNCSizes; + if MinClientWidth > 0 then MinWidth := MinClientWidth + Sz.X; + if MinClientHeight > 0 then MinHeight := MinClientHeight + Sz.Y; + if MaxClientWidth > 0 then MaxWidth := MaxClientWidth + Sz.X; + if MaxClientHeight > 0 then MaxHeight := MaxClientHeight + Sz.Y; +end; + +constructor TTBXCustomDockablePanel.Create(AOwner: TComponent); +begin + inherited; + FMinClientWidth := 32; + FMinClientHeight := 32; + FDockedWidth := 128; + FDockedHeight := 128; + FHorzResizeCursor := crSizeWE; {vb+} + FHorzSplitCursor := crHSplit; {vb+} + FVertResizeCursor := crSizeNS; {vb+} + FVertSplitCursor := crVSplit; {vb+} + CloseButtonWhenDocked := True; + DblClickUndock := False; + FShowCaptionWhenDocked := True; + FSmoothDockedResize := True; + BlockSizeUpdate := True; + SetBounds(Left, Top, 128, 128); + BlockSizeUpdate := False; + FullSize := True; + Color := clNone; + AddThemeNotification(Self); + SupportedDocks := [dkStandardDock, dkMultiDock]; +end; + +destructor TTBXCustomDockablePanel.Destroy; +begin + RemoveThemeNotification(Self); + inherited; +end; + +function TTBXCustomDockablePanel.DoArrange(CanMoveControls: Boolean; + PreviousDockType: TTBDockType; NewFloating: Boolean; NewDock: TTBDock): TPoint; +begin + Result := CalcSize(NewDock); +end; + +function TTBXCustomDockablePanel.DoBeginDockedResizing(Vertical: Boolean): Boolean; +var + Sz: Integer; +begin + Result := True; + if Vertical then Sz := Height else Sz := Width; + if Assigned(FOnDockedResizing) then FOnDockedResizing(Self, Vertical, Sz, rsBeginResizing, Result); + if Result then + if Vertical then Height := Sz else Width := Sz; +end; + +function TTBXCustomDockablePanel.DoDockedResizing(Vertical: Boolean; var NewSize: Integer): Boolean; +const + MIN_PARENT_CLIENT_SIZE = 32; +var + NCSizes: TPoint; + CW, CH: Integer; + DockParent: TWinControl; + ClientSize: TPoint; +begin + NCSizes := CalcNCSizes; + DockParent := Parent.Parent; + ClientSize := GetClientSizeEx(DockParent); + + Assert(DockParent <> nil); + if not Vertical then + begin + CW := ClientSize.X - MIN_PARENT_CLIENT_SIZE + Width; + if NewSize > CW then NewSize := CW; + CW := NewSize - NCSizes.X; + if CW < MinClientWidth then CW := MinClientWidth + else if (MaxClientWidth > MinClientWidth) and (CW > MaxClientWidth) then CW := MaxClientWidth; + NewSize := CW + NCSizes.X; + end + else + begin + CH := ClientSize.Y - MIN_PARENT_CLIENT_SIZE + Height; + if NewSize > CH then NewSize := CH; + CH := NewSize - NCSizes.Y; + if CH < MinClientHeight then CH := MinClientHeight + else if (MaxClientHeight > MinClientHeight) and (CH > MaxClientHeight) then CH := MaxClientHeight; + NewSize := CH + NCSizes.Y; + end; + Result := True; + if Assigned(FOnDockedResizing) then FOnDockedResizing(Self, Vertical, NewSize, rsResizing, Result); +end; + +function TTBXCustomDockablePanel.DoEndDockedResizing(Vertical: Boolean): Boolean; +var + Sz: Integer; +begin + Result := True; + if Vertical then Sz := Height else Sz := Width; + if Assigned(FOnDockedResizing) then + FOnDockedResizing(Self, Vertical, Sz, rsEndResizing, Result); + if Result then + if Vertical then Height := Sz else Width := Sz; +end; + +procedure TTBXCustomDockablePanel.DrawNCArea(const DrawToDC: Boolean; + const ADC: HDC; const Clip: HRGN); +var + DC: HDC; + R, CR: TRect; + ACanvas: TCanvas; + Sz: Integer; + DockPanelInfo: TTBXDockPanelInfo; + S: string; +begin + if not Docked or not HandleAllocated then Exit; + + if not DrawToDC then DC := GetWindowDC(Handle) + else DC := ADC; + + Assert(DC <> 0, 'TTBXToolWindow.DrawNCArea Error'); + try + GetDockPanelInfo(DockPanelInfo); + GetWindowRect(Handle, R); + OffsetRect(R, -R.Left, -R.Top); + if not DrawToDC then + begin + SelectNCUpdateRgn(Handle, DC, Clip); + CR := R; + with DockPanelInfo.BorderSize, CR do + begin + InflateRect(CR, -X, -Y); + if DockPanelInfo.ShowCaption then + begin + Sz := GetSystemMetrics(SM_CYSMCAPTION); + if DockPanelInfo.IsVertical then Inc(Top, Sz) + else Inc(Left, Sz); + end; + ExcludeClipRect(DC, Left, Top, Right, Bottom); + end; + end; + S := Caption; + DockPanelInfo.Caption := PChar(S); + ACanvas := TCanvas.Create; + try + ACanvas.Handle := DC; + ACanvas.Brush.Color := EffectiveColor; + CurrentTheme.PaintDockPanelNCArea(ACanvas, R, DockPanelInfo); + finally + ACanvas.Handle := 0; + ACanvas.Free; + end; + finally + if not DrawToDC then ReleaseDC(Handle, DC); + end; +end; + +procedure TTBXCustomDockablePanel.GetBaseSize(var ASize: TPoint); +begin + ASize := CalcSize(CurrentDock); +end; + +function TTBXCustomDockablePanel.GetDockedCloseButtonRect(LeftRight: Boolean): TRect; +var + X, Y, Z: Integer; +begin + Z := GetSystemMetrics(SM_CYSMCAPTION) - 1; + if LeftRight or not IsVertCaption then + begin + X := (ClientWidth + DockedBorderSize) - Z; + Y := DockedBorderSize; + end + else + begin + X := DockedBorderSize; + Y := ClientHeight + DockedBorderSize - Z; + end; + Result := Bounds(X, Y, Z, Z); +end; + +procedure TTBXCustomDockablePanel.GetDockPanelInfo(out DockPanelInfo: TTBXDockPanelInfo); +begin + FillChar(DockPanelInfo, SizeOf(DockPanelInfo), 0); + DockPanelInfo.WindowHandle := WindowHandle; + DockPanelInfo.ViewType := GetViewType; + if CurrentDock <> nil then DockPanelInfo.IsVertical := not IsVertCaption; + DockPanelInfo.AllowDrag := CurrentDock.AllowDrag; + DockPanelInfo.BorderStyle := BorderStyle; + CurrentTheme.GetViewBorder(DockPanelInfo.ViewType, DockPanelInfo.BorderSize); + DockPanelInfo.ClientWidth := ClientWidth; + DockPanelInfo.ClientHeight := ClientHeight; + DockPanelInfo.ShowCaption := ShowCaptionWhenDocked; + DockPanelInfo.EffectiveColor := EffectiveColor; + if ShowCaptionWhenDocked and CloseButtonWhenDocked then + begin + DockPanelInfo.CloseButtonState := CDBS_VISIBLE; + if CloseButtonDown then DockPanelInfo.CloseButtonState := DockPanelInfo.CloseButtonState or CDBS_PRESSED; + if CloseButtonHover then DockPanelInfo.CloseButtonState := DockPanelInfo.CloseButtonState or CDBS_HOT; + end; +end; + +function TTBXCustomDockablePanel.GetFloatingBorderSize: TPoint; +begin + CurrentTheme.GetViewBorder(GetViewType or DPVT_FLOATING, Result); +end; + +function TTBXCustomDockablePanel.GetFloatingWindowParentClass: TTBFloatingWindowParentClass; +begin + Result := TTBXFloatingWindowParent; +end; + +procedure TTBXCustomDockablePanel.GetMinMaxSize(var AMinClientWidth, AMinClientHeight, + AMaxClientWidth, AMaxClientHeight: Integer); +begin + AMinClientWidth := FMinClientWidth; + AMinClientHeight := FMinClientHeight; + AMaxClientWidth := FMaxClientWidth; + AMaxClientHeight := FMaxClientHeight; +end; + +function TTBXCustomDockablePanel.GetViewType: Integer; +begin + Result := DPVT_NORMAL; + if Floating then Result := Result or DPVT_FLOATING; + if Resizable then Result := Result or DPVT_RESIZABLE; +end; + +function TTBXCustomDockablePanel.IsVertCaption: Boolean; +begin + case CaptionRotation of + dpcrAlwaysHorz: Result := False; + dpcrAlwaysVert: Result := Docked; + else // dpcrAuto: + Result := Docked and (CurrentDock.Position in [dpTop, dpBottom]); + end; +end; + +procedure TTBXCustomDockablePanel.Loaded; +begin + inherited; + UpdateChildColors; +end; + +procedure TTBXCustomDockablePanel.Paint; +begin + if csDesigning in ComponentState then with Canvas do + begin + Pen.Style := psDot; + Pen.Color := clBtnShadow; + Brush.Style := bsClear; + with ClientRect do Rectangle(Left, Top, Right, Bottom); + Pen.Style := psSolid; + end; +end; + +procedure TTBXCustomDockablePanel.ReadPositionData(const Data: TTBReadPositionData); +begin + with Data do + begin + FDockedWidth := ReadIntProc(Name, rvDockedWidth, FDockedWidth, ExtraData); + FDockedHeight := ReadIntProc(Name, rvDockedHeight, FDockedHeight, ExtraData); + FFloatingWidth := ReadIntProc(Name, rvFloatingWidth, FFloatingWidth, ExtraData); + FFloatingHeight := ReadIntProc(Name, rvFloatingHeight, FFloatingHeight, ExtraData); + FSplitWidth := ReadIntProc(Name, rvSplitWidth, FSplitWidth, ExtraData); + FSplitHeight := ReadIntProc(Name, rvSplitHeight, FSplitHeight, ExtraData); + end; +end; + +procedure TTBXCustomDockablePanel.SetBorderSize(Value: Integer); +begin + if FBorderSize <> Value then + begin + FBorderSize := Value; + Realign; + end; +end; + +procedure TTBXCustomDockablePanel.SetBounds(ALeft, ATop, AWidth, AHeight: Integer); +begin + inherited SetBounds(ALeft, ATop, AWidth, AHeight); +end; + +procedure TTBXCustomDockablePanel.SetCaptionRotation(Value: TDPCaptionRotation); +begin + if FCaptionRotation <> Value then + begin + FCaptionRotation := Value; + if Docked and HandleAllocated then + SetWindowPos(Handle, 0, 0, 0, 0, 0, SWP_FRAMECHANGED or + SWP_NOACTIVATE or SWP_NOMOVE or SWP_NOSIZE or SWP_NOZORDER); + end; +end; + +procedure TTBXCustomDockablePanel.SetDockedHeight(Value: Integer); +begin + if Value < MinClientHeight then Value := MinClientHeight; + if Value <> FDockedHeight then + begin + FDockedHeight := Value; + if Docked and (CurrentDock.Position in [dpTop, dpBottom]) then + begin + BlockSizeUpdate := True; + Height := Value + CalcNCSizes.Y; + BlockSizeUpdate := False; + end; + end; +end; + +procedure TTBXCustomDockablePanel.SetDockedWidth(Value: Integer); +begin + if Value < MinClientWidth then Value := MinClientWidth; + if Value <> FDockedWidth then + begin + FDockedWidth := Value; + if Docked and (CurrentDock.Position in [dpLeft, dpRight]) then + begin + BlockSizeUpdate := True; + Width := Value + CalcNCSizes.X; + BlockSizeUpdate := False; + end; + end; +end; + +procedure TTBXCustomDockablePanel.SetFloatingHeight(Value: Integer); +begin + { FloatingHeight (and floating width) can be set to 0 while panel is docked. + This will force to restore floating dimensions from docked size } + if Value < 0 then Value := 0; + if not Docked and (Value < MinClientHeight) then Value := MinClientHeight; + if Value <> FFloatingHeight then + begin + FFloatingHeight := Value; + if not Docked then + begin + BlockSizeUpdate := True; + Height := Value + CalcNCSizes.Y; + BlockSizeUpdate := False; + end; + end; +end; + +procedure TTBXCustomDockablePanel.SetFloatingWidth(Value: Integer); +begin + { See comment for TTBXDockablePanel.SetFloatingHeight } + if Value < 0 then Value := 0; + if not Docked and (Value < MinClientWidth) then Value := MinClientWidth; + if Value <> FFloatingWidth then + begin + FFloatingWidth := Value; + if not Docked then + begin + BlockSizeUpdate := True; + Width := Value + CalcNCSizes.X; + BlockSizeUpdate := False; + end; + end; +end; + +procedure TTBXCustomDockablePanel.SetMinClientHeight(Value: Integer); +begin + if Value < 8 then Value := 8; + FMinClientHeight := Value; +end; + +procedure TTBXCustomDockablePanel.SetMinClientWidth(Value: Integer); +begin + if Value < 8 then Value := 8; + FMinClientWidth := Value; +end; + +procedure TTBXCustomDockablePanel.SetParent(AParent: TWinControl); +begin + inherited; + if AParent is TTBXFloatingWindowParent then + TTBXFloatingWindowParent(AParent).SnapDistance := SnapDistance; +end; + +procedure TTBXCustomDockablePanel.SetShowCaptionWhenDocked(Value: Boolean); +begin + if FShowCaptionWhenDocked <> Value then + begin + FShowCaptionWhenDocked := Value; + if Docked then + begin + if HandleAllocated then + SetWindowPos(Handle, 0, 0, 0, 0, 0, SWP_FRAMECHANGED or + SWP_NOACTIVATE or SWP_NOMOVE or SWP_NOSIZE or SWP_NOZORDER); + end; + end; +end; + +procedure TTBXCustomDockablePanel.SetSnapDistance(Value: Integer); +begin + if Value < 0 then Value := 0; + FSnapDistance := Value; + if (Parent <> nil) and (Parent is TTBXFloatingWindowParent) then + TTBXFloatingWindowParent(Parent).SnapDistance := Value; +end; + +procedure TTBXCustomDockablePanel.SetSplitHeight(Value: Integer); +begin + if Value < 0 then Value := 0; + if FSplitHeight <> Value then + begin + FSplitHeight := Value; + if Docked and (CurrentDock.Position in [dpLeft, dpRight]) and + (CurrentDock is TTBXMultiDock) then CurrentDock.ArrangeToolbars; + end; +end; + +procedure TTBXCustomDockablePanel.SetSplitWidth(Value: Integer); +begin + if Value < 0 then Value := 0; + if FSplitWidth <> Value then + begin + FSplitWidth := Value; + if Docked and (CurrentDock.Position in [dpTop, dpBottom]) and + (CurrentDock is TTBXMultiDock) then CurrentDock.ArrangeToolbars; + end; +end; + +procedure TTBXCustomDockablePanel.SizeChanging(const AWidth, AHeight: Integer); +begin + if not BlockSizeUpdate then + begin + if Docked and (CurrentDock.Position in [dpLeft, dpRight]) then + FDockedWidth := AWidth - CalcNCSizes.X + else if Floating then + FFloatingWidth := AWidth - CalcNCSizes.X; + + if Docked and (CurrentDock.Position in [dpTop, dpBottom]) then + FDockedHeight := AHeight - CalcNCSizes.Y + else if Floating then + FFloatingHeight := AHeight - CalcNCSizes.Y; + end; +end; + +procedure TTBXCustomDockablePanel.TBMGetEffectiveColor(var Message: TMessage); +begin + Message.WParam := EffectiveColor; + Message.Result := 1; +end; + +procedure TTBXCustomDockablePanel.TBMGetViewType(var Message: TMessage); +begin + Message.Result := GetViewType; +end; + +procedure TTBXCustomDockablePanel.TBMThemeChange(var Message: TMessage); +var + M: TMessage; +begin + case Message.WParam of + TSC_BEFOREVIEWCHANGE: BeginUpdate; + TSC_AFTERVIEWCHANGE: + begin + EndUpdate; + UpdateEffectiveColor; + + if HandleAllocated and not (csDestroying in ComponentState) and + (Parent is TTBXFloatingWindowParent) then + UpdateNCArea(TTBXFloatingWindowParent(Parent), GetViewType) + else + UpdateNCArea(Self, GetViewType); + + Invalidate; + + M.Msg := CM_PARENTCOLORCHANGED; + M.WParam := 1; + M.LParam := EffectiveColor; + M.Result := 0; + Broadcast(M); + end; + end; +end; + +procedure TTBXCustomDockablePanel.UpdateChildColors; +var + M: TMessage; +begin + M.Msg := CM_PARENTCOLORCHANGED; + M.WParam := 1; + M.LParam := EffectiveColor; + M.Result := 0; + Broadcast(M); +end; + +procedure TTBXCustomDockablePanel.UpdateEffectiveColor; +begin + if Color = clNone then FEffectiveColor := CurrentTheme.GetViewColor(GetViewType) + else FEffectiveColor := Color; +end; + +procedure TTBXCustomDockablePanel.WMEraseBkgnd(var Message: TWMEraseBkgnd); +var + BRUSH: HBRUSH; +begin + BRUSH := CreateSolidBrush(ColorToRGB(EffectiveColor)); + FillRect(Message.DC, Clientrect, BRUSH); + DeleteObject(BRUSH); + Message.Result := 1; +end; + +procedure TTBXCustomDockablePanel.WMNCCalcSize(var Message: TWMNCCalcSize); +begin + Message.Result := 0; + if Docked then + with Message.CalcSize_Params^ do + begin + InflateRect(rgrc[0], -DockedBorderSize, -DockedBorderSize); + if ShowCaptionWhenDocked then + if IsVertCaption then Inc(rgrc[0].Left, GetSystemMetrics(SM_CYSMCAPTION)) + else Inc(rgrc[0].Top, GetSystemMetrics(SM_CYSMCAPTION)) + end; +end; + +procedure TTBXCustomDockablePanel.WMNCHitTest(var Message: TWMNCHitTest); +const + CResizeMargin = 2; +var + P: TPoint; + R: TRect; + Sz: Integer; + IsVertical, UseDefaultHandler: Boolean; +begin + if Docked then + begin + UseDefaultHandler := False; + if csDesigning in ComponentState then with Message do + begin + P := SmallPointToPoint(Pos); + GetWindowRect(Handle, R); + if PtInRect(R, P) then + begin + Result := 0; + case CurrentDock.Position of + dpLeft: if P.X >= R.Right - CResizeMargin then Result := HTRIGHT; + dpTop: if P.Y >= R.Bottom - CResizeMargin then Result := HTBOTTOM; + dpRight: if P.X <= R.Left + CResizeMargin then Result := HTLEFT; + dpBottom: if P.Y <= R.Top + CResizeMargin then Result := HTTOP; + end; + if Result = 0 then + begin + if (P.X >= R.Right - CResizeMargin) and CanSplitResize(dpRight) then Result := HT_TBX_SPLITRESIZERIGHT + else if (P.Y >= R.Bottom - CResizeMargin) and CanSplitResize(dpBottom) then Result := HT_TBX_SPLITRESIZEBOTTOM + else if (P.X <= R.Left + CResizeMargin) and CanSplitResize(dpLeft) then Result := HT_TBX_SPLITRESIZELEFT + else if (P.Y <= R.Top + CResizeMargin) and CanSplitResize(dpTop) then Result := HT_TBX_SPLITRESIZETOP; + end; + UseDefaultHandler := Result <> 0; + end; + if UseDefaultHandler then DefaultHandler(Message) + else inherited; + end; + + with Message do + begin + P := SmallPointToPoint(Pos); + GetWindowRect(Handle, R); + if Resizable then + case CurrentDock.Position of + dpLeft: if P.X >= R.Right - CResizeMargin then Result := HTRIGHT; + dpTop: if P.Y >= R.Bottom - CResizeMargin then Result := HTBOTTOM; + dpRight: if P.X <= R.Left + CResizeMargin then Result := HTLEFT; + dpBottom: if P.Y <= R.Top + CResizeMargin then Result := HTTOP; + end; + if Result = 0 then + begin + if (P.X >= R.Right - CResizeMargin) and CanSplitResize(dpRight) then Result := HT_TBX_SPLITRESIZERIGHT + else if (P.Y >= R.Bottom - CResizeMargin) and CanSplitResize(dpBottom) then Result := HT_TBX_SPLITRESIZEBOTTOM + else if (P.X <= R.Left + CResizeMargin) and CanSplitResize(dpLeft) then Result := HT_TBX_SPLITRESIZELEFT + else if (P.Y <= R.Top + CResizeMargin) and CanSplitResize(dpTop) then Result := HT_TBX_SPLITRESIZETOP; + end; + if (Result <> HTCLIENT) and ((Result < HTLEFT) or (Result > HTBOTTOM)) and + ((Result < HT_TBX_SPLITRESIZELEFT) or (Result > HT_TBX_SPLITRESIZEBOTTOM)) then + begin + Result := HTNOWHERE; + InflateRect(R, -DockedBorderSize, -DockedBorderSize); + + if PtInRect(R, P) and ShowCaptionWhenDocked and not (csDesigning in ComponentState) then + begin + { caption area } + IsVertical := not IsVertCaption; + if CloseButtonWhenDocked then + begin + Sz := GetSystemMetrics(SM_CYSMCAPTION); + if IsVertical then Inc(Sz, 4) else Dec(Sz, 4); + end + else Sz := 0; + + if (IsVertical and (P.X >= R.Right - Sz) and (P.Y < R.Top + Sz)) or + (not IsVertical and (P.Y >= R.Bottom - Sz) and (P.X < R.Left + Sz)) then + Result := HT_TB2k_Close + else + Result := HT_TB2k_Border; + end; + end; + end; + end + else inherited; +end; + +procedure TTBXCustomDockablePanel.WMNCLButtonDown(var Message: TWMNCLButtonDown); +var + OldCursor: HCURSOR; +begin + if Message.HitTest in [HTLEFT..HTBOTTOM] then BeginDockedSizing(Message.HitTest) + else if Message.HitTest in [HT_TBX_SPLITRESIZELEFT..HT_TBX_SPLITRESIZEBOTTOM] then BeginSplitResizing(Message.HitTest) + else + begin + if (Message.HitTest = HT_TB2k_Border) and IsMovable then + begin + OldCursor := SetCursor(LoadCursor(0, IDC_SIZEALL)); + try + inherited; + finally + SetCursor(OldCursor); + end; + end + else inherited; + end; +end; + +procedure TTBXCustomDockablePanel.WMSetCursor(var Message: TWMSetCursor); +var Cur: TCursor; {vb+} +begin + {if Docked and CurrentDock.AllowDrag and + (Message.CursorWnd = WindowHandle) and + (Smallint(Message.HitTest) = HT_TB2k_Border) and + ShowCaptionWhenDocked then + begin + SetCursor(LoadCursor(0, IDC_ARROW)); + Message.Result := 1; + Exit; + end + else if Docked and CurrentDock.AllowDrag and (Message.CursorWnd = WindowHandle) then + begin + if (Message.HitTest = HT_TBX_SPLITRESIZELEFT) or (Message.HitTest = HT_TBX_SPLITRESIZERIGHT) then + begin + SetCursor(LoadCursor(0, IDC_SIZEWE)); + Message.Result := 1; + Exit; + end + else if (Message.HitTest = HT_TBX_SPLITRESIZETOP) or (Message.HitTest = HT_TBX_SPLITRESIZEBOTTOM) then + begin + SetCursor(LoadCursor(0, IDC_SIZENS)); + Message.Result := 1; + Exit; + end; + end; } {vb-} + if Docked and CurrentDock.AllowDrag and + (Message.CursorWnd = WindowHandle) then + begin + Cur := crNone; + case Message.HitTest of + HTLEFT, HTRIGHT: + Cur := HorzResizeCursor; + HTTOP, HTBOTTOM: + Cur := VertResizeCursor; + HT_TBX_SPLITRESIZELEFT, HT_TBX_SPLITRESIZERIGHT: + Cur := HorzSplitCursor; + HT_TBX_SPLITRESIZETOP, HT_TBX_SPLITRESIZEBOTTOM: + Cur := VertSplitCursor; + HT_TB2k_Border: + if ShowCaptionWhenDocked then Cur := crArrow; + end; + if Cur <> crNone then + begin + SetCursor(Screen.Cursors[Cur]); + Message.Result := 1; + Exit; + end; + end; + inherited; +end; + +procedure TTBXCustomDockablePanel.WMWindowPosChanged(var Message: TWMWindowPosChanged); +begin + inherited; + if (Message.WindowPos^.flags and SWP_NOSIZE) = 0 then + begin + Realign; + Update; + end; + if (Message.WindowPos^.flags and SWP_SHOWWINDOW) <> 0 then + begin + UpdateEffectiveColor; + UpdateChildColors; + end; +end; + +procedure TTBXCustomDockablePanel.WritePositionData(const Data: TTBWritePositionData); +begin + with Data do + begin + WriteIntProc(Name, rvDockedWidth, FDockedWidth, ExtraData); + WriteIntProc(Name, rvDockedHeight, FDockedHeight, ExtraData); + WriteIntProc(Name, rvFloatingWidth, FFloatingWidth, ExtraData); + WriteIntProc(Name, rvFloatingHeight, FFloatingHeight, ExtraData); + WriteIntProc(Name, rvSplitWidth, FSplitWidth, ExtraData); + WriteIntProc(Name, rvSplitHeight, FSplitHeight, ExtraData); + end; +end; + +//----------------------------------------------------------------------------// + +{ TTBXTextObject } + +procedure TTBXTextObject.AdjustFont(AFont: TFont); +begin +end; + +procedure TTBXTextObject.AdjustHeight; +var + NewHeight: Integer; +begin + if HandleAllocated and not FUpdating and ([csReading, csLoading] * ComponentState = []) and AutoSize then + begin + FUpdating := True; + try + NewHeight := 0; + DoAdjustHeight(StockCompatibleBitmap.Canvas, NewHeight); + SetBounds(Left, Top, Width, NewHeight); + finally + FUpdating := False; + end; + end; +end; + +function TTBXTextObject.CanAutoSize(var NewWidth, NewHeight: Integer): Boolean; +begin + if not FUpdating and ([csReading, csLoading] * ComponentState = []) and AutoSize then + begin + FUpdating := True; + try + NewHeight := 0; + DoAdjustHeight(StockCompatibleBitmap.Canvas, NewHeight); + Result := True; + finally + FUpdating := False; + end; + end + else Result := False; +end; + +procedure TTBXTextObject.CMEnabledChanged(var Message: TMessage); +begin + inherited; + Invalidate; +end; + +procedure TTBXTextObject.CMFontChanged(var Message: TMessage); +begin + inherited; + Invalidate; + AdjustHeight; +end; + +procedure TTBXTextObject.CMTextChanged(var Message: TMessage); +begin + inherited; + Invalidate; + AdjustHeight; +end; + +constructor TTBXTextObject.Create(AOwner: TComponent); +begin + inherited; + ControlStyle := ControlStyle + [csSetCaption, csDoubleClicks]; + FMargins := TTBXControlMargins.Create; + FMargins.OnChange := MarginsChangeHandler; + FShowAccelChar := True; + PaintOptions := [cpoDoubleBuffered]; + AutoSize := True; + Width := 100; +end; + +procedure TTBXTextObject.CreateParams(var Params: TCreateParams); +begin + inherited; + if not (csDesigning in ComponentState) then + with Params.WindowClass do style := style or CS_HREDRAW; +end; + +destructor TTBXTextObject.Destroy; +begin + FMargins.Free; + inherited; +end; + +procedure TTBXTextObject.DoAdjustHeight(ACanvas: TCanvas; var NewHeight: Integer); +const + WordWraps: array [TTextWrapping] of Word = (0, DT_END_ELLIPSIS, DT_PATH_ELLIPSIS, DT_WORDBREAK); +var + R: TRect; + EffectiveMargins: TRect; +begin + R := ClientRect; + EffectiveMargins := GetTextMargins; + with Margins do + begin + Inc(EffectiveMargins.Left, Left); Inc(EffectiveMargins.Right, Right); + Inc(EffectiveMargins.Top, Top); Inc(EffectiveMargins.Bottom, Bottom); + end; + ApplyMargins(R, EffectiveMargins); + NewHeight := DoDrawText(ACanvas, R, (DT_EXPANDTABS or DT_CALCRECT) or WordWraps[Wrapping]); + with EffectiveMargins do Inc(NewHeight, Top + Bottom); +end; + +function TTBXTextObject.DoDrawText(ACanvas: TCanvas; var Rect: TRect; Flags: Integer): Integer; +var + Text: string; +begin + Text := GetLabelText; + if (Flags and DT_CALCRECT <> 0) and ((Text = '') or + (Text[1] = '&') and (Text[2] = #0)) then Text := Text + ' '; + Flags := DrawTextBiDiModeFlags(Flags); + ACanvas.Font := Font; + AdjustFont(ACanvas.Font); + + if Flags and DT_CALCRECT = DT_CALCRECT then + begin + Flags := Flags and not DT_VCENTER; + Result := DrawText(ACanvas.Handle, PChar(Text), Length(Text), Rect, Flags); + end + else if not Enabled then + begin + OffsetRect(Rect, 1, 1); + ACanvas.Font.Color := clBtnHighlight; + DrawText(ACanvas.Handle, PChar(Text), Length(Text), Rect, Flags); + OffsetRect(Rect, -1, -1); + ACanvas.Font.Color := clBtnShadow; + Result := DrawText(ACanvas.Handle, PChar(Text), Length(Text), Rect, Flags); + end + else + begin + Result := DrawText(ACanvas.Handle, PChar(Text), Length(Text), Rect, Flags); + end; +end; + +procedure TTBXTextObject.DoMarginsChanged; +begin + Invalidate; + AdjustHeight; +end; + +function TTBXTextObject.GetControlsAlignment: TAlignment; +begin + Result := FAlignment; +end; + +function TTBXTextObject.GetFocusRect(const R: TRect): TRect; +begin + { R is the client rectangle without the margins } + Result := Rect(0, 0, 0, 0); +end; + +function TTBXTextObject.GetLabelText: string; +begin + Result := Caption; +end; + +function TTBXTextObject.GetTextAlignment: TAlignment; +begin + Result := Alignment; +end; + +function TTBXTextObject.GetTextMargins: TRect; +const + ZeroRect: TRect = (Left: 0; Top: 0; Right: 0; Bottom: 0); +begin + Result := ZeroRect; +end; + +procedure TTBXTextObject.Loaded; +begin + inherited; + AdjustHeight; +end; + +procedure TTBXTextObject.MarginsChangeHandler(Sender: TObject); +begin + DoMarginsChanged; +end; + +procedure TTBXTextObject.Paint; +const + Alignments: array [TAlignment] of Integer = (DT_LEFT, DT_RIGHT, DT_CENTER); + WordWraps: array [TTextWrapping] of Integer = (DT_SINGLELINE, + DT_SINGLELINE or DT_END_ELLIPSIS, + DT_SINGLELINE or DT_PATH_ELLIPSIS, DT_WORDBREAK); + ShowAccelChars: array [Boolean] of Integer = (DT_NOPREFIX, 0); +var + R, R2: TRect; + DrawStyle: Longint; + CaptionHeight: Integer; +begin + with Canvas do + begin + R := ClientRect; + ApplyMargins(R, Margins); + if Focused then DrawFocusRect2(Canvas, GetFocusRect(R)); + DrawStyle := DT_EXPANDTABS or WordWraps[Wrapping] or + Alignments[GetRealAlignment(Self)] or ShowAccelChars[ShowAccelChar]; + Brush.Style := bsClear; + ApplyMargins(R, GetTextMargins); + R2 := R; + CaptionHeight := DoDrawText(Canvas, R2, DrawStyle or DT_CALCRECT); + R.Top := (R.Top + R.Bottom - CaptionHeight) div 2; + R.Bottom := R.Top + CaptionHeight; + DoDrawText(Canvas, R, DrawStyle); + Brush.Style := bsSolid; + end; +end; + +procedure TTBXTextObject.SetAlignment(Value: TLeftRight); +begin + FAlignment := Value; + Invalidate; +end; + +procedure TTBXTextObject.SetMargins(Value: TTBXControlMargins); +begin + FMargins.Assign(Value); +end; + +procedure TTBXTextObject.SetShowAccelChar(Value: Boolean); +begin + if FShowAccelChar <> Value then + begin + FShowAccelChar := Value; + AdjustHeight; + Invalidate; + end; +end; + +procedure TTBXTextObject.SetWrapping(Value: TTextWrapping); +begin + FWrapping := Value; + Invalidate; + AdjustHeight; +end; + +//----------------------------------------------------------------------------// + +{ TTBXCustomLabel } + +procedure TTBXCustomLabel.CMDialogChar(var Message: TCMDialogChar); +begin + if (FFocusControl <> nil) and Enabled and ShowAccelChar and IsAccel(Message.CharCode, Caption) then + with FFocusControl do if CanFocus then + begin + SetFocus; + Message.Result := 1; + end; +end; + +constructor TTBXCustomLabel.Create(AOwner: TComponent); +begin + inherited; + Wrapping := twWrap; + FUnderlineColor := clBtnShadow; + TabStop := False; +end; + +function TTBXCustomLabel.GetTextMargins: TRect; +const + BottomMargin: array [Boolean] of Integer = (0, 1); +begin + with Result do + begin + Left := 0; + Top := 0; + Right := 0; + Result.Bottom := BottomMargin[Underline]; + end; +end; + +procedure TTBXCustomLabel.Notification(AComponent: TComponent; Operation: TOperation); +begin + inherited; + inherited Notification(AComponent, Operation); + if (Operation = opRemove) and (AComponent = FFocusControl) then FFocusControl := nil; +end; + +procedure TTBXCustomLabel.Paint; +var + Rect: TRect; +begin + inherited; + if Underline then with Canvas do + begin + Rect := ClientRect; + ApplyMargins(Rect, Margins); + ApplyMargins(Rect, GetTextMargins); + Pen.Color := UnderlineColor; + MoveTo(Rect.Left, Rect.Bottom); + LineTo(Rect.Right, Rect.Bottom); + end; +end; + +procedure TTBXCustomLabel.SetFocusControl(Value: TWinControl); +begin + if FFocusControl <> Value then + begin + if FFocusControl <> nil then FFocusControl.RemoveFreeNotification(Self); + FFocusControl := Value; + if FFocusControl <> nil then FFocusControl.FreeNotification(Self); + end; +end; + +procedure TTBXCustomLabel.SetUnderline(Value: Boolean); +begin + if Value <> FUnderline then + begin + FUnderline := Value; + Invalidate; + AdjustHeight; + end; +end; + +procedure TTBXCustomLabel.SetUnderlineColor(Value: TColor); +begin + FUnderlineColor := Value; + Invalidate; +end; + +//----------------------------------------------------------------------------// + +{ TTBXCustomLink } + +procedure TTBXCustomLink.AdjustFont(AFont: TFont); +begin + if MouseInControl then AFont.Style := AFont.Style + [fsUnderline]; +end; + +procedure TTBXCustomLink.CMDialogChar(var Message: TCMDialogChar); +begin + with Message do + if Enabled and ShowAccelChar and IsAccel(CharCode, GetLabelText) and CanFocus and Visible then + begin + Click; + Result := 1; + end + else inherited; +end; + +procedure TTBXCustomLink.CMDialogKey(var Message: TCMDialogKey); +begin + with Message do + if (CharCode = VK_RETURN) and Focused and + (KeyDataToShiftState(Message.KeyData) = []) then + begin + Click; + Result := 1; + end + else inherited; +end; + +constructor TTBXCustomLink.Create(AOwner: TComponent); +begin + inherited; + FImageChangeLink := TChangeLink.Create; + FImageChangeLink.OnChange := ImageListChange; + SmartFocus := True; + SpaceAsClick := True; + TabStop := True; + Cursor := crHandPoint; +end; + +destructor TTBXCustomLink.Destroy; +begin + FImageChangeLink.Free; + inherited; +end; + +procedure TTBXCustomLink.DoAdjustHeight(ACanvas: TCanvas; var NewHeight: Integer); +begin + inherited DoAdjustHeight(ACanvas, NewHeight); + if Images <> nil then + if NewHeight < Images.Height + 4 then NewHeight := Images.Height + 4; +end; + +procedure TTBXCustomLink.DoMouseEnter; +begin + inherited; + Invalidate; +end; + +procedure TTBXCustomLink.DoMouseLeave; +begin + inherited; + Invalidate; +end; + +function TTBXCustomLink.GetControlsAlignment: TAlignment; +begin + Result := GetTextAlignment; +end; + +function TTBXCustomLink.GetFocusRect(const R: TRect): TRect; +const + WordWraps: array [TTextWrapping] of Integer = (DT_SINGLELINE or DT_VCENTER, + DT_SINGLELINE or DT_VCENTER or DT_END_ELLIPSIS, + DT_SINGLELINE or DT_VCENTER or DT_PATH_ELLIPSIS, DT_WORDBREAK); +var + TR: TRect; + ShowImage: Boolean; +begin + Result := R; + ShowImage := Assigned(Images) and (ImageIndex >= 0) and (ImageIndex < Images.Count); + + { Text Rectangle } + TR := R; + ApplyMargins(TR, GetTextMargins); + DoDrawText(Canvas, TR, (DT_EXPANDTABS or DT_CALCRECT) or WordWraps[Wrapping] or DT_LEFT); + + if ShowImage then + begin + if GetRealAlignment(Self) = taLeftJustify then + begin + Result.Left := R.Left; + Result.Right := TR.Right; + end + else + begin + Result.Left := TR.Left; + Result.Right := R.Right; + end; + end + else + begin + Result.Right := TR.Right; + Result.Left := TR.Left; + end; + Dec(Result.Left, 2); + Inc(Result.Right, 2); +end; + +function TTBXCustomLink.GetTextAlignment: TAlignment; +begin + Result := taLeftJustify; +end; + +function TTBXCustomLink.GetTextMargins: TRect; +begin + Result := Rect(2, 1, 2, 1); + if Assigned(Images) then with Result do + begin + if GetRealAlignment(Self) = taLeftJustify then Inc(Left, Images.Width + 5) + else Inc(Right, Images.Width + 5); + end; +end; + +procedure TTBXCustomLink.ImageListChange(Sender: TObject); +begin + if Sender = Images then + begin + Invalidate; + AdjustHeight; + end; +end; + +procedure TTBXCustomLink.Notification(AComponent: TComponent; Operation: TOperation); +begin + inherited; + if (AComponent = Images) and (Operation = opRemove) then Images := nil; +end; + +procedure TTBXCustomLink.Paint; +var + Rect, R: TRect; +begin + inherited; + if Assigned(Images) and (ImageIndex >= 0) and (ImageIndex < Images.Count) then + with Canvas do + begin + Rect := ClientRect; + ApplyMargins(Rect, Margins); + + if GetRealAlignment(Self) = taLeftJustify then R.Left := Rect.Left + 2 + else R.Left := Rect.Right - 2 - Images.Width; + + R.Top := (Rect.Top + Rect.Bottom - Images.Height) div 2; + R.Right := R.Left + Images.Width; + R.Bottom := R.Top + Images.Height; + + if Enabled then Images.Draw(Canvas, R.Left, R.Top, ImageIndex) + else DrawTBXImage(Canvas, R, Images, ImageIndex, ISF_DISABLED); + end; +end; + +procedure TTBXCustomLink.SetImageIndex(Value: TImageIndex); +begin + if FImageIndex <> Value then + begin + FImageIndex := Value; + if Assigned(Images) then Invalidate; + end; +end; + +procedure TTBXCustomLink.SetImages(Value: TCustomImageList); +begin + if FImages <> nil then FImages.UnRegisterChanges(FImageChangeLink); + FImages := Value; + if FImages <> nil then + begin + FImages.RegisterChanges(FImageChangeLink); + FImages.FreeNotification(Self); + end; + Invalidate; + AdjustHeight; +end; + +procedure TTBXCustomLink.WMNCHitTest(var Message: TWMNCHitTest); +var + P: TPoint; + R: TRect; +begin + inherited; + if not (csDesigning in ComponentState) then + begin + P := ScreenToClient(SmallPointToPoint(Message.Pos)); + R := ClientRect; + ApplyMargins(R, Margins); + R := GetFocusRect(R); + if not PtInRect(R, P) then Message.Result := HTTRANSPARENT; + end; +end; + +//----------------------------------------------------------------------------// + +{ TTBXCustomButton } + +function TTBXCustomButton.ArrowVisible: Boolean; +begin + Result := DropDownMenu <> nil; +end; + +procedure TTBXCustomButton.Click; +var + Form: TCustomForm; + Pt: TPoint; + R: TRect; + SaveAlignment: TPopupAlignment; + + procedure RemoveClicks; + var + RepostList: TList; + Repost: Boolean; + I: Integer; + Msg: TMsg; + P: TPoint; + begin + RepostList := TList.Create; + try + while PeekMessage(Msg, 0, WM_LBUTTONDOWN, WM_MBUTTONDBLCLK, PM_REMOVE) do + with Msg do + begin + Repost := True; + case Message of + WM_QUIT: begin + { Throw back any WM_QUIT messages } + PostQuitMessage(wParam); + Break; + end; + WM_LBUTTONDOWN, WM_LBUTTONDBLCLK, + WM_RBUTTONDOWN, WM_RBUTTONDBLCLK, + WM_MBUTTONDOWN, WM_MBUTTONDBLCLK: begin + P := SmallPointToPoint(TSmallPoint(lParam)); + Windows.ClientToScreen(hwnd, P); + if FindDragTarget(P, True) = Self then Repost := False; + end; + end; + if Repost then + begin + RepostList.Add(AllocMem(SizeOf(TMsg))); + PMsg(RepostList.Last)^ := Msg; + end; + end; + finally + for I := 0 to RepostList.Count-1 do + begin + with PMsg(RepostList[I])^ do PostMessage(hwnd, message, wParam, lParam); + FreeMem(RepostList[I]); + end; + RepostList.Free; + end; + end; + +begin + if FRepeating and not FMenuVisible then inherited + else + try + FInClick := True; + if (GroupIndex <> 0) and not FMenuVisible then SetChecked(not Checked); + MouseLeft; + if (DropDownMenu = nil) or (DropDownCombo and not FMenuVisible) then + begin + if ModalResult <> 0 then + begin + Form := GetParentForm(Self); + if Form <> nil then Form.ModalResult := ModalResult; + end; + inherited; + end + else + begin + MouseCapture := False; + SaveAlignment := paLeft; // to avoid compiler warnings + if DoDropDown then + try + Pt := Point(0, Height); + Pt := ClientToScreen(Pt); + SaveAlignment := DropDownMenu.Alignment; + DropDownMenu.PopupComponent := Self; + + if DropDownMenu is TTBXPopupMenu then + begin + R := ClientRect; + ApplyMargins(R, Margins); + R.TopLeft := ClientToScreen(R.TopLeft); + R.BottomRight := ClientToScreen(R.BottomRight); + TTBXPopupMenu(DropDownMenu).PopupEx(R); + end + else DropDownMenu.Popup(Pt.X, Pt.Y); + finally + DropDownMenu.Alignment := SaveAlignment; + if Pushed then FPushed := False; + Invalidate; + RemoveClicks; + end + else inherited; + end; + finally + FInClick := False; + end; +end; + +procedure TTBXCustomButton.CMDialogChar(var Message: TCMDialogChar); +begin + with Message do + if Enabled and ShowAccelChar and IsAccel(CharCode, GetLabelText) and CanFocus and Visible then + begin + Click; + Result := 1; + end + else inherited; +end; + +procedure TTBXCustomButton.CMDialogKey(var Message: TCMDialogKey); +begin + with Message do + if (CharCode = VK_RETURN) and Focused and + (KeyDataToShiftState(Message.KeyData) = []) then + begin + Click; + Result := 1; + end + else inherited; +end; + +constructor TTBXCustomButton.Create(AOwner: TComponent); +begin + inherited; + FAlignment := taCenter; + FBorderSize := 4; + FGlyphSpacing := 4; + FImageChangeLink := TChangeLink.Create; + FImageChangeLink.OnChange := ImageListChange; + FRepeatDelay := 400; + FRepeatInterval := 100; + SmartFocus := True; + SpaceAsClick := True; + TabStop := True; +end; + +destructor TTBXCustomButton.Destroy; +begin + FImageChangeLink.Free; + inherited; +end; + +procedure TTBXCustomButton.DoAdjustHeight(ACanvas: TCanvas; var NewHeight: Integer); +var + Sz: Integer; +begin + if Length(GetLabelText) = 0 then + begin + if Images <> nil then NewHeight := Images.Height + BorderSize * 2 + else if BorderSize * 2 >= 16 then NewHeight := BorderSize * 2 + else NewHeight := 16; + end + else + begin + inherited DoAdjustHeight(ACanvas, NewHeight); + if Images <> nil then + if Layout in [blGlyphLeft, blGlyphRight] then + begin + Sz := Images.Height + BorderSize * 2; + if NewHeight < Sz then NewHeight := Sz; + end; + end; +end; + +function TTBXCustomButton.DoDrawText(ACanvas: TCanvas; var Rect: TRect; Flags: Integer): Integer; +var + ItemInfo: TTBXItemInfo; + Text: string; +begin + Text := GetLabelText; + if (Flags and DT_CALCRECT <> 0) and ((Text = '') or + (Text[1] = '&') and (Text[2] = #0)) then Text := Text + ' '; + Flags := DrawTextBiDiModeFlags(Flags); + ACanvas.Font := Font; + AdjustFont(ACanvas.Font); + + if Flags and DT_CALCRECT = DT_CALCRECT then + begin + Flags := Flags and not DT_VCENTER; + Result := DrawText(ACanvas.Handle, PChar(Text), Length(Text), Rect, Flags); + end + else + begin + GetItemInfo(ItemInfo); + ACanvas.Font.Color := clNone; + CurrentTheme.PaintCaption(Canvas, Rect, ItemInfo, Text, Flags, False); + Flags := Flags or DT_CALCRECT; + Result := DrawText(ACanvas.Handle, PChar(Text), Length(Text), Rect, Flags); + end; +end; + +function TTBXCustomButton.DoDropDown: Boolean; +begin + Result := FDropDownMenu <> nil; + if Result and Assigned(FOnDropDown) then FOnDropDown(Self, Result); +end; + +procedure TTBXCustomButton.DoMouseEnter; +begin + inherited; + Invalidate; +end; + +procedure TTBXCustomButton.DoMouseLeave; +begin + inherited; + Invalidate; +end; + +function TTBXCustomButton.GetControlsAlignment: TAlignment; +begin + Result := GetTextAlignment; +end; + +function TTBXCustomButton.GetFocusRect(const R: TRect): TRect; +begin + Result := R; + InflateRect(Result, -2, -2); +end; + +procedure TTBXCustomButton.GetItemInfo(out ItemInfo: TTBXItemInfo); +const + ViewTypes: array [TButtonStyle] of Integer = + (VT_TOOLBAR or TVT_EMBEDDED, VT_TOOLBAR); +begin + FillChar(ItemInfo, SizeOf(ItemInfo), 0); + ItemInfo.ViewType := ViewTypes[ButtonStyle]; + ItemInfo.Enabled := Enabled; + ItemInfo.ItemOptions := IO_TOOLBARSTYLE or IO_APPACTIVE; + ItemInfo.Pushed := Pushed and (MouseInControl or FMenuVisible); + if FMenuVisible and DropDownCombo then ItemInfo.Pushed := False; + if FMenuVisible then ItemInfo.IsPopupParent := True; + ItemInfo.Selected := Checked; + ItemInfo.IsVertical := False; + if ArrowVisible and DropDownCombo then ItemInfo.ComboPart := cpCombo; + if MouseInControl or FMenuVisible then ItemInfo.HoverKind := hkMouseHover; +end; + +function TTBXCustomButton.GetTextAlignment: TAlignment; +begin + Result := FAlignment; +end; + +function TTBXCustomButton.GetTextMargins: TRect; +var + L, Sz: Integer; + IsSpecialDropDown: Boolean; +begin + Result := Rect(BorderSize, BorderSize, BorderSize, BorderSize); + L := Length(GetLabelText); + if (Images <> nil) and (L > 0) then Sz := GlyphSpacing + else Sz := 0; + if Assigned(Images) then with Result do + case Layout of + blGlyphLeft: Inc(Left, Images.Width + Sz); + blGlyphTop: Inc(Top, Images.Height + Sz); + blGlyphRight: Inc(Right, Images.Width + Sz); + blGlyphBottom: Inc(Bottom, Images.Height + Sz); + end; + if ArrowVisible then + begin + if DropDownCombo then Inc(Result.Right, CurrentTheme.SplitBtnArrowWidth) + else + begin + IsSpecialDropDown := (L > 0) and (Images <> nil) and (Layout in [blGlyphTop, blGlyphBottom]); + if not IsSpecialDropDown then Inc(Result.Right, CurrentTheme.DropDownArrowWidth); + end; + end; +end; + +procedure TTBXCustomButton.ImageListChange(Sender: TObject); +begin + if Sender = Images then + begin + Invalidate; + AdjustHeight; + end; +end; + +procedure TTBXCustomButton.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); +var + R: TRect; +begin + inherited; + if Enabled and (Button = mbLeft) then + begin + R := ClientRect; + ApplyMargins(R, Margins); + FMenuVisible := not FInClick and Assigned(DropDownMenu) and + (not DropDownCombo or (X >= R.Right - CurrentTheme.SplitBtnArrowWidth)); + try + if FMenuVisible then + begin + ControlState := ControlState - [csClicked]; + if not FInClick then + begin + Click; + end; + end + else if Repeating then + begin + Click; + ControlState := ControlState - [csClicked]; + if not Assigned(FRepeatTimer) then FRepeatTimer := TTimer.Create(Self); + FRepeatTimer.Interval := RepeatDelay; + FRepeatTimer.OnTimer := RepeatTimerHandler; + FRepeatTimer.Enabled := True; + end; + finally + FMenuVisible := False; + end; + end; +end; + +procedure TTBXCustomButton.MouseMove(Shift: TShiftState; X, Y: Integer); +begin + inherited; + if Assigned(FRepeatTimer) and PtInButtonPart(Point(X, Y)) then FRepeatTimer.Enabled := True; +end; + +procedure TTBXCustomButton.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); +begin + inherited; + if Button = mbLeft then + begin + FRepeatTimer.Free; + FRepeatTimer := nil; + end; +end; + +procedure TTBXCustomButton.Notification(AComponent: TComponent; Operation: TOperation); +begin + inherited; + if Operation = opRemove then + begin + if AComponent = Images then Images := nil + else if AComponent = DropdownMenu then DropdownMenu := nil; + end; +end; + +procedure TTBXCustomButton.Paint; +const + Alignments: array [TAlignment] of Integer = (DT_LEFT, DT_RIGHT, DT_CENTER); + WordWraps: array [TTextWrapping] of Integer = (DT_SINGLELINE, + DT_SINGLELINE or DT_END_ELLIPSIS, + DT_SINGLELINE or DT_PATH_ELLIPSIS, DT_WORDBREAK); + ShowAccelChars: array [Boolean] of Integer = (DT_NOPREFIX, 0); +var + CR, IR, TR: TRect; + W, X: Integer; + Text: string; + ItemInfo: TTBXItemInfo; + RealAlignment: TAlignment; + CaptionHeight: Integer; + DrawStyle: Cardinal; + ShowArrow: Boolean; +begin + CR := ClientRect; + ApplyMargins(CR, Margins); + + ShowArrow := ArrowVisible; + GetItemInfo(ItemInfo); + if ShowArrow and DropDownCombo then + begin + TR := CR; + TR.Left := TR.Right - CurrentTheme.SplitBtnArrowWidth; + CR.Right := TR.Left; + + ItemInfo.ComboPart := cpSplitRight; + ItemInfo.Pushed := FMenuVisible; + CurrentTheme.PaintButton(Canvas, TR, ItemInfo); + + ItemInfo.ComboPart := cpSplitLeft; + ItemInfo.Pushed := Pushed and not FMenuVisible; + CurrentTheme.PaintButton(Canvas, CR, ItemInfo); + end + else CurrentTheme.PaintButton(Canvas, CR, ItemInfo); + if Focused then DrawFocusRect2(Canvas, GetFocusRect(CR)); + InflateRect(CR, -BorderSize, -BorderSize); + + if ShowArrow and not DropDownCombo then + begin + TR := CR; + TR.Left := TR.Right - CurrentTheme.DropdownArrowWidth; + CurrentTheme.PaintDropDownArrow(Canvas, TR, ItemInfo); + CR.Right := TR.Left - CurrentTheme.DropdownArrowMargin; + end; + + Text := GetLabelText; + DrawStyle := 0; + + if (Length(Text) > 0) or (Images <> nil) then + begin + RealAlignment := GetRealAlignment(Self); + + if Length(Text) = 0 then + begin + IR.Top := (CR.Top + CR.Bottom - Images.Height) div 2; + IR.Bottom := IR.Top + Images.Height; + + case RealAlignment of + taLeftJustify: IR.Left := CR.Left; + taRightJustify: IR.Left := CR.Right - Images.Width; + else + IR.Left := (CR.Left + CR.Right - Images.Width) div 2; + end; + IR.Right := IR.Left + Images.Width; + end + else + begin + TR := CR; + DrawStyle := DT_EXPANDTABS or WordWraps[Wrapping] or + Alignments[RealAlignment] or ShowAccelChars[ShowAccelChar]; + if (Images = nil) or (Layout in [blGlyphTop, blGlyphBottom]) then + begin + CaptionHeight := DoDrawText(Canvas, TR, DrawStyle or DT_CALCRECT); + TR := CR; + if Images = nil then + begin + TR.Top := (TR.Top + TR.Bottom - CaptionHeight) div 2; + end + else + begin + TR.Top := (CR.Top + CR.Bottom - Images.Height - GlyphSpacing - CaptionHeight) div 2; + IR.Top := TR.Top; + if Layout = blGlyphTop then Inc(TR.Top, Images.Height + GlyphSpacing) + else Inc(IR.Top, CaptionHeight + GlyphSpacing); + TR.Bottom := TR.Top + CaptionHeight; + IR.Bottom := IR.Top + Images.Height; + case RealAlignment of + taLeftJustify: IR.Left := CR.Left; + taRightJustify: IR.Left := CR.Right - Images.Width; + else + IR.Left := (CR.Left + CR.Right - Images.Width) div 2; + end; + IR.Right := IR.Left + Images.Width; + end; + end + else + begin + IR.Left := CR.Left; + if Layout = blGlyphLeft then Inc(TR.Left, Images.Width + GlyphSpacing) + else Dec(TR.Right, Images.Width + GlyphSpacing); + IR.Right := IR.Left + Images.Width; + IR.Top := (CR.Top + CR.Bottom - Images.Height) div 2; + IR.Bottom := IR.Top + Images.Height; + CaptionHeight := DoDrawText(Canvas, TR, DrawStyle or DT_CALCRECT); + TR.Top := (CR.Top + CR.Bottom - CaptionHeight) div 2; + TR.Bottom := TR.Top + CaptionHeight; + W := Images.Width + GlyphSpacing + TR.Right - TR.Left; + case RealAlignment of + taLeftJustify: X := CR.Left; + taRightJustify: X := CR.Right - W; + else + X := (CR.Left + CR.Right - W) div 2; + end; + case Layout of + blGlyphLeft: + begin + if X < CR.Left then X := CR.Left; + IR.Left := X; + IR.Right := X + Images.Width; + OffsetRect(TR, IR.Right + GlyphSpacing - TR.Left, 0); + if TR.Right > CR.Right then TR.Right := CR.Right; + DrawStyle := DrawStyle and not DT_RIGHT and not DT_CENTER or DT_LEFT; + end; + blGlyphRight: + begin + OffsetRect(TR, X - TR.Left, 0); + IR.Left := TR.Right + GlyphSpacing; + IR.Right := IR.Left + Images.Width; + DrawStyle := DrawStyle and not DT_CENTER and not DT_LEFT or DT_RIGHT; + end; + end; + end; + end; + + if Images <> nil then + CurrentTheme.PaintImage(Canvas, IR, ItemInfo, Images, ImageIndex); + + if Length(Text) > 0 then + begin + Brush.Style := bsClear; + DoDrawText(Canvas, TR, DrawStyle); + Brush.Style := bsSolid; + end; + end; +end; + +function TTBXCustomButton.PtInButtonPart(const Pt: TPoint): Boolean; +var + R: TRect; +begin + R := ClientRect; + ApplyMargins(R, Margins); + Result := PtInRect(R, Pt); +end; + +procedure TTBXCustomButton.RepeatTimerHandler(Sender: TObject); +var + P: TPoint; +begin + FRepeatTimer.Interval := RepeatInterval; + GetCursorPos(P); + P := ScreenToClient(P); + if not MouseCapture then + begin + FRepeatTimer.Free; + FRepeatTimer := nil; + end + else if Repeating and Pushed and PtInButtonPart(P) then Click + else FRepeatTimer.Enabled := False; +end; + +procedure TTBXCustomButton.SetAlignment(Value: TAlignment); +begin + FAlignment := Value; + Invalidate; +end; + +procedure TTBXCustomButton.SetAllowAllUnchecked(Value: Boolean); +begin + if FAllowAllUnchecked <> Value then + begin + FAllowAllUnchecked := Value; + UpdateCheckedState; + end; +end; + +procedure TTBXCustomButton.SetBorderSize(Value: Integer); +begin + FBorderSize := Value; + Invalidate; + AdjustHeight; +end; + +procedure TTBXCustomButton.SetButtonStyle(Value: TButtonStyle); +begin + FButtonStyle := Value; + Invalidate; +end; + +procedure TTBXCustomButton.SetChecked(Value: Boolean); +begin + if FGroupIndex = 0 then Value := False; + if FChecked <> Value then + begin + if FChecked and not AllowAllUnchecked then Exit; + FChecked := Value; + Invalidate; + if Value then UpdateCheckedState; + end; +end; + +procedure TTBXCustomButton.SetDropdownCombo(Value: Boolean); +begin + FDropdownCombo := Value; + Invalidate; +end; + +procedure TTBXCustomButton.SetDropdownMenu(Value: TPopupMenu); +begin + if FDropdownMenu <> Value then + begin + if FDropDownMenu <> nil then RemoveFreeNotification(FDropDownMenu); + FDropDownMenu := Value; + if FDropDownMenu <> nil then FreeNotification(FDropDownMenu); + Invalidate; + end; +end; + +procedure TTBXCustomButton.SetGlyphSpacing(Value: Integer); +begin + FGlyphSpacing := Value; + Invalidate; + AdjustHeight; +end; + +procedure TTBXCustomButton.SetGroupIndex(Value: Integer); +begin + if FGroupIndex <> Value then + begin + FGroupIndex := Value; + UpdateCheckedState; + end; +end; + +procedure TTBXCustomButton.SetImageIndex(Value: TImageIndex); +begin + if FImageIndex <> Value then + begin + FImageIndex := Value; + if Assigned(Images) then Invalidate; + end; +end; + +procedure TTBXCustomButton.SetImages(Value: TCustomImageList); +begin + if FImages <> nil then FImages.UnRegisterChanges(FImageChangeLink); + FImages := Value; + if FImages <> nil then + begin + FImages.RegisterChanges(FImageChangeLink); + FImages.FreeNotification(Self); + end; + Invalidate; + AdjustHeight; +end; + +procedure TTBXCustomButton.SetLayout(Value: TButtonLayout); +begin + FLayout := Value; + Invalidate; + AdjustHeight; +end; + +procedure TTBXCustomButton.UpdateCheckedState; +var + I: Integer; + C: TControl; +begin + if (FGroupIndex <> 0) and (Parent <> nil) then with Parent do + for I := 0 to ControlCount - 1 do + begin + C := Controls[I]; + if (C <> Self) and (C is TTBXCustomButton) then + with TTBXCustomButton(C) do + if FGroupIndex = Self.FGroupIndex then + begin + if Self.Checked and FChecked then + begin + FChecked := False; + Invalidate; + end; + FAllowAllUnchecked := Self.AllowAllUnchecked; + end; + end; +end; + +procedure TTBXCustomButton.WMCancelMode(var Message: TWMCancelMode); +begin + FRepeatTimer.Free; + FRepeatTimer := nil; + MouseLeft; +end; + +procedure TTBXCustomButton.WMLButtonDblClk(var Message: TWMLButtonDblClk); +begin + Perform(WM_LBUTTONDOWN, Message.Keys, Longint(Message.Pos)); +end; + +//----------------------------------------------------------------------------// + +procedure TTBXCustomButton.WMNCHitTest(var Message: TWMNCHitTest); +var + P: TPoint; + R: TRect; +begin + inherited; + if not (csDesigning in ComponentState) then + begin + P := ScreenToClient(SmallPointToPoint(Message.Pos)); + R := ClientRect; + ApplyMargins(R, Margins); + if not PtInRect(R, P) then Message.Result := HTTRANSPARENT; + end; +end; + +{ TTBXAlignmentPanel } + +procedure TTBXAlignmentPanel.AdjustClientRect(var Rect: TRect); +begin + inherited AdjustClientRect(Rect); + with Margins do + begin + Inc(Rect.Left, Left); + Inc(Rect.Top, Top); + Dec(Rect.Right, Right); + Dec(Rect.Bottom, Bottom); + end; +end; + +constructor TTBXAlignmentPanel.Create(AOwner: TComponent); +begin + inherited; + FMargins := TTBXControlMargins.Create; + FMargins.OnChange := MarginsChangeHandler; +end; + +destructor TTBXAlignmentPanel.Destroy; +begin + FMargins.Free; + inherited; +end; + +function TTBXAlignmentPanel.GetMinHeight: Integer; +var + I: Integer; + Control: TControl; +begin + Result := 0; + for I := 0 to ControlCount - 1 do + begin + Control := Controls[I]; + if Control.Visible then + if Control.Align in [alTop, alBottom] then Inc(Result, Control.Height) + else if Control.Align = alClient then Inc(Result, GetMinControlHeight(Control)); + end; + Inc(Result, Margins.Top + Margins.Bottom); +end; + +function TTBXAlignmentPanel.GetMinWidth: Integer; +var + I: Integer; + Control: TControl; +begin + Result := 0; + for I := 0 to ControlCount - 1 do + begin + Control := Controls[I]; + if Control.Visible then + if Control.Align in [alLeft, alRight] then Inc(Result, Control.Width) + else if Control.Align = alClient then Inc(Result, GetMinControlWidth(Control)); + end; + Inc(Result, Margins.Left + Margins.Right); +end; + +procedure TTBXAlignmentPanel.MarginsChangeHandler(Sender: TObject); +begin + Realign; + Invalidate; +end; + +procedure TTBXAlignmentPanel.Paint; +var + R: TRect; + DC: HDC; +begin + if csDesigning in ComponentState then + begin + DC := Canvas.Handle; + R := ClientRect; + SaveDC(DC); + InflateRect(R, -1, -1); + with R do ExcludeClipRect(DC, Left, Top, Right, Bottom); + InflateRect(R, 1, 1); + DitherRect(DC, R, clBtnFace, clBtnShadow); + RestoreDC(DC, -1); + end; +end; + +procedure TTBXAlignmentPanel.SetMargins(Value: TTBXControlMargins); +begin + FMargins.Assign(Value); +end; + +//----------------------------------------------------------------------------// + +{ TTBXCustomPageScroller } + +procedure TTBXCustomPageScroller.AdjustClientRect(var Rect: TRect); +begin + if Orientation = tpsoVertical then + begin + if tpsbPrev in FVisibleButtons then Dec(Rect.Top, ButtonSize); + if tpsbNext in FVisibleButtons then Inc(Rect.Bottom, ButtonSize); + OffsetRect(Rect, 0, -Position); + if Range > Rect.Bottom - Rect.Top then Rect.Bottom := Rect.Top + Range; + end + else + begin + if tpsbPrev in FVisibleButtons then Dec(Rect.Left, ButtonSize); + if tpsbNext in FVisibleButtons then Inc(Rect.Right, ButtonSize); + OffsetRect(Rect, -Position, 0); + if Range > Rect.Right - Rect.Left then Rect.Right := Rect.Left + Range; + end; +end; + +procedure TTBXCustomPageScroller.AlignControls(AControl: TControl; var ARect: TRect); +begin + CalcAutoRange; + UpdateButtons; + ARect := ClientRect; + inherited AlignControls(AControl, ARect); +end; + +function TTBXCustomPageScroller.AutoScrollEnabled: Boolean; +begin + Result := not AutoSize and not (DockSite and UseDockManager); +end; + +procedure TTBXCustomPageScroller.BeginScrolling(HitTest: Integer); +var + Msg: TMsg; +begin + if HitTest = HTSCROLLPREV then FScrollDirection := -1 else FScrollDirection := 1; + try + SetCapture(Handle); + FScrollCounter := FScrollDirection * 8; + FScrollPending := True; + FScrollTimer.Enabled := True; + DrawNCArea(False, 0, 0); + HandleScrollTimer; + FScrollPending := True; + FScrollTimer.Interval := ScrollDelay; + + while GetCapture = Handle do + begin + case Integer(GetMessage(Msg, 0, 0, 0)) of + -1: Break; + 0: begin + PostQuitMessage(Msg.WParam); + Break; + end; + end; + case Msg.Message of + WM_KEYDOWN, WM_KEYUP: if Msg.WParam = VK_ESCAPE then Break; + WM_LBUTTONDOWN, WM_LBUTTONDBLCLK: begin + Break; + end; + WM_LBUTTONUP: + begin + Break; + end; + WM_RBUTTONDOWN..WM_MBUTTONDBLCLK:; + WM_TIMER: + begin + HandleScrollTimer; + end; + else + TranslateMessage(Msg); + DispatchMessage(Msg); + end; + end; + finally + StopScrolling; + if GetCapture = Handle then ReleaseCapture; + end; +end; + +procedure TTBXCustomPageScroller.CalcAutoRange; +var + I: Integer; + Bias: Integer; + NewRange, AlignMargin: Integer; + CW, CH: Integer; + Control: TControl; +begin + if (FAutoRangeCount <= 0) and AutoRange then + begin + if AutoScrollEnabled then + begin + NewRange := 0; + AlignMargin := 0; + if Position > 0 then Bias := ButtonSize + else Bias := 0; + CW := ClientWidth; + CH := ClientHeight; + DisableAlign; + for I := 0 to ControlCount - 1 do + begin + Control := Controls[I]; + if Control.Visible or (csDesigning in Control.ComponentState) and + not (csNoDesignVisible in Control.ControlStyle) then + begin + if Orientation = tpsoVertical then + begin + if Control.Align in [alTop, alBottom, alClient] then + Control.Width := CW; + case Control.Align of + alTop, alNone: + if (Control.Align = alTop) or (Control.Anchors * [akTop, akBottom] = [akTop]) then + NewRange := Max(NewRange, Position + Control.Top + Control.Height + Bias); + alBottom: Inc(AlignMargin, Control.Height); + alClient: Inc(AlignMargin, GetMinControlHeight(Control)); + end + end + else + begin + if Control.Align in [alLeft, alRight, alClient] then + Control.Height := CH; + case Control.Align of + alLeft, alNone: + if (Control.Align = alLeft) or (Control.Anchors * [akLeft, akRight] = [akLeft]) then + NewRange := Max(NewRange, Position + Control.Left + Control.Width + Bias); + alRight: Inc(AlignMargin, Control.Width); + alClient: Inc(AlignMargin, GetMinControlWidth(Control)); + end; + end; + end; + end; + EnableAlign; + DoSetRange(NewRange + AlignMargin + Margin); + end + else DoSetRange(0); + end; +end; + +function TTBXCustomPageScroller.CalcClientArea: TRect; +begin + Result := ClientRect; + if Orientation = tpsoVertical then + begin + if tpsbPrev in FVisibleButtons then Dec(Result.Top, ButtonSize); + if tpsbNext in FVisibleButtons then Inc(Result.Bottom, ButtonSize); + end + else + begin + if tpsbPrev in FVisibleButtons then Dec(Result.Left, ButtonSize); + if tpsbNext in FVisibleButtons then Inc(Result.Right, ButtonSize); + end; +end; + +function TTBXCustomPageScroller.CanAutoSize(var NewWidth, NewHeight: Integer): Boolean; +begin + Result := NewHeight > FButtonSize * 3; +end; + +procedure TTBXCustomPageScroller.CMParentColorChanged(var Message: TMessage); +begin + if (Message.WParam = 0) then + begin + Message.WParam := 1; + Message.LParam := GetEffectiveColor(Parent); + end; + inherited; +end; + +procedure TTBXCustomPageScroller.ConstrainedResize(var MinWidth, MinHeight, MaxWidth, MaxHeight: Integer); +begin + // do not call inherited here +end; + +constructor TTBXCustomPageScroller.Create(AOwner: TComponent); +begin + inherited; + ControlStyle := ControlStyle + [csAcceptsControls, csClickEvents, csDoubleClicks]; + FAutoScroll := True; + FButtonSize := 10; + FScrollTimer := TTimer.Create(Self); + FScrollTimer.Enabled := False; + FScrollTimer.Interval := 60; + FScrollTimer.OnTimer := ScrollTimerTimer; + Width := 64; + Height := 64; +end; + +procedure TTBXCustomPageScroller.CreateParams(var Params: TCreateParams); +begin + inherited CreateParams(Params); + with Params.WindowClass do style := style and not (CS_HREDRAW or CS_VREDRAW); +end; + +procedure TTBXCustomPageScroller.DisableAutoRange; +begin + Inc(FAutoRangeCount); +end; + +procedure TTBXCustomPageScroller.DoSetRange(Value: Integer); +begin + FRange := Value; + if FRange < 0 then FRange := 0; + UpdateButtons; +end; + +procedure TTBXCustomPageScroller.DrawNCArea(const DrawToDC: Boolean; + const ADC: HDC; const Clip: HRGN); +const + CBtns: array [TTBXPageScrollerOrientation, Boolean] of Integer = + ((PSBT_UP, PSBT_DOWN), (PSBT_LEFT, PSBT_RIGHT)); +var + DC: HDC; + R, CR, BR: TRect; + ACanvas: TCanvas; + PrevBtnSize, NextBtnSize: Integer; +begin + if FVisibleButtons = [] then Exit; + if not DrawToDC then DC := GetWindowDC(Handle) + else DC := ADC; + try + GetWindowRect(Handle, R); + OffsetRect(R, -R.Left, -R.Top); + if not DrawToDC then + begin + SelectNCUpdateRgn(Handle, DC, Clip); + CR := R; + PrevBtnSize := 0; + NextBtnSize := 0; + if tpsbPrev in FVisibleButtons then PrevBtnSize := ButtonSize; + if tpsbNext in FVisibleButtons then NextBtnSize := ButtonSize; + if Orientation = tpsoVertical then + begin + Inc(CR.Top, PrevBtnSize); + Dec(CR.Bottom, NextBtnSize); + end + else + begin + Inc(CR.Left, PrevBtnSize); + Dec(CR.Right, NextBtnSize); + end; + with CR do ExcludeClipRect(DC, Left, Top, Right, Bottom); + end; + + ACanvas := TCanvas.Create; + try + ACanvas.Handle := DC; + ACanvas.Brush.Color := Color; + ACanvas.FillRect(R); + + if tpsbPrev in FVisibleButtons then + begin + BR := R; + if Orientation = tpsoVertical then BR.Bottom := BR.Top + ButtonSize + else BR.Right := BR.Left + ButtonSize; + CurrentTheme.PaintPageScrollButton(ACanvas, BR, CBtns[Orientation, False], + FScrollDirection < 0); + end; + if tpsbNext in FVisibleButtons then + begin + BR := R; + if Orientation = tpsoVertical then BR.Top := BR.Bottom - ButtonSize + else BR.Left := BR.Right - ButtonSize; + CurrentTheme.PaintPageScrollButton(ACanvas, BR, CBtns[Orientation, True], + FScrollDirection > 0); + end; + finally + ACanvas.Handle := 0; + ACanvas.Free; + end; + finally + if not DrawToDC then ReleaseDC(Handle, DC); + end; +end; + +procedure TTBXCustomPageScroller.EnableAutoRange; +begin + if FAutoRangeCount > 0 then + begin + Dec(FAutoRangeCount); + if FAutoRangeCount = 0 then CalcAutoRange; + end; +end; + +procedure TTBXCustomPageScroller.HandleScrollTimer; +var + Pt: TPoint; + R: TRect; + OldPosition: Integer; + OldDirection: Integer; +begin + GetCursorPos(Pt); + GetWindowRect(Handle, R); + if not PtInRect(R, Pt) then + begin + StopScrolling; + end + else if FScrollDirection = 0 then + begin + FScrollTimer.Enabled := False; + FScrollCounter := 0; + end + else + begin + OldPosition := Position; + OldDirection := FScrollDirection; + if ((FScrollDirection > 0) and (FScrollCounter < 0)) or + ((FScrollDirection < 0) and (FScrollCounter > 0)) then FScrollCounter := 0; + if FScrollDirection > 0 then Inc(FScrollCounter) + else Dec(FScrollCounter); + Position := Position + FScrollCounter; + if Position = OldPosition then + begin + ReleaseCapture; + FScrollTimer.Enabled := False; + DrawNCArea(False, 0, 0); + end + else + begin + if FScrollPending or (FScrollDirection * OldDirection <= 0) or + (FScrollDirection * OldDirection <= 0) then + DrawNCArea(False, 0, 0); + end; + end; + if FScrollPending then FScrollTimer.Interval := ScrollInterval; + FScrollPending := False; +end; + +function TTBXCustomPageScroller.IsRangeStored: Boolean; +begin + Result := not AutoRange; +end; + +procedure TTBXCustomPageScroller.Loaded; +begin + inherited; + UpdateButtons; +end; + +procedure TTBXCustomPageScroller.RecalcNCArea; +begin + SetWindowPos(Handle, 0, 0, 0, 0, 0, + SWP_FRAMECHANGED or SWP_NOACTIVATE or SWP_NOZORDER or SWP_NOMOVE or SWP_NOSIZE); +end; + +procedure TTBXCustomPageScroller.Resizing; +begin + // do nothing by default +end; + +procedure TTBXCustomPageScroller.ScrollTimerTimer(Sender: TObject); +begin + HandleScrollTimer; +end; + +procedure TTBXCustomPageScroller.ScrollToCenter(ARect: TRect); +var + X, Y: Integer; +begin + if Orientation = tpsoVertical then + begin + if ARect.Bottom - ARect.Top < Range then Y := (ARect.Top + ARect.Bottom) div 2 + else Y := ARect.Top; + Position := Position + Y - Height div 2; + end + else + begin + if ARect.Right - ARect.Left < Range then X := (ARect.Left + ARect.Right) div 2 + else X := ARect.Left; + Position := Position + X - Width div 2; + end; +end; + +procedure TTBXCustomPageScroller.ScrollToCenter(AControl: TControl); +var + R: TRect; +begin + R := AControl.ClientRect; + R.TopLeft := ScreenToClient(AControl.ClientToScreen(R.TopLeft)); + R.BottomRight := ScreenToClient(AControl.ClientToScreen(R.BottomRight)); + ScrollToCenter(R); +end; + +procedure TTBXCustomPageScroller.SetAutoRange(Value: Boolean); +begin + if FAutoRange <> Value then + begin + FAutoRange := Value; + if Value then CalcAutoRange else Range := 0; + end; +end; + +procedure TTBXCustomPageScroller.SetButtonSize(Value: Integer); +begin + if FButtonSize <> Value then + begin + FButtonSize := Value; + UpdateButtons; + end; +end; + +procedure TTBXCustomPageScroller.SetOrientation(Value: TTBXPageScrollerOrientation); +begin + if Orientation <> Value then + begin + FOrientation := Value; + Realign; + end; +end; + +procedure TTBXCustomPageScroller.SetPosition(Value: Integer); +var + OldPos: Integer; +begin + if csReading in ComponentState then FPosition := Value + else + begin + ValidatePosition(Value); + if FPosition <> Value then + begin + OldPos := FPosition; + FPosition := Value; + + if OldPos > 0 then Inc(OldPos, ButtonSize); + if Value > 0 then Inc(Value, ButtonSize); + + if Orientation = tpsoHorizontal then ScrollBy(OldPos - Value, 0) + else ScrollBy(0, OldPos - Value); + UpdateButtons; + end; + end; +end; + +procedure TTBXCustomPageScroller.SetRange(Value: Integer); +begin + FAutoRange := False; + DoSetRange(Value); +end; + +procedure TTBXCustomPageScroller.StopScrolling; +begin + if (FScrollDirection <> 0) or (FScrollCounter <> 0) or (FScrollTimer.Enabled) then + begin + FScrollDirection := 0; + FScrollCounter := 0; + FScrollTimer.Enabled := False; + if HandleAllocated and IsWindowVisible(Handle) then DrawNCArea(False, 0, 0); + end; +end; + +procedure TTBXCustomPageScroller.UpdateButtons; +var + Sz: Integer; + OldVisibleButtons: TTBXPageScrollerButtons; + RealignNeeded: Boolean; +begin + RealignNeeded := False; + if not FUpdatingButtons and HandleAllocated then + try + FUpdatingButtons := True; + if Orientation = tpsoHorizontal then Sz := Width + else Sz := Height; + OldVisibleButtons := FVisibleButtons; + FVisibleButtons := []; + + FPosRange := Range - Sz; + if FPosRange < 0 then FPosRange := 0; + if FPosition > FPosRange - 1 then + begin + FPosition := FPosRange; + RealignNeeded := True; + end; + + if Sz > ButtonSize * 3 then + begin + if Position > 0 then Include(FVisibleButtons, tpsbPrev); + if Range - Position > Sz then Include(FVisibleButtons, tpsbNext); + end; + if FVisibleButtons <> OldVisibleButtons then + begin + RecalcNCArea; + RealignNeeded := True; + end; + finally + FUpdatingButtons := False; + if RealignNeeded then Realign; + end; +end; + +procedure TTBXCustomPageScroller.ValidatePosition(var NewPos: Integer); +begin + if NewPos < 0 then NewPos := 0; + if NewPos > FPosRange then NewPos := FPosRange; +end; + +procedure TTBXCustomPageScroller.WMEraseBkgnd(var Message: TWmEraseBkgnd); +begin + if Color = clNone then + begin + DrawParentBackground(Self, Message.DC, ClientRect); + Message.Result := 1; + end + else inherited; +end; + +procedure TTBXCustomPageScroller.WMMouseMove(var Message: TWMMouseMove); +begin + if AutoScroll then StopScrolling; + inherited; +end; + +procedure TTBXCustomPageScroller.WMNCCalcSize(var Message: TWMNCCalcSize); +begin + with Message.CalcSize_Params^ do + begin + if Orientation = tpsoVertical then + begin + if tpsbPrev in FVisibleButtons then Inc(rgrc[0].Top, ButtonSize); + if tpsbNext in FVisibleButtons then Dec(rgrc[0].Bottom, ButtonSize); + end + else + begin + if tpsbPrev in FVisibleButtons then Inc(rgrc[0].Left, ButtonSize); + if tpsbNext in FVisibleButtons then Dec(rgrc[0].Right, ButtonSize); + end; + Message.Result := 0; + end; +end; + +procedure TTBXCustomPageScroller.WMNCHitTest(var Message: TWMNCHitTest); +var + Pt: TPoint; + R: TRect; +begin + DefaultHandler(Message); + with Message do if Result <> HTCLIENT then + begin + Pt := SmallPointToPoint(Pos); + GetWindowRect(Handle, R); + if PtInRect(R, Pt) then + begin + if (tpsbPrev in FVisibleButtons) then + begin + if Orientation = tpsoVertical then + begin + if Pt.Y < R.Top + ButtonSize then Result := HTSCROLLPREV + end + else + begin + if Pt.X < R.Left + ButtonSize then Result := HTSCROLLPREV + end; + end; + if (tpsbNext in FVisibleButtons) then + begin + if Orientation = tpsoVertical then + begin + if Pt.Y >= R.Bottom - ButtonSize then Result := HTSCROLLNEXT; + end + else + begin + if Pt.X >= R.Right - ButtonSize then Result := HTSCROLLNEXT; + end; + end; + end; + end; +end; + +procedure TTBXCustomPageScroller.WMNCLButtonDown(var Message: TWMNCLButtonDown); +begin + if (Win32MajorVersion >= 5) or + (Win32MajorVersion = 4) and (Win32MinorVersion >= 10) then + CallTrackMouseEvent(Handle, TME_LEAVE or $10 {TME_NONCLIENT}); + + if not AutoScroll and (Message.HitTest in [HTSCROLLPREV, HTSCROLLNEXT]) then + BeginScrolling(Message.HitTest) + else + inherited; +end; + +procedure TTBXCustomPageScroller.WMNCMouseLeave(var Message: TMessage); +begin + if AutoScroll then StopScrolling; + inherited; +end; + +procedure TTBXCustomPageScroller.WMNCMouseMove(var Message: TWMNCMouseMove); +var + OldScrollDirection: Integer; +begin + if (Win32MajorVersion >= 5) or + (Win32MajorVersion = 4) and (Win32MinorVersion >= 10) then + CallTrackMouseEvent(Handle, TME_LEAVE or $10 {TME_NONCLIENT}); + + if AutoScroll then + begin + OldScrollDirection := FScrollDirection; + case Message.HitTest of + HTSCROLLPREV: FScrollDirection := -1; + HTSCROLLNEXT: FScrollDirection := 1; + else + StopScrolling; + inherited; + Exit; + end; + if OldScrollDirection <> FScrollDirection then + begin + FScrollCounter := 0; + FScrollPending := True; + FScrollTimer.Interval := ScrollDelay; + FScrollTimer.Enabled := True; + DrawNCArea(False, 0, 0); + end; + end; +end; + +procedure TTBXCustomPageScroller.WMNCPaint(var Message: TMessage); +begin + DrawNCArea(False, 0, HRGN(Message.WParam)); +end; + +procedure TTBXCustomPageScroller.WMSize(var Message: TWMSize); +begin + FUpdatingButtons := True; + try + CalcAutoRange; + finally + FUpdatingButtons := False; + end; + Inc(FAutoRangeCount); + inherited; + Resizing; + Dec(FAutoRangeCount); +end; + +{ TTBXCustomCheckBox } + +procedure TTBXCustomCheckBox.Click; +begin + Toggle; + Invalidate; + inherited; +end; + +procedure TTBXCustomCheckBox.CMDialogChar(var Message: TCMDialogChar); +begin + with Message do + if Enabled and ShowAccelChar and IsAccel(CharCode, GetLabelText) and CanFocus and Visible then + begin + Click; + Result := 1; + end + else inherited; +end; + +procedure TTBXCustomCheckBox.CMDialogKey(var Message: TCMDialogKey); +begin + with Message do + if (CharCode = VK_RETURN) and Focused and + (KeyDataToShiftState(Message.KeyData) = []) then + begin + Click; + Result := 1; + end + else inherited; +end; + +procedure TTBXCustomCheckBox.CNCommand(var Message: TWMCommand); +begin + if Message.NotifyCode = BN_CLICKED then Toggle; +end; + +constructor TTBXCustomCheckBox.Create(AOwner: TComponent); +begin + inherited; + SmartFocus := True; + SpaceAsClick := True; + TabStop := True; +end; + +procedure TTBXCustomCheckBox.DoAdjustHeight(ACanvas: TCanvas; var NewHeight: Integer); +begin + inherited DoAdjustHeight(ACanvas, NewHeight); + if NewHeight < GetGlyphSize + 4 then NewHeight := GetGlyphSize + 4; +end; + +procedure TTBXCustomCheckBox.DoChange; +begin + if Assigned(FOnChange) then FOnChange(Self); +end; + +procedure TTBXCustomCheckBox.DoMouseEnter; +begin + inherited; + Invalidate; +end; + +procedure TTBXCustomCheckBox.DoMouseLeave; +begin + inherited; + Invalidate; +end; + +function TTBXCustomCheckBox.DoSetState(var NewState: TCheckBoxState): Boolean; +begin + Result := True; +end; + +function TTBXCustomCheckBox.GetChecked: Boolean; +begin + Result := State = cbChecked; +end; + +function TTBXCustomCheckBox.GetFocusRect(const R: TRect): TRect; +const + Alignments: array [TLeftRight] of Word = (DT_LEFT, DT_RIGHT); + WordWraps: array [TTextWrapping] of Integer = (DT_SINGLELINE or DT_VCENTER, + DT_SINGLELINE or DT_VCENTER or DT_END_ELLIPSIS, + DT_SINGLELINE or DT_VCENTER or DT_PATH_ELLIPSIS, DT_WORDBREAK); +var + TR: TRect; +begin + TR := R; + ApplyMargins(TR, GetTextMargins); + DoDrawText(Canvas, TR, (DT_EXPANDTABS or DT_CALCRECT) or WordWraps[Wrapping] or Alignments[Alignment]); + Result := R; + Result.Right := TR.Right + 2; + Result.Left := TR.Left - 2; +end; + +function TTBXCustomCheckBox.GetGlyphSize: Integer; +begin + Result := 13; +end; + +function TTBXCustomCheckBox.GetTextAlignment: TAlignment; +begin + Result := taLeftJustify; +end; + +function TTBXCustomCheckBox.GetTextMargins: TRect; +begin + Result := Rect(2, 2, 2, 2); + with Result do + if GetRealAlignment(Self) = taLeftJustify then Inc(Left, GetGlyphSize + 6) + else Inc(Right, GetGlyphSize + 6); +end; + +procedure TTBXCustomCheckBox.Paint; +const + EnabledState: array [Boolean] of Integer = (PFS_DISABLED, 0); + StateFlags: array [TCheckBoxState] of Integer = (0, PFS_CHECKED, PFS_MIXED); + HotState: array [Boolean] of Integer = (0, PFS_HOT); + PushedState: array [Boolean] of Integer = (0, PFS_PUSHED); + FocusedState: array [Boolean] of Integer = (0, PFS_FOCUSED); +var + Rect: TRect; + Sz, Flags: Integer; +begin + inherited; + with Canvas do + begin + Rect := ClientRect; + ApplyMargins(Rect, Margins); + Sz := GetGlyphSize; + if Alignment = taLeftJustify then Rect.Right := Rect.Left + GetGlyphSize + else Rect.Left := Rect.Right - GetGlyphSize; + Rect.Top := (Rect.Top + Rect.Bottom + 1 - Sz) div 2; + Rect.Bottom := Rect.Top + Sz; + Brush.Color := clBtnShadow; + Flags := EnabledState[Enabled]; + if Enabled then Flags := Flags or StateFlags[State] or + HotState[MouseInControl] or PushedState[Pushed and MouseInControl] or FocusedState[Focused]; + CurrentTheme.PaintFrameControl(Canvas, Rect, PFC_CHECKBOX, Flags, nil); + end; +end; + +procedure TTBXCustomCheckBox.SetChecked(Value: Boolean); +begin + if Value then State := cbChecked else State := cbUnchecked; +end; + +procedure TTBXCustomCheckBox.SetState(Value: TCheckBoxState); +begin + if (FState <> Value) and DoSetState(Value) then + begin + FState := Value; + Invalidate; + DoChange; + end; +end; + +procedure TTBXCustomCheckBox.Toggle; +begin + case State of + cbUnchecked: if AllowGrayed then State := cbGrayed else State := cbChecked; + cbChecked: State := cbUnchecked; + cbGrayed: State := cbChecked; + end; +end; + +procedure TTBXCustomCheckBox.WMNCHitTest(var Message: TWMNCHitTest); +var + P: TPoint; + R: TRect; + SL, SR: Integer; +begin + inherited; + if not (csDesigning in ComponentState) then + begin + P := ScreenToClient(SmallPointToPoint(Message.Pos)); + R := ClientRect; + ApplyMargins(R, Margins); + SL := R.Left; SR := R.Right; + R := GetFocusRect(R); + if GetRealAlignment(Self) = taLeftJustify then R.Left := SL + else R.Right := SR; + if not PtInRect(R, P) then Message.Result := HTTRANSPARENT; + end; +end; + +{ TTBXCustomRadioButton } + +procedure TTBXCustomRadioButton.Click; +begin + if not Checked then Checked := True; + Invalidate; + inherited; +end; + +procedure TTBXCustomRadioButton.CMDialogChar(var Message: TCMDialogChar); +begin + with Message do + if Enabled and ShowAccelChar and IsAccel(CharCode, GetLabelText) and CanFocus and Visible then + begin + Click; + Result := 1; + end + else inherited; +end; + +procedure TTBXCustomRadioButton.CNCommand(var Message: TWMCommand); +begin + if Message.NotifyCode = BN_CLICKED then Checked := not Checked; +end; + +constructor TTBXCustomRadioButton.Create(AOwner: TComponent); +begin + inherited; + SmartFocus := True; + SpaceAsClick := True; + TabStop := True; +end; + +procedure TTBXCustomRadioButton.DoAdjustHeight(ACanvas: TCanvas; var NewHeight: Integer); +begin + inherited DoAdjustHeight(ACanvas, NewHeight); + if NewHeight < GetGlyphSize + 4 then NewHeight := GetGlyphSize + 4; +end; + +procedure TTBXCustomRadioButton.DoChange; +begin + if Assigned(FOnChange) then FOnChange(Self); +end; + +procedure TTBXCustomRadioButton.DoMouseEnter; +begin + inherited; + Invalidate; +end; + +procedure TTBXCustomRadioButton.DoMouseLeave; +begin + inherited; + Invalidate; +end; + +function TTBXCustomRadioButton.DoSetChecked(var Value: Boolean): Boolean; +begin + Result := True; +end; + +function TTBXCustomRadioButton.GetFocusRect(const R: TRect): TRect; +const + Alignments: array [TLeftRight] of Word = (DT_LEFT, DT_RIGHT); + WordWraps: array [TTextWrapping] of Integer = (DT_SINGLELINE or DT_VCENTER, + DT_SINGLELINE or DT_VCENTER or DT_END_ELLIPSIS, + DT_SINGLELINE or DT_VCENTER or DT_PATH_ELLIPSIS, DT_WORDBREAK); +var + TR: TRect; +begin + TR := R; + ApplyMargins(TR, GetTextMargins); + DoDrawText(Canvas, TR, (DT_EXPANDTABS or DT_CALCRECT) or WordWraps[Wrapping] or Alignments[Alignment]); + Result := R; + Result.Right := TR.Right + 2; + Result.Left := TR.Left - 2; +end; + +function TTBXCustomRadioButton.GetGlyphSize: Integer; +begin + Result := 13; +end; + +function TTBXCustomRadioButton.GetTextAlignment: TAlignment; +begin + Result := taLeftJustify; +end; + +function TTBXCustomRadioButton.GetTextMargins: TRect; +begin + Result := Rect(2, 2, 2, 2); + with Result do + if GetRealAlignment(Self) = taLeftJustify then Inc(Left, GetGlyphSize + 6) + else Inc(Right, GetGlyphSize + 6); +end; + +procedure TTBXCustomRadioButton.Paint; +const + EnabledState: array [Boolean] of Integer = (PFS_DISABLED, 0); + CheckedState: array [Boolean] of Integer = (0, PFS_CHECKED); + HotState: array [Boolean] of Integer = (0, PFS_HOT); + PushedState: array [Boolean] of Integer = (0, PFS_PUSHED); + FocusedState: array [Boolean] of Integer = (0, PFS_FOCUSED); +var + Rect: TRect; + Sz, Flags: Integer; +begin + inherited; + with Canvas do + begin + Rect := ClientRect; + with Margins do + begin + Inc(Rect.Left, Left); + Inc(Rect.Top, Top); + Dec(Rect.Right, Right); + Dec(Rect.Bottom, Bottom); + end; + Sz := GetGlyphSize; + if Alignment = taLeftJustify then Rect.Right := Rect.Left + GetGlyphSize + else Rect.Left := Rect.Right - GetGlyphSize; + Rect.Top := (Rect.Top + Rect.Bottom + 1 - Sz) div 2; + Rect.Bottom := Rect.Top + Sz; + Brush.Color := clBtnShadow; + Flags := EnabledState[Enabled]; + if Enabled then Flags := Flags or CheckedState[Checked] or + HotState[MouseInControl] or PushedState[Pushed and MouseInControl] or FocusedState[Focused]; + CurrentTheme.PaintFrameControl(Canvas, Rect, PFC_RADIOBUTTON, Flags, nil); + end; +end; + +procedure TTBXCustomRadioButton.SetChecked(Value: Boolean); +begin + if (Value <> FChecked) and DoSetChecked(Value) then + begin + FChecked := Value; + TabStop := Value; + if Value then TurnSiblingsOff; + Invalidate; + DoChange; + end; +end; + +procedure TTBXCustomRadioButton.SetGroupIndex(Value: Integer); +begin + FGroupIndex := Value; + if Checked then TurnSiblingsOff; +end; + +procedure TTBXCustomRadioButton.TurnSiblingsOff; +var + I: Integer; + Sibling: TControl; +begin + if Parent <> nil then + with Parent do + for I := 0 to ControlCount - 1 do + begin + Sibling := Controls[I]; + if (Sibling <> Self) and (Sibling is TTBXCustomRadioButton) then + with TTBXCustomRadioButton(Sibling) do + begin + if GroupIndex = Self.GroupIndex then SetChecked(False); + end; + end; +end; + +procedure TTBXCustomRadioButton.WMNCHitTest(var Message: TWMNCHitTest); +var + P: TPoint; + R: TRect; + SL, SR: Integer; +begin + inherited; + if not (csDesigning in ComponentState) then + begin + P := ScreenToClient(SmallPointToPoint(Message.Pos)); + R := ClientRect; + ApplyMargins(R, Margins); + SL := R.Left; SR := R.Right; + R := GetFocusRect(R); + if GetRealAlignment(Self) = taLeftJustify then R.Left := SL + else R.Right := SR; + if not PtInRect(R, P) then Message.Result := HTTRANSPARENT; + end; +end; + +end. diff --git a/official/2.1.6+2.1.beta1/TBX/TBXDkPanels.pas.orig b/official/2.1.6+2.1.beta1/TBX/TBXDkPanels.pas.orig new file mode 100644 index 0000000..8c6af97 --- /dev/null +++ b/official/2.1.6+2.1.beta1/TBX/TBXDkPanels.pas.orig @@ -0,0 +1,5459 @@ +unit TBXDkPanels; + +// TBX Package +// Copyright 2001-2004 Alex A. Denisov. All Rights Reserved +// See TBX.chm for license and installation instructions +// +// $Id: TBXDkPanels.pas 21 2004-05-29 22:16:01Z Alex@ZEISS $ + +interface + +{$I TB2Ver.inc} +{$I TBX.inc} + +uses + Windows, Messages, Classes, Graphics, Controls, StdCtrls, ExtCtrls, Forms, + TB2Dock, TB2Item, TBX, TBXThemes, ImgList, Menus; + +const + { New hit test constants for page scrollers } + HTSCROLLPREV = 30; + HTSCROLLNEXT = 31; + +type + { TTBXDockablePanel } + + TTBXControlMargins = class(TPersistent) + private + FLeft, FTop, FRight, FBottom: Integer; + FOnChange: TNotifyEvent; + procedure SetBottom(Value: Integer); + procedure SetLeft(Value: Integer); + procedure SetRight(Value: Integer); + procedure SetTop(Value: Integer); + public + procedure Assign(Src: TPersistent); override; + procedure Modified; dynamic; + property OnChange: TNotifyEvent read FOnChange write FOnChange; + published + property Left: Integer read FLeft write SetLeft default 0; + property Top: Integer read FTop write SetTop default 0; + property Right: Integer read FRight write SetRight default 0; + property Bottom: Integer read FBottom write SetBottom default 0; + end; + + { TTBXMultiDock } + + TTBXMultiDock = class(TTBDock) + protected + LastValidRowSize: Integer; + function Accepts(ADockableWindow: TTBCustomDockableWindow): Boolean; override; + procedure ValidateInsert(AComponent: TComponent); override; + public + procedure Paint; override; + procedure ResizeVisiblePanels(NewSize: Integer); + procedure ArrangeToolbars; override; + end; + + + { TTBXDockablePanel } + + TDPCaptionRotation = (dpcrAuto, dpcrAlwaysHorz, dpcrAlwaysVert); + TTBXResizingStage = (rsBeginResizing, rsResizing, rsEndResizing); + TTBXDockedResizing = procedure(Sender: TObject; Vertical: Boolean; + var NewSize: Integer; Stage: TTBXResizingStage; var AllowResize: Boolean) of object; + TDockKinds = set of (dkStandardDock, dkMultiDock); + + TTBXDockablePanel = class(TTBCustomDockableWindow) + private + FBorderSize: Integer; + FCaptionRotation: TDPCaptionRotation; + FDockedWidth: Integer; + FDockedHeight: Integer; + FEffectiveColor: TColor; + FFloatingWidth: Integer; + FFloatingHeight: Integer; + FIsResizing: Boolean; + FIsSplitting: Boolean; + FMinClientWidth: Integer; + FMinClientHeight: Integer; + FMaxClientWidth: Integer; + FMaxClientHeight: Integer; + FSmoothDockedResize: Boolean; + FSnapDistance: Integer; + FShowCaptionWhenDocked: Boolean; + FSplitHeight: Integer; + FSplitWidth: Integer; + FSupportedDocks: TDockKinds; + FOnDockedResizing: TTBXDockedResizing; + function CalcSize(ADock: TTBDock): TPoint; + procedure SetBorderSize(Value: Integer); + procedure SetCaptionRotation(Value: TDPCaptionRotation); + procedure SetDockedHeight(Value: Integer); + procedure SetDockedWidth(Value: Integer); + procedure SetFloatingHeight(Value: Integer); + procedure SetFloatingWidth(Value: Integer); + procedure SetMinClientHeight(Value: Integer); + procedure SetMinClientWidth(Value: Integer); + procedure SetShowCaptionWhenDocked(Value: Boolean); + procedure SetSnapDistance(Value: Integer); + procedure CMColorChanged(var Message: TMessage); message CM_COLORCHANGED; + procedure CMControlChange(var Message: TCMControlChange); message CM_CONTROLCHANGE; + procedure CMTextChanged(var Message: TMessage); message CM_TEXTCHANGED; + procedure TBMGetEffectiveColor(var Message: TMessage); message TBM_GETEFFECTIVECOLOR; + procedure TBMGetViewType(var Message: TMessage); message TBM_GETVIEWTYPE; + procedure TBMThemeChange(var Message: TMessage); message TBM_THEMECHANGE; + procedure WMEraseBkgnd(var Message: TWMEraseBkgnd); message WM_ERASEBKGND; + procedure WMNCHitTest(var Message: TWMNCHitTest); message WM_NCHITTEST; + procedure WMNCCalcSize(var Message: TWMNCCalcSize); message WM_NCCALCSIZE; + procedure WMNCLButtonDown(var Message: TWMNCLButtonDown); message WM_NCLBUTTONDOWN; + procedure WMSetCursor(var Message: TWMSetCursor); message WM_SETCURSOR; + procedure WMWindowPosChanged(var Message: TWMWindowPosChanged); message WM_WINDOWPOSCHANGED; + procedure SetSplitHeight(Value: Integer); + procedure SetSplitWidth(Value: Integer); + protected + BlockSizeUpdate: Boolean; + procedure AdjustClientRect(var Rect: TRect); override; + procedure BeginDockedSizing(HitTest: Integer); + procedure BeginSplitResizing(HitTest: Integer); + function CalcNCSizes: TPoint; override; + function CanAutoSize(var NewWidth, NewHeight: Integer): Boolean; override; + function CanDockTo(ADock: TTBDock): Boolean; override; + function CanSplitResize(EdgePosition: TTBDockPosition): Boolean; + procedure ConstrainedResize(var MinWidth, MinHeight, MaxWidth, MaxHeight: Integer); override; + function DoArrange(CanMoveControls: Boolean; PreviousDockType: TTBDockType; NewFloating: Boolean; NewDock: TTBDock): TPoint; override; + function DoBeginDockedResizing(Vertical: Boolean): Boolean; virtual; + function DoDockedResizing(Vertical: Boolean; var NewSize: Integer): Boolean; virtual; + function DoEndDockedResizing(Vertical: Boolean): Boolean; virtual; + procedure DrawNCArea(const DrawToDC: Boolean; const ADC: HDC; const Clip: HRGN); override; + procedure GetBaseSize(var ASize: TPoint); override; + function GetDockedCloseButtonRect(LeftRight: Boolean): TRect; override; + procedure GetDockPanelInfo(out DockPanelInfo: TTBXDockPanelInfo); virtual; + function GetFloatingWindowParentClass: TTBFloatingWindowParentClass; override; + procedure GetMinMaxSize(var AMinClientWidth, AMinClientHeight, AMaxClientWidth, AMaxClientHeight: Integer); override; + function GetViewType: Integer; + function IsVertCaption: Boolean; virtual; + procedure Loaded; override; + procedure Paint; override; + procedure SetParent(AParent: TWinControl); override; + procedure SizeChanging(const AWidth, AHeight: Integer); override; + procedure UpdateEffectiveColor; + property IsResizing: Boolean read FIsResizing; + property IsSplitting: Boolean read FIsSplitting; + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + function GetFloatingBorderSize: TPoint; override; + procedure ReadPositionData(const Data: TTBReadPositionData); override; + procedure SetBounds(ALeft, ATop, AWidth, AHeight: Integer); override; + procedure UpdateChildColors; + procedure WritePositionData(const Data: TTBWritePositionData); override; + property EffectiveColor: TColor read FEffectiveColor; + published + { client size constraints should be restored before other size related properties } + property MaxClientHeight: Integer read FMaxClientHeight write FMaxClientHeight default 0; + property MaxClientWidth: Integer read FMaxClientWidth write FMaxClientWidth default 0; + property MinClientHeight: Integer read FMinClientHeight write SetMinClientHeight default 32; + property MinClientWidth: Integer read FMinClientWidth write SetMinClientWidth default 32; + + property ActivateParent; + property Align; + property Anchors; + property BorderSize: Integer read FBorderSize write SetBorderSize default 0; + property BorderStyle; + property Caption; + property CaptionRotation: TDPCaptionRotation read FCaptionRotation write SetCaptionRotation default dpcrAuto; + property Color default clNone; + property CloseButton; + property CloseButtonWhenDocked default True; + property CurrentDock; + property DblClickUndock default False; + property DefaultDock; + property DockableTo; + property DockedWidth: Integer read FDockedWidth write SetDockedWidth default 128; + property DockedHeight: Integer read FDockedHeight write SetDockedHeight default 128; + property DockMode; + property DockPos; + property DockRow; + property FloatingWidth: Integer read FFloatingWidth write SetFloatingWidth default 0; + property FloatingHeight: Integer read FFloatingHeight write SetFloatingHeight default 0; + property FloatingMode; + property Font; + property Height stored False; + property HideWhenInactive; + property LastDock; + property ParentFont; + property ParentShowHint; + property PopupMenu; + property Resizable; + property ShowCaption; + property ShowCaptionWhenDocked: Boolean read FShowCaptionWhenDocked write SetShowCaptionWhenDocked default True; + property ShowHint; + property SplitHeight: Integer read FSplitHeight write SetSplitHeight default 0; + property SplitWidth: Integer read FSplitWidth write SetSplitWidth default 0; + property SupportedDocks: TDockKinds read FSupportedDocks write FSupportedDocks; + property SmoothDrag; + property SmoothDockedResize: Boolean read FSmoothDockedResize write FSmoothDockedResize default True; + property SnapDistance: Integer read FSnapDistance write SetSnapDistance default 0; + property TabOrder; + property UseLastDock; + property Visible; + property Width stored False; + + property OnClose; + property OnCloseQuery; + {$IFDEF JR_D5} + property OnContextPopup; + {$ENDIF} + property OnDragDrop; + property OnDragOver; + property OnDockChanged; + property OnDockChanging; + property OnDockChangingHidden; + property OnDockedResizing: TTBXDockedResizing read FOnDockedResizing write FOnDockedResizing; + property OnMouseDown; + property OnMouseMove; + property OnMouseUp; + property OnMove; + property OnRecreated; + property OnRecreating; + property OnResize; + property OnVisibleChanged; + end; + + { TTBXPanelObject } + + TControlPaintOptions = set of (cpoDoubleBuffered); + + TTBXPanelObject = class(TCustomControl) + private + FDisableScroll: Boolean; + FMouseInControl: Boolean; + FPaintOptions: TControlPaintOptions; + FPushed: Boolean; + FSmartFocus: Boolean; + FSpaceAsClick: Boolean; + FOnMouseEnter: TNotifyEvent; + FOnMouseLeave: TNotifyEvent; + procedure CMParentColorChanged(var Message: TMessage); message CM_PARENTCOLORCHANGED; + procedure CMEnabledChanged(var Message: TMessage); message CM_ENABLEDCHANGED; + procedure MouseTimerHandler(Sender: TObject); + procedure RemoveMouseTimer; + procedure SetPaintOptions(Value: TControlPaintOptions); + procedure TBMThemeChange(var Message); message TBM_THEMECHANGE; + procedure WMEraseBkgnd(var Message: TMessage); message WM_ERASEBKGND; + procedure WMKillFocus(var Message: TMessage); message WM_KILLFOCUS; + procedure WMSetFocus(var Message: TMessage); message WM_SETFOCUS; + protected + procedure CreateParams(var Params: TCreateParams); override; + procedure DoMouseEnter; virtual; + procedure DoMouseLeave; virtual; + procedure KeyDown(var Key: Word; Shift: TShiftState); override; + procedure KeyUp(var Key: Word; Shift: TShiftState); override; + procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override; + procedure MouseMove(Shift: TShiftState; X, Y: Integer); override; + procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override; + function GetMinHeight: Integer; virtual; + function GetMinWidth: Integer; virtual; + property Color default clNone; + property MouseInControl: Boolean read FMouseInControl; + property PaintOptions: TControlPaintOptions read FPaintOptions write SetPaintOptions; + property ParentColor default False; + property Pushed: Boolean read FPushed; + property SpaceAsClick: Boolean read FSpaceAsClick write FSpaceAsClick default False; + property SmartFocus: Boolean read FSmartFocus write FSmartFocus default False; + property OnMouseEnter: TNotifyEvent read FOnMouseEnter write FOnMouseEnter; + property OnMouseLeave: TNotifyEvent read FOnMouseLeave write FOnMouseLeave; + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + procedure MakeVisible; + procedure MouseEntered; + procedure MouseLeft; + end; + + { TTBXAlignmentPanel } + + TTBXAlignmentPanel = class(TTBXPanelObject) + private + FMargins: TTBXControlMargins; + procedure MarginsChangeHandler(Sender: TObject); + procedure SetMargins(Value: TTBXControlMargins); + protected + procedure AdjustClientRect(var Rect: TRect); override; + procedure Paint; override; + function GetMinHeight: Integer; override; + function GetMinWidth: Integer; override; + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + published + property ParentColor; + property Align; + property Anchors; + property AutoSize; + property Color; + property Constraints; + property DragCursor; + property DragKind; + property DragMode; + property Enabled; + property Font; + property Margins: TTBXControlMargins read FMargins write SetMargins; + property ParentFont; + property ShowHint; + property TabOrder; + property TabStop; + property Visible; + property OnClick; +{$IFDEF JR_D5} + property OnContextPopup; +{$ENDIF} + property OnDblClick; + property OnDragDrop; + property OnDragOver; + property OnEndDock; + property OnEndDrag; + property OnMouseDown; + property OnMouseEnter; + property OnMouseLeave; + property OnMouseMove; + property OnMouseUp; + property OnStartDock; + property OnStartDrag; + end; + + { TTBXTextObject } + + TTBXTextObject = class(TTBXPanelObject) + private + FAlignment: TLeftRight; + FMargins: TTBXControlMargins; + FWrapping: TTextWrapping; + FShowAccelChar: Boolean; + FUpdating: Boolean; + procedure CMEnabledChanged(var Message: TMessage); message CM_ENABLEDCHANGED; + procedure CMFontChanged(var Message: TMessage); message CM_FONTCHANGED; + procedure CMTextChanged(var Message: TMessage); message CM_TEXTCHANGED; + procedure MarginsChangeHandler(Sender: TObject); + procedure SetAlignment(Value: TLeftRight); + procedure SetMargins(Value: TTBXControlMargins); + procedure SetShowAccelChar(Value: Boolean); + procedure SetWrapping(Value: TTextWrapping); + protected + procedure AdjustFont(AFont: TFont); virtual; + procedure AdjustHeight; + procedure CreateParams(var Params: TCreateParams); override; + function CanAutoSize(var NewWidth, NewHeight: Integer): Boolean; override; + procedure DoAdjustHeight(ACanvas: TCanvas; var NewHeight: Integer); virtual; + function DoDrawText(ACanvas: TCanvas; var Rect: TRect; Flags: Longint): Integer; virtual; + procedure DoMarginsChanged; virtual; + function GetFocusRect(const R: TRect): TRect; virtual; + function GetLabelText: string; virtual; + function GetTextAlignment: TAlignment; virtual; + function GetTextMargins: TRect; virtual; + procedure Loaded; override; + procedure Paint; override; + property Alignment: TLeftRight read FAlignment write SetAlignment default taLeftJustify; + property AutoSize default True; + property PaintOptions default [cpoDoubleBuffered]; + property ShowAccelChar: Boolean read FShowAccelChar write SetShowAccelChar default True; + property Margins: TTBXControlMargins read FMargins write SetMargins; + property Wrapping: TTextWrapping read FWrapping write SetWrapping default twNone; + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + function GetControlsAlignment: TAlignment; override; + end; + + { TTBXCustomLabel } + + TTBXCustomLabel = class(TTBXTextObject) + private + FFocusControl: TWinControl; + FUnderline: Boolean; + FUnderlineColor: TColor; + procedure CMDialogChar(var Message: TCMDialogChar); message CM_DIALOGCHAR; + procedure SetUnderline(Value: Boolean); + procedure SetUnderlineColor(Value: TColor); + procedure SetFocusControl(Value: TWinControl); + protected + function GetTextMargins: TRect; override; + procedure Notification(AComponent: TComponent; Operation: TOperation); override; + procedure Paint; override; + property FocusControl: TWinControl read FFocusControl write SetFocusControl; + property Underline: Boolean read FUnderline write SetUnderline default False; + property UnderlineColor: TColor read FUnderlineColor write SetUnderlineColor default clBtnShadow; + property Wrapping default twWrap; + public + constructor Create(AOwner: TComponent); override; + end; + + { TTBXLabel } + + TTBXLabel = class(TTBXCustomLabel) + published + property Align; + property Alignment; + property Anchors; + property AutoSize; + property BiDiMode; + property Caption; + property Color; + property Constraints; + property DragCursor; + property DragKind; + property DragMode; + property Enabled; + property FocusControl; + property Font; + property Margins; +// property PaintOptions; + property ParentBiDiMode; + property ParentColor; + property ParentFont; + property ParentShowHint; + property PopupMenu; + property ShowAccelChar; + property ShowHint; + property Underline; + property UnderlineColor; + property Visible; + property Wrapping; + property OnClick; +{$IFDEF JR_D5} + property OnContextPopup; +{$ENDIF} + property OnDblClick; + property OnDragDrop; + property OnDragOver; + property OnEndDock; + property OnEndDrag; + property OnMouseDown; + property OnMouseEnter; + property OnMouseLeave; + property OnMouseMove; + property OnMouseUp; + property OnStartDock; + property OnStartDrag; + end; + + { TTBXCustomLink } + + TTBXCustomLink = class(TTBXTextObject) + private + FImageChangeLink: TChangeLink; + FImageIndex: TImageIndex; + FImages: TCustomImageList; + procedure ImageListChange(Sender: TObject); + procedure SetImageIndex(Value: TImageIndex); + procedure SetImages(Value: TCustomImageList); + procedure CMDialogChar(var Message: TCMDialogChar); message CM_DIALOGCHAR; + procedure CMDialogKey(var Message: TCMDialogKey); message CM_DIALOGKEY; + procedure WMNCHitTest(var Message: TWMNCHitTest); message WM_NCHITTEST; + protected + procedure AdjustFont(AFont: TFont); override; + procedure DoAdjustHeight(ACanvas: TCanvas; var NewHeight: Integer); override; + procedure DoMouseEnter; override; + procedure DoMouseLeave; override; + function GetFocusRect(const R: TRect): TRect; override; + function GetTextAlignment: TAlignment; override; + function GetTextMargins: TRect; override; + procedure Paint; override; + procedure Notification(AComponent: TComponent; Operation: TOperation); override; + property Cursor default crHandPoint; + property ImageIndex: TImageIndex read FImageIndex write SetImageIndex; + property Images: TCustomImageList read FImages write SetImages; + property SmartFocus default True; + property TabStop default True; + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + function GetControlsAlignment: TAlignment; override; + end; + + { TTBXLink } + + TTBXLink = class(TTBXCustomLink) + published + property Align; + property Alignment; + property Anchors; + property AutoSize; + property BiDiMode; + property Caption; + property Color; + property Constraints; + property DragCursor; + property DragKind; + property DragMode; + property Enabled; + property Font; + property ImageIndex; + property Images; + property Margins; +// property PaintOptions; + property ParentBiDiMode; + property ParentColor; + property ParentFont; + property ParentShowHint; + property PopupMenu; + property ShowAccelChar; + property ShowHint; + property SmartFocus; + property TabOrder; + property TabStop; + property Visible; + property Wrapping; + property OnClick; +{$IFDEF JR_D5} + property OnContextPopup; +{$ENDIF} + property OnDblClick; + property OnDragDrop; + property OnDragOver; + property OnEndDock; + property OnEndDrag; + property OnEnter; + property OnExit; + property OnMouseDown; + property OnMouseEnter; + property OnMouseLeave; + property OnMouseMove; + property OnMouseUp; + property OnStartDock; + property OnStartDrag; + end; + + { TTBXCustomButton } + TTBXCustomButton = class; + TButtonLayout = (blGlyphLeft, blGlyphTop, blGlyphRight, blGlyphBottom); + TButtonStyle = (bsNormal, bsFlat); + TDropDownEvent = procedure(Sender: TTBXCustomButton; var AllowDropDown: Boolean) of object; + + TTBXCustomButton = class(TTBXTextObject) + private + FAlignment: TAlignment; + FAllowAllUnchecked: Boolean; + FBorderSize: Integer; + FChecked: Boolean; + FDropdownCombo: Boolean; + FDropdownMenu: TPopupMenu; + FButtonStyle: TButtonStyle; + FGlyphSpacing: Integer; + FGroupIndex: Integer; + FImageChangeLink: TChangeLink; + FImageIndex: TImageIndex; + FImages: TCustomImageList; + FInClick: Boolean; + FLayout: TButtonLayout; + FMenuVisible: Boolean; + FModalResult: TModalResult; + FRepeating: Boolean; + FRepeatDelay: Integer; + FRepeatInterval: Integer; + FRepeatTimer: TTimer; + FOnDropDown: TDropDownEvent; + procedure ImageListChange(Sender: TObject); + procedure RepeatTimerHandler(Sender: TObject); + procedure SetAlignment(Value: TAlignment); + procedure SetAllowAllUnchecked(Value: Boolean); + procedure SetBorderSize(Value: Integer); + procedure SetButtonStyle(Value: TButtonStyle); + procedure SetChecked(Value: Boolean); + procedure SetDropdownCombo(Value: Boolean); + procedure SetDropdownMenu(Value: TPopupMenu); + procedure SetGlyphSpacing(Value: Integer); + procedure SetGroupIndex(Value: Integer); + procedure SetImageIndex(Value: TImageIndex); + procedure SetImages(Value: TCustomImageList); + procedure SetLayout(Value: TButtonLayout); + procedure CMDialogChar(var Message: TCMDialogChar); message CM_DIALOGCHAR; + procedure CMDialogKey(var Message: TCMDialogKey); message CM_DIALOGKEY; + procedure WMCancelMode(var Message: TWMCancelMode); message WM_CANCELMODE; + procedure WMLButtonDblClk(var Message: TWMLButtonDblClk); message WM_LBUTTONDBLCLK; + procedure WMNCHitTest(var Message: TWMNCHitTest); message WM_NCHITTEST; + protected + function ArrowVisible: Boolean; + procedure DoAdjustHeight(ACanvas: TCanvas; var NewHeight: Integer); override; + function DoDrawText(ACanvas: TCanvas; var Rect: TRect; Flags: Longint): Integer; override; + function DoDropDown: Boolean; virtual; + procedure DoMouseEnter; override; + procedure DoMouseLeave; override; + function GetFocusRect(const R: TRect): TRect; override; + procedure GetItemInfo(out ItemInfo: TTBXItemInfo); virtual; + function GetTextAlignment: TAlignment; override; + function GetTextMargins: TRect; override; + procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override; + procedure MouseMove(Shift: TShiftState; X, Y: Integer); override; + procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override; + procedure Paint; override; + function PtInButtonPart(const Pt: TPoint): Boolean; virtual; + procedure Notification(AComponent: TComponent; Operation: TOperation); override; + procedure UpdateCheckedState; + property Alignment: TAlignment read FAlignment write SetAlignment default taCenter; + property AllowAllUnchecked: Boolean read FAllowAllUnchecked write SetAllowAllUnchecked default False; + property BorderSize: Integer read FBorderSize write SetBorderSize default 4; + property ButtonStyle: TButtonStyle read FButtonStyle write SetButtonStyle default bsNormal; + property Checked: Boolean read FChecked write SetChecked default False; + property DropdownCombo: Boolean read FDropdownCombo write SetDropdownCombo default False; + property DropdownMenu: TPopupMenu read FDropdownMenu write SetDropdownMenu; + property GlyphSpacing: Integer read FGlyphSpacing write SetGlyphSpacing default 4; + property GroupIndex: Integer read FGroupIndex write SetGroupIndex default 0; + property ImageIndex: TImageIndex read FImageIndex write SetImageIndex; + property Images: TCustomImageList read FImages write SetImages; + property Layout: TButtonLayout read FLayout write SetLayout default blGlyphLeft; + property ModalResult: TModalResult read FModalResult write FModalResult default 0; + property Repeating: Boolean read FRepeating write FRepeating default False; + property RepeatDelay: Integer read FRepeatDelay write FRepeatDelay default 400; + property RepeatInterval: Integer read FRepeatInterval write FRepeatInterval default 100; + property SmartFocus default True; + property TabStop default True; + property OnDropDown: TDropDownEvent read FOnDropDown write FOnDropDown; + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + procedure Click; override; + function GetControlsAlignment: TAlignment; override; + end; + + { TTBXButton } + TTBXButton = class(TTBXCustomButton) + published + property Align; + property Alignment; + property GroupIndex; + property AllowAllUnchecked; + property Anchors; + property AutoSize; + property BiDiMode; + property BorderSize; + property ButtonStyle; + property Caption; + property Checked; + property Constraints; + property DragCursor; + property DragKind; + property DragMode; + property DropDownCombo; + property DropDownMenu; + property Enabled; + property Font; + property GlyphSpacing; + property ImageIndex; + property Images; + property Layout; + property Margins; + property ModalResult; +// property PaintOptions; + property ParentBiDiMode; + property ParentFont; + property ParentShowHint; + property PopupMenu; + property Repeating; + property RepeatDelay; + property RepeatInterval; + property ShowAccelChar; + property ShowHint; + property SmartFocus; + property TabOrder; + property TabStop; + property Visible; + property Wrapping; + property OnClick; +{$IFDEF JR_D5} + property OnContextPopup; +{$ENDIF} + property OnDblClick; + property OnDragDrop; + property OnDragOver; + property OnDropDown; + property OnEndDock; + property OnEndDrag; + property OnMouseDown; + property OnMouseEnter; + property OnMouseLeave; + property OnMouseMove; + property OnMouseUp; + property OnStartDock; + property OnStartDrag; + end; + + { TTBXCustomCheckBox } + + TTBXCustomCheckBox = class(TTBXTextObject) + private + FAllowGrayed: Boolean; + FState: TCheckBoxState; + FOnChange: TNotifyEvent; + function GetChecked: Boolean; + procedure CMDialogChar(var Message: TCMDialogChar); message CM_DIALOGCHAR; + procedure CMDialogKey(var Message: TCMDialogKey); message CM_DIALOGKEY; + procedure CNCommand(var Message: TWMCommand); message CN_COMMAND; + procedure SetChecked(Value: Boolean); + procedure SetState(Value: TCheckBoxState); + procedure WMNCHitTest(var Message: TWMNCHitTest); message WM_NCHITTEST; + protected + procedure Click; override; + procedure DoAdjustHeight(ACanvas: TCanvas; var NewHeight: Integer); override; + procedure DoChange; virtual; + procedure DoMouseEnter; override; + procedure DoMouseLeave; override; + function DoSetState(var NewState: TCheckBoxState): Boolean; virtual; + function GetGlyphSize: Integer; + function GetFocusRect(const R: TRect): TRect; override; + function GetTextAlignment: TAlignment; override; + function GetTextMargins: TRect; override; + procedure Paint; override; + procedure Toggle; virtual; + property AllowGrayed: Boolean read FAllowGrayed write FAllowGrayed default False; + property Checked: Boolean read GetChecked write SetChecked stored False; + property SmartFocus default True; + property State: TCheckBoxState read FState write SetState default cbUnchecked; + property TabStop default True; + property OnChange: TNotifyEvent read FOnChange write FOnChange; + public + constructor Create(AOwner: TComponent); override; + end; + + TTBXCheckBox = class(TTBXCustomCheckBox) + published + property Align; + property Alignment; + property AllowGrayed; + property Anchors; + property AutoSize; + property BiDiMode; + property Caption; + property Checked; + property Color; + property Constraints; + property DragCursor; + property DragKind; + property DragMode; + property Enabled; + property Font; + property Margins; +// property PaintOptions; + property ParentBiDiMode; + property ParentColor; + property ParentFont; + property ParentShowHint; + property PopupMenu; + property ShowAccelChar; + property ShowHint; + property SmartFocus; + property State; + property TabOrder; + property TabStop; + property Visible; + property Wrapping; + property OnChange; + property OnClick; +{$IFDEF JR_D5} + property OnContextPopup; +{$ENDIF} + property OnDblClick; + property OnDragDrop; + property OnDragOver; + property OnEndDock; + property OnEndDrag; + property OnMouseDown; + property OnMouseEnter; + property OnMouseLeave; + property OnMouseMove; + property OnMouseUp; + property OnStartDock; + property OnStartDrag; + end; + + { TTBXCustomRadioButton } + + TTBXCustomRadioButton = class(TTBXTextObject) + private + FChecked: Boolean; + FGroupIndex: Integer; + FOnChange: TNotifyEvent; + procedure SetChecked(Value: Boolean); + procedure CMDialogChar(var Message: TCMDialogChar); message CM_DIALOGCHAR; + procedure CNCommand(var Message: TWMCommand); message CN_COMMAND; + procedure SetGroupIndex(Value: Integer); + procedure TurnSiblingsOff; + procedure WMNCHitTest(var Message: TWMNCHitTest); message WM_NCHITTEST; + protected + procedure Click; override; + procedure DoAdjustHeight(ACanvas: TCanvas; var NewHeight: Integer); override; + procedure DoChange; virtual; + procedure DoMouseEnter; override; + procedure DoMouseLeave; override; + function DoSetChecked(var Value: Boolean): Boolean; virtual; + function GetGlyphSize: Integer; + function GetFocusRect(const R: TRect): TRect; override; + function GetTextAlignment: TAlignment; override; + function GetTextMargins: TRect; override; + procedure Paint; override; + property Checked: Boolean read FChecked write SetChecked default False; + property GroupIndex: Integer read FGroupIndex write SetGroupIndex default 0; + property SmartFocus default True; + property TabStop default True; + property OnChange: TNotifyEvent read FOnChange write FOnChange; + public + constructor Create(AOwner: TComponent); override; + end; + + TTBXRadioButton = class(TTBXCustomRadioButton) + published + property Align; + property Alignment; + property Anchors; + property AutoSize; + property BiDiMode; + property Caption; + property Checked; + property Color; + property Constraints; + property DragCursor; + property DragKind; + property DragMode; + property Enabled; + property Font; + property GroupIndex; + property Margins; +// property PaintOptions; + property ParentBiDiMode; + property ParentColor; + property ParentFont; + property ParentShowHint; + property PopupMenu; + property ShowAccelChar; + property ShowHint; + property SmartFocus; + property TabOrder; + property TabStop; + property Visible; + property Wrapping; + property OnChange; + property OnClick; +{$IFDEF JR_D5} + property OnContextPopup; +{$ENDIF} + property OnDblClick; + property OnDragDrop; + property OnDragOver; + property OnEndDock; + property OnEndDrag; + property OnMouseDown; + property OnMouseEnter; + property OnMouseLeave; + property OnMouseMove; + property OnMouseUp; + property OnStartDock; + property OnStartDrag; + end; + + { TTBXPageScroller } + + TTBXPageScrollerOrientation = (tpsoVertical, tpsoHorizontal); + TTBXPageScrollerButtons = set of (tpsbPrev, tpsbNext); + + TTBXCustomPageScroller = class(TWinControl) + private + FAutoRangeCount: Integer; + FAutoRange: Boolean; + FAutoScroll: Boolean; + FButtonSize: Integer; + FMargin: Integer; + FOrientation: TTBXPageScrollerOrientation; + FPosition: Integer; + FPosRange: Integer; + FRange: Integer; + FScrollDirection: Integer; + FScrollCounter: Integer; + FScrollPending: Boolean; + FScrollTimer: TTimer; + FUpdatingButtons: Boolean; + FVisibleButtons: TTBXPageScrollerButtons; + procedure CalcAutoRange; + function IsRangeStored: Boolean; + procedure ScrollTimerTimer(Sender: TObject); + procedure SetButtonSize(Value: Integer); + procedure SetAutoRange(Value: Boolean); + procedure SetOrientation(Value: TTBXPageScrollerOrientation); + procedure SetPosition(Value: Integer); + procedure SetRange(Value: Integer); + procedure StopScrolling; + procedure ValidatePosition(var NewPos: Integer); + procedure CMParentColorChanged(var Message: TMessage); message CM_PARENTCOLORCHANGED; + procedure WMMouseMove(var Message: TWMMouseMove); message WM_MOUSEMOVE; + procedure WMNCCalcSize(var Message: TWMNCCalcSize); message WM_NCCALCSIZE; + procedure WMEraseBkgnd(var Message: TWmEraseBkgnd); message WM_ERASEBKGND; + procedure WMNCHitTest(var Message: TWMNCHitTest); message WM_NCHITTEST; + procedure WMNCLButtonDown(var Message: TWMNCLButtonDown); message WM_NCLBUTTONDOWN; + procedure WMNCMouseLeave(var Message: TMessage); message $2A2 {WM_NCMOUSELEAVE}; + procedure WMNCMouseMove(var Message: TWMNCMouseMove); message WM_NCMOUSEMOVE; + procedure WMNCPaint(var Message: TMessage); message WM_NCPAINT; + procedure WMSize(var Message: TWMSize); message WM_SIZE; + protected + procedure AdjustClientRect(var Rect: TRect); override; + procedure AlignControls(AControl: TControl; var ARect: TRect); override; + function AutoScrollEnabled: Boolean; virtual; + procedure BeginScrolling(HitTest: Integer); + function CalcClientArea: TRect; + function CanAutoSize(var NewWidth, NewHeight: Integer): Boolean; override; + procedure ConstrainedResize(var MinWidth, MinHeight, MaxWidth, MaxHeight: Integer); override; + procedure CreateParams(var Params: TCreateParams); override; + procedure DoSetRange(Value: Integer); virtual; + procedure DrawNCArea(const DrawToDC: Boolean; const ADC: HDC; const Clip: HRGN); virtual; + procedure HandleScrollTimer; virtual; + procedure Loaded; override; + procedure RecalcNCArea; + procedure Resizing; virtual; + procedure UpdateButtons; + property AutoScroll: Boolean read FAutoScroll write FAutoScroll default True; + property ButtonSize: Integer read FButtonSize write SetButtonSize default 10; + property Orientation: TTBXPageScrollerOrientation read FOrientation write SetOrientation default tpsoVertical; + property Position: Integer read FPosition write SetPosition default 0; + property Margin: Integer read FMargin write FMargin default 0; + property Range: Integer read FRange write SetRange stored IsRangeStored; + public + constructor Create(AOwner: TComponent); override; + procedure DisableAutoRange; + procedure EnableAutoRange; + procedure ScrollToCenter(ARect: TRect); overload; + procedure ScrollToCenter(AControl: TControl); overload; + property AutoRange: Boolean read FAutoRange write SetAutoRange default False; + end; + + TTBXPageScroller = class(TTBXCustomPageScroller) + public + property Position; + published + property Align; + property Anchors; + property AutoRange; + property AutoScroll; + property ButtonSize; + property Color; + property Constraints; + property DockSite; + property DragCursor; + property DragKind; + property DragMode; + property DoubleBuffered; + property Enabled; + property Ctl3D; + property Font; + property Margin; + property Orientation; + property ParentBiDiMode; + property ParentColor; + property ParentCtl3D; + property ParentFont; + property ParentShowHint; + property PopupMenu; + property Range; + property ShowHint; + property TabOrder; + property TabStop; + property Visible; + property OnCanResize; + property OnClick; + property OnConstrainedResize; +{$IFDEF JR_D5} + property OnContextPopup; +{$ENDIF} + property OnDblClick; + property OnDockDrop; + property OnDockOver; + property OnDragDrop; + property OnDragOver; + property OnEndDock; + property OnEndDrag; + property OnEnter; + property OnExit; + property OnGetSiteInfo; + property OnMouseDown; + property OnMouseMove; + property OnMouseUp; + property OnMouseWheel; + property OnMouseWheelDown; + property OnMouseWheelUp; + property OnResize; + property OnStartDock; + property OnStartDrag; + property OnUnDock; + end; + +implementation + +uses + TB2Common, TBXUtils, SysUtils; + +type + TWinControlAccess = class(TWinControl); + TDockAccess = class(TTBXMultiDock); + TTBDockableWindowAccess = class(TTBCustomDockableWindow); + +const + { Constants for TTBXDockablePanel-specific registry values. Do not localize! } + rvDockedWidth = 'DPDockedWidth'; + rvDockedHeight = 'DPDockedHeight'; + rvFloatingWidth = 'DPFloatingWidth'; + rvFloatingHeight = 'DPFloatingHeight'; + rvSplitWidth = 'DPSplitWidth'; + rvSplitHeight = 'DPSplitHeight'; + + HT_TB2k_Border = 2000; + HT_TB2k_Close = 2001; + HT_TB2k_Caption = 2002; + HT_TBX_SPLITRESIZELEFT = 86; + HT_TBX_SPLITRESIZERIGHT = 87; + HT_TBX_SPLITRESIZETOP = 88; + HT_TBX_SPLITRESIZEBOTTOM = 89; + DockedBorderSize = 2; + ScrollDelay = 300; + ScrollInterval = 75; + +var + MouseTimer: TTimer = nil; + MouseInObject: TTBXPanelObject = nil; + ObjectCount: Integer = 0; + + +procedure UpdateNCArea(Control: TWinControl; ViewType: Integer); +var + W, H: Integer; +begin + with Control do + begin + { Keep the client rect at the same position relative to screen } + W := ClientWidth; + H := ClientHeight; + SetWindowPos(Handle, 0, 0, 0, 0, 0, + SWP_FRAMECHANGED or SWP_NOACTIVATE or SWP_NOZORDER or SWP_NOREDRAW or SWP_NOMOVE or SWP_NOSIZE); + W := W - ClientWidth; + H := H - ClientHeight; + if (W <> 0) or (H <> 0) then + SetWindowPos(Handle, 0, Left - W div 2, Top - H div 2, Width + W, Height + H, + SWP_FRAMECHANGED or SWP_NOACTIVATE or SWP_NOZORDER); + RedrawWindow(Handle, nil, 0, RDW_FRAME or RDW_INVALIDATE or + RDW_ERASE or RDW_UPDATENOW or RDW_ALLCHILDREN); + end; +end; + +function GetMinControlHeight(Control: TControl): Integer; +begin + if Control.Align = alClient then + begin + if Control is TTBXPanelObject then Result := TTBXPanelObject(Control).GetMinHeight + else Result := Control.Constraints.MinHeight; + end + else Result := Control.Height; +end; + +function GetMinControlWidth(Control: TControl): Integer; +begin + if Control.Align = alClient then + begin + if Control is TTBXPanelObject then Result := TTBXPanelObject(Control).GetMinWidth + else Result := Control.Constraints.MinWidth; + end + else Result := Control.Width; +end; + +function IsActivated(AWinControl: TWinControl): Boolean; +var + C: TWinControl; +begin + { Returns true if AWinControl contains a focused control } + C := Screen.ActiveControl; + Result := True; + while C <> nil do + if C = AWinControl then Exit + else C := C.Parent; + Result := False; +end; + +procedure ApplyMargins(var R: TRect; const Margins: TTBXControlMargins); overload; +begin + with Margins do + begin + Inc(R.Left, Left); Inc(R.Top, Top); + Dec(R.Right, Right); Dec(R.Bottom, Bottom); + end; +end; + +procedure ApplyMargins(var R: TRect; const Margins: TRect); overload; +begin + with Margins do + begin + Inc(R.Left, Left); Inc(R.Top, Top); + Dec(R.Right, Right); Dec(R.Bottom, Bottom); + end; +end; + +procedure DrawFocusRect2(Canvas: TCanvas; const R: TRect); +var + DC: HDC; + C1, C2: TColor; +begin + DC := Canvas.Handle; + C1 := SetTextColor(DC, clBlack); + C2 := SetBkColor(DC, clWhite); + Canvas.DrawFocusRect(R); + SetTextColor(DC, C1); + SetBkColor(DC, C2); +end; + +function GetRealAlignment(Control: TControl): TAlignment; +const + ReverseAlignment: array [TAlignment] of TAlignment = (taRightJustify, taLeftJustify, taCenter); +begin + Result := Control.GetControlsAlignment; + if Control.UseRightToLeftAlignment then Result := ReverseAlignment[Result]; +end; + +function CompareEffectiveDockPos(const Item1, Item2, ExtraData: Pointer): Integer; far; +begin + Result := TTBCustomDockableWindow(Item1).EffectiveDockPos - TTBCustomDockableWindow(Item2).EffectiveDockPos; +end; + +function CompareDockPos(const Item1, Item2, ExtraData: Pointer): Integer; far; +var + P1, P2: Integer; +begin + P1 := TTBCustomDockableWindow(Item1).DockPos; + P2 := TTBCustomDockableWindow(Item2).DockPos; + if csLoading in TTBCustomDockableWindow(Item1).ComponentState then + begin + if P1 < 0 then P1 := MaxInt; + if P2 < 0 then P2 := MaxInt; + end; + Result := P1 - P2; +end; + + +//----------------------------------------------------------------------------// + +{ TTBXControlMargins } + +procedure TTBXControlMargins.Assign(Src: TPersistent); +begin + inherited; + Modified; +end; + +procedure TTBXControlMargins.Modified; +begin + if Assigned(FOnChange) then FOnChange(Self); +end; + +procedure TTBXControlMargins.SetBottom(Value: Integer); +begin + if FBottom <> Value then + begin + FBottom := Value; + Modified; + end; +end; + +procedure TTBXControlMargins.SetLeft(Value: Integer); +begin + if FLeft <> Value then + begin + FLeft := Value; + Modified; + end; +end; + +procedure TTBXControlMargins.SetRight(Value: Integer); +begin + if FRight <> Value then + begin + FRight := Value; + Modified; + end; +end; + +procedure TTBXControlMargins.SetTop(Value: Integer); +begin + if FTop <> Value then + begin + FTop := Value; + Modified; + end; +end; + +//----------------------------------------------------------------------------// + +{ TTBXMultiDock } + +function TTBXMultiDock.Accepts(ADockableWindow: TTBCustomDockableWindow): Boolean; +begin + Result := ADockableWindow is TTBXDockablePanel; +end; + +procedure TTBXMultiDock.ArrangeToolbars; +const + DSGN_DROPZONESIZE = 16; +type + TPosRec = record + Panel: TTBXDockablePanel; + MinSize, MaxSize, Size, Pos: Integer; + CanStretch: Boolean; + end; +var + NewDockList: TList; + PosData: array of TPosRec; + LeftRight: Boolean; + I, J, K, L, DragIndex, ResizeIndex, ForcedWidth: Integer; + EmptySize, ClientW, ClientH, DockSize, TotalSize, TotalMinimumSize, TotalMaximumSize: Integer; + DragIndexPos: Integer; + T: TTBXDockablePanel; + S: TPoint; + CurRowPixel, CurRowSize: Integer; + StretchPanelCount: Integer; + Stretching: Boolean; + AccDelta, Acc: Extended; + Delta, IntAcc: Integer; + MinWidth, MaxWidth, EffectiveMinWidth, EffectiveMaxWidth: Integer; + R: TRect; + + procedure GetSizes(Panel: TTBXDockablePanel; out Size, MinSize, MaxSize: Integer); + var + Sz: TPoint; + MinWidth, MinHeight, MaxWidth, MaxHeight: Integer; + begin + Panel.GetBaseSize(Sz); + if LeftRight then + begin + Size := Panel.SplitHeight; + end + else + begin + Size := Panel.SplitWidth; + end; + MinWidth := 0; MaxWidth := 0; MinHeight := 0; MaxHeight := 0; + Panel.ConstrainedResize(MinWidth, MinHeight, MaxWidth, MaxHeight); + if not LeftRight then begin MinSize := MinWidth; MaxSize := MaxWidth end + else begin MinSize := MinHeight; MaxSize := MaxHeight end; + if MaxSize < MinSize then + begin + MaxSize := DockSize; + if MaxSize < MinSize then MaxSize := MinSize; + end; + if Size < MinSize then Size := MinSize + else if Size > MaxSize then Size := MaxSize; + end; + + procedure GetMinMaxWidth(Panel: TTBXDockablePanel; out Min, Max: Integer); + var + MinWidth, MinHeight, MaxWidth, MaxHeight: Integer; + begin + MinWidth := 0; MaxWidth := 0; MinHeight := 0; MaxHeight := 0; + Panel.ConstrainedResize(MinWidth, MinHeight, MaxWidth, MaxHeight); + if LeftRight then begin Min := MinWidth; Max := MaxWidth end + else begin Min := MinHeight; Max := MaxHeight end; + end; + +begin + if (DisableArrangeToolbars > 0) or (csLoading in ComponentState) then + begin + ArrangeToolbarsNeeded := True; + Exit; + end; + NewDockList := nil; + PosData := nil; + DisableArrangeToolbars := DisableArrangeToolbars + 1; + try + LeftRight := Position in [dpLeft, dpRight]; + + if not HasVisibleToolbars then + begin + EmptySize := Ord(FixAlign); + if csDesigning in ComponentState then EmptySize := 7; + if not LeftRight then ChangeWidthHeight(Width, EmptySize) + else ChangeWidthHeight(EmptySize, Height); + Exit; + end; + + ClientW := Width - NonClientWidth; + if ClientW < 0 then ClientW := 0; + ClientH := Height - NonClientHeight; + if ClientH < 0 then ClientH := 0; + if not LeftRight then DockSize := ClientW + else DockSize := ClientH; + + { Leave some space for dropping other panels in design time } + if csDesigning in ComponentState then Dec(DockSize, DSGN_DROPZONESIZE); + if DockSize < 0 then DockSize := 0; + + + for I := DockList.Count - 1 downto 0 do + begin + T := DockList[I]; + if csDestroying in T.ComponentState then + begin + DockList.Delete(I); + DockVisibleList.Remove(T); + end; + end; + + { always limit to one row } + for I := 0 to DockList.Count - 1 do + with TTBCustomDockableWindow(DockList[I]) do DockRow := 0; + + { Copy DockList to NewDockList, and ensure it is in correct ordering + according to DockRow/DockPos } + NewDockList := TList.Create; + NewDockList.Count := DockList.Count; + for I := 0 to NewDockList.Count - 1 do NewDockList[I] := DockList[I]; + I := NewDockList.IndexOf(DragToolbar); + ListSortEx(NewDockList, CompareDockPos, nil); + DragIndex := NewDockList.IndexOf(DragToolbar); + if (I <> -1) and DragSplitting then + begin + { When splitting, don't allow the toolbar being dragged to change + positions in the dock list } + NewDockList.Move(DragIndex, I); + DragIndex := I; + end; + ListSortEx(DockVisibleList, CompareDockPos, nil); + + { Create a temporary array that holds new position data for the toolbars + and get size info } + SetLength(PosData, 0); + for I := 0 to NewDockList.Count - 1 do + begin + T := NewDockList[I]; + if ToolbarVisibleOnDock(T) then + begin + SetLength(PosData, Length(PosData) + 1); + with PosData[Length(PosData) - 1] do + begin + Panel := T as TTBXDockablePanel; + Pos := Panel.DockPos; + GetSizes(Panel, Size, MinSize, MaxSize{, OrigWidth}); + end; + end; + end; + + { Update drag index... } + if DragIndex >= 0 then + for I := 0 to Length(PosData) - 1 do + if NewDockList.IndexOf(PosData[I].Panel) = DragIndex then + begin + DragIndex := I; + Break; + end; + + { Count total sizes and set initial positions } + DragIndexPos := 0; + TotalSize := 0; TotalMinimumSize := 0; TotalMaximumSize := 0; + for I := 0 to Length(PosData) - 1 do + with PosData[I] do + begin + if I = DragIndex then DragIndexPos := Panel.DockPos; + Pos := TotalSize; + Inc(TotalSize, Size); + Inc(TotalMinimumSize, MinSize); + Inc(TotalMaximumSize, MaxSize); + end; + + if DockSize <> TotalSize then + begin + begin + { Proportionally stretch and shrink toolbars } + + if TotalMinimumSize >= DockSize then + for I := 0 to Length(PosData) - 1 do PosData[I].Size := PosData[I].MinSize + else if TotalMaximumSize <= DockSize then + for I := 0 to Length(PosData) - 1 do PosData[I].Size := PosData[I].MaxSize + else + begin + Delta := DockSize - TotalSize; + StretchPanelCount := 0; + Stretching := TotalSize < DockSize; // otherwise, shrinking + + for I := 0 to Length(PosData) - 1 do + with PosData[I] do + begin + if Stretching then CanStretch := Size < MaxSize + else CanStretch := Size > MinSize; + if CanStretch then Inc(StretchPanelCount); + end; + Assert(StretchPanelCount > 0); + + while Delta <> 0 do + begin + Assert(StretchPanelCount <> 0); + AccDelta := Delta / StretchPanelCount; + Acc := 0; IntAcc := 0; + for I := 0 to Length(PosData) - 1 do + with PosData[I] do if CanStretch then + begin + Acc := Acc + AccDelta; + Inc(Size, Round(Acc) - IntAcc); + IntAcc := Round(Acc); + end; + + TotalSize := 0; + for I := 0 to Length(PosData) - 1 do + with PosData[I] do + begin + if CanStretch then + if Stretching then + begin + if Size > MaxSize then + begin + Size := MaxSize; + CanStretch := False; + Dec(StretchPanelCount); + end; + end + else + begin + if Size < MinSize then + begin + Size := MinSize; + CanStretch := False; + Dec(StretchPanelCount); + end; + end; + Inc(TotalSize, Size); + end; + Delta := DockSize - TotalSize; + end; + end; + + TotalSize := 0; + for I := 0 to Length(PosData) - 1 do + with PosData[I] do + begin + Pos := TotalSize; + Inc(TotalSize, Size); + end; + end + end; + + for I := 0 to NewDockList.Count - 1 do + begin + for J := 0 to Length(PosData) - 1 do + with PosData[J] do + begin + if Panel = NewDockList[I] then + begin + Panel.EffectiveDockRowAccess := 0; + Panel.EffectiveDockPosAccess := PosData[J].Pos; + end; + end; + if CommitNewPositions then + begin + T := NewDockList[I]; + T.DockRow := T.EffectiveDockRow; + T.DockPos := T.EffectiveDockPos; + DockList[I] := NewDockList[I]; + end; + end; + + ResizeIndex := -1; + for I := 0 to Length(PosData) - 1 do + with PosData[I] do + if Panel is TTBXDockablePanel and Panel.IsResizing then + begin + ResizeIndex := I; + Break; + end; + + { Calculate the size of the dock } + if ResizeIndex < 0 then + begin + CurRowSize := 0; + for I := 0 to Length(PosData) - 1 do + with PosData[I] do + begin + Panel.CurrentSize := Size; + Panel.GetBaseSize(S); + if LeftRight then K := S.X + Panel.CalcNCSizes.X else K := S.Y + Panel.CalcNCSizes.Y; + if (DragIndex = I) and (Length(PosData) > 1) and (LastValidRowSize > 0) then K := 0; + if K > CurRowSize then CurRowSize := K; + end; + end + else + begin + EffectiveMinWidth := 0; + EffectiveMaxWidth := 0; + for I := 0 to Length(PosData) - 1 do + begin + GetMinMaxWidth(PosData[I].Panel, MinWidth, MaxWidth); + if MinWidth > EffectiveMinWidth then EffectiveMinWidth := MinWidth; + if (MaxWidth >= MinWidth) and (MaxWidth < EffectiveMaxWidth) then EffectiveMaxWidth := MaxWidth; + end; + if LeftRight then CurRowSize := PosData[ResizeIndex].Panel.Width + else CurRowSize := PosData[ResizeIndex].Panel.Height; + if (EffectiveMaxWidth > EffectiveMinWidth) and (CurRowSize > EffectiveMaxWidth) then CurRowSize := EffectiveMaxWidth; + if CurRowSize < EffectiveMinWidth then CurRowSize := EffectiveMinWidth; + end; + if CurRowSize > 0 then LastValidRowSize := CurRowSize; + + { Now actually move the toolbars } + for I := 0 to Length(PosData) - 1 do + with PosData[I] do + begin + if LeftRight then R := Bounds(0, Pos, CurRowSize, Size) + else R := Bounds(Pos, 0, Size, CurRowSize); + Panel.BoundsRect := R; + { This is to fix some weird behavior in design time } + if csDesigning in ComponentState then + with R do MoveWindow(Panel.Handle, Left, Top, Right - Left, Bottom - Top, True); + end; + + { Set the size of the dock } + if not LeftRight then ChangeWidthHeight(Width, CurRowSize + NonClientHeight) + else ChangeWidthHeight(CurRowSize + NonClientWidth, Height); + + finally + DisableArrangeToolbars := DisableArrangeToolbars - 1; + ArrangeToolbarsNeeded := False; + CommitNewPositions := False; + SetLength(PosData, 0); + NewDockList.Free; + end; +end; + +procedure TTBXMultiDock.Paint; +var + R: TRect; +begin + { Draw dotted border in design mode } + if csDesigning in ComponentState then + begin + R := ClientRect; + with Canvas do + begin + Pen.Style := psSolid; + Pen.Color := clBtnHighlight; + Brush.Color := clBtnHighlight; + Brush.Style := bsFDiagonal; + Rectangle(R.Left, R.Top, R.Right, R.Bottom); + Pen.Style := psSolid; + end; + end; +end; + +procedure TTBXMultiDock.ResizeVisiblePanels(NewSize: Integer); +var + I: Integer; +begin + BeginUpdate; + try + for I := 0 to DockVisibleList.Count - 1 do + if Position in [dpLeft, dpRight] then + TTBXDockablePanel(DockVisibleList[I]).DockedWidth := NewSize + else + TTBXDockablePanel(DockVisibleList[I]).DockedHeight := NewSize; + finally + EndUpdate; + end; +end; + +procedure TTBXMultiDock.ValidateInsert(AComponent: TComponent); +begin + if not (AComponent is TTBXDockablePanel) then + raise EInvalidOperation.CreateFmt('Cannot insert %s into TTBXMultiDock', [AComponent.ClassName]); +end; + +//----------------------------------------------------------------------------// + +{ TTBXPanelObject } + +procedure TTBXPanelObject.CMEnabledChanged(var Message: TMessage); +begin + inherited; + if not Enabled and FMouseInControl then + begin + FMouseInControl := False; + RemoveMouseTimer; + DoMouseLeave; + Invalidate; + Perform(WM_CANCELMODE, 0, 0); + end; +end; + +procedure TTBXPanelObject.CMParentColorChanged(var Message: TMessage); +begin + if Message.WParam = 0 then + begin + Message.WParam := 1; + Message.LParam := GetEffectiveColor(Parent); + end; + inherited; + Invalidate; +end; + +constructor TTBXPanelObject.Create(AOwner: TComponent); +begin + inherited; + ControlStyle := ControlStyle + [csAcceptsControls, csClickEvents, csDoubleClicks] - [csOpaque]; + if MouseTimer = nil then + begin + MouseTimer := TTimer.Create(nil); + MouseTimer.Enabled := False; + MouseTimer.Interval := 125; + end; + Inc(ObjectCount); + ParentColor := False; + Color := clNone; + AddThemeNotification(Self); +end; + +procedure TTBXPanelObject.CreateParams(var Params: TCreateParams); +begin + inherited CreateParams(Params); + if not (csDesigning in ComponentState) then + with Params.WindowClass do style := style and not (CS_HREDRAW or CS_VREDRAW); +// if cpoTransparent in PaintOptions then +// Params.ExStyle := Params.ExStyle or WS_EX_TRANSPARENT; +end; + +destructor TTBXPanelObject.Destroy; +begin + RemoveThemeNotification(Self); + RemoveMouseTimer; + Dec(ObjectCount); + if ObjectCount = 0 then + begin + MouseTimer.Free; + MouseTimer := nil; + end; + inherited; +end; + +procedure TTBXPanelObject.DoMouseEnter; +begin + if Assigned(FOnMouseEnter) then FOnMouseEnter(Self); +end; + +procedure TTBXPanelObject.DoMouseLeave; +begin + if Assigned(FOnMouseLeave) then FOnMouseLeave(Self); +end; + +function TTBXPanelObject.GetMinHeight: Integer; +begin + Result := Height; +end; + +function TTBXPanelObject.GetMinWidth: Integer; +begin + Result := Width; +end; + +procedure TTBXPanelObject.KeyDown(var Key: Word; Shift: TShiftState); +begin + inherited; + if SpaceAsClick and (Key = VK_SPACE) then + begin + FPushed := True; + Invalidate; + end; +end; + +procedure TTBXPanelObject.KeyUp(var Key: Word; Shift: TShiftState); +begin + if SpaceAsClick and Pushed and (Key = VK_SPACE) then + begin + FPushed := False; + Click; + Invalidate; + end; + inherited; +end; + +procedure TTBXPanelObject.MakeVisible; + + procedure HandleScroll(SW: TControl); + begin + if SW is TScrollingWinControl then TScrollingWinControl(SW).ScrollInView(Self) + else if SW is TTBXCustomPageScroller then TTBXCustomPageScroller(SW).ScrollToCenter(Self) + else if (Parent <> nil) and (Parent <> SW) then HandleScroll(Parent); + end; + +begin + HandleScroll(Parent); +end; + +procedure TTBXPanelObject.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); +begin + if (Button = mbLeft) and not FPushed then + begin + FPushed := True; + Invalidate; + end; + if Enabled then MouseEntered; + if not SmartFocus and CanFocus then SetFocus + else if SmartFocus and CanFocus and Assigned(Parent) and IsActivated(Parent) then + begin + FDisableScroll := True; + SetFocus; + FDisableScroll := False; + end; + inherited; +end; + +procedure TTBXPanelObject.MouseEntered; +begin + if Enabled and not FMouseInControl then + begin + FMouseInControl := True; + DoMouseEnter; + end; +end; + +procedure TTBXPanelObject.MouseLeft; +begin + if Enabled and FMouseInControl then + begin + FMouseInControl := False; + RemoveMouseTimer; + DoMouseLeave; + Invalidate; + end; +end; + +procedure TTBXPanelObject.MouseMove(Shift: TShiftState; X, Y: Integer); +var + P: TPoint; + DragTarget: TControl; +begin + P := ClientToScreen(Point(X, Y)); + DragTarget := FindDragTarget(P, True); + if (MouseInObject <> Self) and (DragTarget = Self) then + begin + if Assigned(MouseInObject) then MouseInObject.MouseLeft; + MouseInObject := Self; + MouseTimer.OnTimer := MouseTimerHandler; + MouseTimer.Enabled := True; + MouseEntered; + end + else if (DragTarget <> Self) and (Mouse.Capture = Handle) and FMouseInControl then + begin + MouseLeft; + end; + inherited; +end; + +procedure TTBXPanelObject.MouseTimerHandler(Sender: TObject); +var + P: TPoint; +begin + GetCursorPos(P); + if FindDragTarget(P, True) <> Self then MouseLeft; +end; + +procedure TTBXPanelObject.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); +begin + FPushed := False; + Invalidate; + inherited; +end; + +procedure TTBXPanelObject.RemoveMouseTimer; +begin + if MouseInObject = Self then + begin + MouseTimer.Enabled := False; + MouseInObject := nil; + end; +end; + +procedure TTBXPanelObject.SetPaintOptions(Value: TControlPaintOptions); +begin + if Value <> FPaintOptions then + begin + FPaintOptions := Value; + if cpoDoubleBuffered in Value then DoubleBuffered := True + else DoubleBuffered := False; + RecreateWnd; + end; +end; + +procedure TTBXPanelObject.TBMThemeChange(var Message); +var + R: TRect; +begin + if HandleAllocated then + begin + R := ClientRect; + InvalidateRect(Handle, @R, True); + end; +end; + +procedure TTBXPanelObject.WMEraseBkgnd(var Message: TMessage); +begin + if not DoubleBuffered or (Message.wParam = Message.lParam) then + begin + if Color = clNone then + DrawParentBackground(Self, TWMEraseBkgnd(Message).DC, ClientRect) + else + FillRectEx(TWMEraseBkgnd(Message).DC, ClientRect, Color); + end; + Message.Result := 1; +end; + +procedure TTBXPanelObject.WMKillFocus(var Message: TMessage); +begin + FPushed := False; + Invalidate; +end; + +procedure TTBXPanelObject.WMSetFocus(var Message: TMessage); +begin + inherited; + if not FDisableScroll then MakeVisible; + Invalidate; +end; + +//----------------------------------------------------------------------------// + +{ TTBXDockablePanel } + +procedure TTBXDockablePanel.AdjustClientRect(var Rect: TRect); +begin + inherited AdjustClientRect(Rect); + if BorderSize <> 0 then InflateRect(Rect, -BorderSize, -BorderSize); +end; + +procedure TTBXDockablePanel.BeginDockedSizing(HitTest: Integer); +var + OrigPos, OldPos: TPoint; + Msg: TMsg; + DockRect, DragRect, OrigDragRect, OldDragRect: TRect; + NCSizes: TPoint; + EdgeRect, OldEdgeRect: TRect; + ScreenDC: HDC; + EraseEdgeRect, CommitResizing: Boolean; + Form: TCustomForm; + LeftRight: Boolean; + + function RectToScreen(const R: TRect): TRect; + begin + Result := R; + Result.TopLeft := Parent.ClientToScreen(Result.TopLeft); + Result.BottomRight := Parent.ClientToScreen(Result.BottomRight); + end; + + function RectToClient(const R: TRect): TRect; + begin + Result := R; + Result.TopLeft := Parent.ScreenToClient(Result.TopLeft); + Result.BottomRight := Parent.ScreenToClient(Result.BottomRight); + end; + + function GetEdgeRect(const R: TRect): TRect; + begin + Result := DockRect; + case HitTest of + HTLEFT: begin Result.Left := R.Left - 1; Result.Right := R.Left + 1 end; + HTRIGHT: begin Result.Left := R.Right - 1; Result.Right := R.Right + 1 end; + HTTOP: begin Result.Top := R.Top - 1; Result.Bottom := R.Top + 1 end; + HTBOTTOM: begin Result.Top := R.Bottom - 1; Result.Bottom := R.Bottom + 1 end; + end; + end; + + procedure MouseMoved; + var + Pos: TPoint; + NewWidth: Integer; + NewHeight: Integer; + begin + GetCursorPos(Pos); + if (Pos.X = OldPos.X) and (Pos.Y = OldPos.Y) then Exit; + DragRect := OrigDragRect; + case HitTest of + HTLEFT: + begin + NewWidth := DragRect.Right - (DragRect.Left + Pos.X - OrigPos.X - 1); + if DoDockedResizing(False, NewWidth) then + DragRect.Left := DragRect.Right - NewWidth; + end; + HTRIGHT: + begin + NewWidth := (DragRect.Right + Pos.X - OrigPos.X) - DragRect.Left; + if DoDockedResizing(False, NewWidth) then + DragRect.Right := DragRect.Left + NewWidth; + end; + HTTOP: + begin + NewHeight := DragRect.Bottom - (DragRect.Top + Pos.Y - OrigPos.Y - 1); + if DoDockedResizing(True, NewHeight) then + DragRect.Top := DragRect.Bottom - NewHeight; + end; + HTBOTTOM: + begin + NewHeight := (DragRect.Bottom + Pos.Y - OrigPos.Y) - DragRect.Top; + if DoDockedResizing(True, NewHeight) then + DragRect.Bottom := DragRect.Top + NewHeight; + end; + end; + if not CompareMem(@OldDragRect, @DragRect, SizeOf(TRect)) then + begin + if SmoothDockedResize then + begin + CurrentDock.BeginUpdate; + if HitTest in [HTLEFT, HTRIGHT] then + begin + BlockSizeUpdate := True; + DockedWidth := DragRect.Right - DragRect.Left - NCSizes.X; + end + else + begin + BlockSizeUpdate := True; + DockedHeight := DragRect.Bottom - DragRect.Top - NCSizes.Y; + end; + BlockSizeUpdate := False; + CurrentDock.EndUpdate; + end + else + begin + EdgeRect := GetEdgeRect(DragRect); + DrawDraggingOutline(ScreenDC, EdgeRect, OldEdgeRect); + OldEdgeRect := EdgeRect; + EraseEdgeRect := True; + end; + OldPos := Pos; + OldDragRect := DragRect; + end; + end; + +begin + LeftRight := HitTest in [HTLEFT, HTRIGHT]; + if DoBeginDockedResizing(HitTest in [HTTOP, HTBOTTOM]) then + try + SetCapture(Handle); + ScreenDC := GetDC(0); + OrigDragRect := RectToScreen(BoundsRect); + DockRect := RectToScreen(CurrentDock.ClientRect); + OldDragRect := Rect(0, 0, 0, 0); + NCSizes := CalcNCSizes; + DragRect := OrigDragRect; + GetCursorPos(OrigPos); + OldPos := OrigPos; + FIsResizing := True; + + if not SmoothDockedResize then + begin + EdgeRect := GetEdgeRect(DragRect); + DrawDraggingOutline(ScreenDC, EdgeRect, Rect(0, 0, 0, 0)); + OldEdgeRect := EdgeRect; + EraseEdgeRect := True; + end + else EraseEdgeRect := False; + + while GetCapture = Handle do + begin + case Integer(GetMessage(Msg, 0, 0, 0)) of + -1: Break; + 0: begin + PostQuitMessage(Msg.WParam); + Break; + end; + end; + case Msg.Message of + WM_KEYDOWN, WM_KEYUP: if Msg.WParam = VK_ESCAPE then Break; + WM_MOUSEMOVE: MouseMoved; + WM_LBUTTONDOWN, WM_LBUTTONDBLCLK:Break; + WM_LBUTTONUP: Break; + WM_RBUTTONDOWN..WM_MBUTTONDBLCLK:; + else + TranslateMessage(Msg); + DispatchMessage(Msg); + end; + end; + finally + if GetCapture = Handle then ReleaseCapture; + CommitResizing := DoEndDockedResizing(HitTest in [HTTOP, HTBOTTOM]); + if EraseEdgeRect then + begin + DrawDraggingOutline(ScreenDC, Rect(0, 0, 0, 0), OldEdgeRect); + if CommitResizing then with OldDragRect do + begin + BlockSizeUpdate := True; + if LeftRight then DockedWidth := Right - Left - NCSizes.X + else DockedHeight := Bottom - Top - NCSizes.Y; + BlockSizeUpdate := False; + end; + end + else if not CommitResizing then + begin + BlockSizeUpdate := True; + BoundsRect := RectToClient(OrigDragRect); + BlockSizeUpdate := False; + end; + ReleaseDC(0, ScreenDC); + FIsResizing := False; + if csDesigning in ComponentState then + begin + Form := GetParentForm(Self); + if (Form <> nil) and (Form.Designer <> nil) then Form.Designer.Modified; + end; + end; +end; + +procedure TTBXDockablePanel.BeginSplitResizing(HitTest: Integer); +type + TPosRec = record + Panel: TTBXDockablePanel; + OrigPos, OrigSize, OrigWidth, Pos, Size, MinSize, MaxSize: Integer; + end; +var + Dock: TDockAccess; + PosData: array of TPosRec; + I: Integer; + LeftRight, Smooth, CommitResizing: Boolean; + DockSize, TotalSize, TotalMinSize, TotalMaxSize: Integer; + OrigCursorPos, OldCursorPos: TPoint; + Msg: TMsg; + EffectiveIndex: Integer; + EffectivePanel: TTBXDockablePanel; + PanelRect, DockRect, EdgeRect, OrigEdgeRect, OldEdgeRect: TRect; + EdgePosition: TTBDockPosition; + ScreenDC: HDC; + EraseEdgeRect: Boolean; + Form: TCustomForm; + Delta: Integer; + + procedure GetSizes(Panel: TTBXDockablePanel; out Size, MinSize, MaxSize, W: Integer); + var + Sz: TPoint; + MinWidth, MinHeight, MaxWidth, MaxHeight: Integer; + begin + Panel.GetBaseSize(Sz); + if not LeftRight then + begin + Size := Panel.Width; + W := Panel.Height; + end + else + begin + Size := Panel.Height; + W := Panel.Width; + end; + MinWidth := 0; MaxWidth := 0; MinHeight := 0; MaxHeight := 0; + Panel.ConstrainedResize(MinWidth, MinHeight, MaxWidth, MaxHeight); + if not LeftRight then begin MinSize := MinWidth; MaxSize := MaxWidth; end + else begin MinSize := MinHeight; MaxSize := MaxHeight end; + if MaxSize < MinSize then + begin + MaxSize := DockSize; + if MaxSize < MinSize then MaxSize := MinSize; + end; + if Size < MinSize then Size := MinSize + else if Size > MaxSize then Size := MaxSize; + end; + + procedure BlockSizeUpdates(DoBlock: Boolean); + var + I: Integer; + begin + for I := 0 to Length(PosData) - 1 do + with PosData[I].Panel do BlockSizeUpdate := DoBlock; + end; + + procedure SetSizes(RestoreOriginal: Boolean = False); + var + I: Integer; + R: TRect; + begin + Dock.BeginUpdate; + BlockSizeUpdates(True); + for I := 0 to Length(PosData) - 1 do + with PosData[I] do + begin + if LeftRight then + begin + if RestoreOriginal then R := Bounds(0, OrigPos, OrigWidth, OrigSize) + else R := Bounds(0, Pos, OrigWidth, Size); + end + else + begin + if RestoreOriginal then R := Bounds(OrigPos, 0, OrigSize, OrigWidth) + else R := Bounds(Pos, 0, Size, OrigWidth); + end; + if LeftRight then Panel.SplitHeight := Size + else Panel.SplitWidth := Size; + Panel.BoundsRect := R; + + { This is to fix some weird behavior in design time } + if csDesigning in ComponentState then + with R do MoveWindow(Panel.Handle, Left, Top, Right - Left, Bottom - Top, True); + end; + BlockSizeUpdates(False); + Dock.EndUpdate; + end; + + function GetEdgeRect(R: TRect): TRect; + begin + Result := R; + case EdgePosition of + dpRight: begin Result.Left := Result.Right - 1; Inc(Result.Right); end; + dpBottom: begin Result.Top := Result.Bottom - 1; Inc(Result.Bottom); end; + end; + end; + + function RectToScreen(const R: TRect): TRect; + begin + Result := R; + Result.TopLeft := Parent.ClientToScreen(Result.TopLeft); + Result.BottomRight := Parent.ClientToScreen(Result.BottomRight); + end; + + function RectToClient(const R: TRect): TRect; + begin + Result := R; + Result.TopLeft := Parent.ScreenToClient(Result.TopLeft); + Result.BottomRight := Parent.ScreenToClient(Result.BottomRight); + end; + + procedure MouseMoved; + var + CursorPos: TPoint; + I, P, Acc: Integer; + begin + GetCursorPos(CursorPos); + if (CursorPos.X = OldCursorPos.X) and (CursorPos.Y = OldCursorPos.Y) then Exit; + case EdgePosition of + dpRight: Delta := CursorPos.X - OrigCursorPos.X; + dpBottom: Delta := CursorPos.Y - OrigCursorPos.Y; + end; + if Delta = 0 then Exit; + + for I := 0 to Length(PosData) - 1 do + with PosData[I] do + begin + Pos := OrigPos; + Size := OrigSize; + end; + + Acc := Delta; + for I := EffectiveIndex downto 0 do + with PosData[I] do + begin + Inc(Size, Acc); Acc := 0; + if Size > MaxSize then + begin + Acc := Size - MaxSize; + Size := MaxSize; + end + else if Size < MinSize then + begin + Acc := Size - MinSize; + Size := MinSize; + end; + if Acc = 0 then Break; + end; + + if Acc <> 0 then Dec(Delta, Acc); + + Acc := Delta; + for I := EffectiveIndex + 1 to Length(PosData) - 1 do + with PosData[I] do + begin + Dec(Size, Acc); Acc := 0; + if Size > MaxSize then + begin + Acc := MaxSize - Size; + Size := MaxSize; + end + else if Size < MinSize then + begin + Acc := MinSize - Size; + Size := MinSize; + end; + if Acc = 0 then Break; + end; + + if Acc <> 0 then + begin + Dec(Delta, Acc); + for I := 0 to EffectiveIndex do with PosData[I] do Size := OrigSize; + Acc := Delta; + for I := EffectiveIndex downto 0 do + with PosData[I] do + begin + Inc(Size, Acc); Acc := 0; + if Size > MaxSize then + begin + Acc := Size - MaxSize; + Size := MaxSize; + end + else if Size < MinSize then + begin + Acc := Size - MinSize; + Size := MinSize; + end; + if Acc = 0 then Break; + end; + end; + + P := 0; + for I := 0 to Length(PosData) - 1 do + with PosData[I] do begin Pos := P; Inc(P, Size); end; + + if Smooth then SetSizes + else + begin + EdgeRect := DockRect; + if LeftRight then + begin + Inc(EdgeRect.Top, PosData[EffectiveIndex + 1].Pos - 1); + EdgeRect.Bottom := EdgeRect.Top + 2; + end + else + begin + Inc(EdgeRect.Left, PosData[EffectiveIndex + 1].Pos - 1); + EdgeRect.Right := EdgeRect.Left + 2; + end; + DrawDraggingOutline(ScreenDC, EdgeRect, OldEdgeRect); + EraseEdgeRect := True; + end; + + OldCursorPos := CursorPos; + OldEdgeRect := EdgeRect; + end; + +begin + if not (CurrentDock is TTBXMultiDock) then Exit; + Dock := TDockAccess(CurrentDock); + + SetLength(PosData, Dock.DockVisibleList.Count); + for I := 0 to Dock.DockVisibleList.Count - 1 do + with PosData[I] do + begin + { only docks with TTBXDockablePanels can be resized } + if not (TTBCustomDockableWindow(Dock.DockVisibleList[I]) is TTBXDockablePanel) then Exit; + Panel := TTBXDockablePanel(Dock.DockVisibleList[I]); + end; + + LeftRight := Dock.Position in [dpLeft, dpRight]; + if not LeftRight then DockSize := Dock.Width - Dock.NonClientWidth + else DockSize := Dock.Height - Dock.NonClientHeight; + if DockSize < 0 then DockSize := 0; + + { See if we can actually resize anything } + TotalSize := 0; TotalMinSize := 0; TotalMaxSize := 0; + for I := 0 to Length(PosData) - 1 do + with PosData[I] do + begin + GetSizes(Panel, Size, MinSize, MaxSize, OrigWidth); + OrigSize := Size; + OrigPos := TotalSize; + Pos := OrigPos; + Inc(TotalSize, Size); + Inc(TotalMinSize, MinSize); + Inc(TotalMaxSize, MaxSize); + end; + if (TotalMinSize > DockSize) or (TotalMaxSize < DockSize) then Exit; + + { Get effective edge and panel } + case HitTest of + HT_TBX_SPLITRESIZETOP: EdgePosition := dpTop; + HT_TBX_SPLITRESIZEBOTTOM: EdgePosition := dpBottom; + HT_TBX_SPLITRESIZELEFT: EdgePosition := dpLeft; + else + EdgePosition := dpRight; + end; + Smooth := True; + EffectivePanel := Self; + for I := 0 to Length(PosData) - 1 do + with PosData[I] do + begin + if not Panel.SmoothDockedResize then Smooth := False; + if Panel = Self then + begin + EffectiveIndex := I; + if EdgePosition in [dpLeft, dpTop] then + begin + Assert(I > 0); + EffectivePanel := PosData[I - 1].Panel; + if EdgePosition = dpLeft then EdgePosition := dpRight + else EdgePosition := dpBottom; + Dec(EffectiveIndex); + end; + end; + end; + + try + SetCapture(Handle); + ScreenDC := GetDC(0); + with EffectivePanel do PanelRect := RectToScreen(BoundsRect); + DockRect := RectToScreen(Dock.ClientRect); + GetCursorPos(OrigCursorPos); + OldCursorPos := OrigCursorPos; + OrigEdgeRect := GetEdgeRect(PanelRect); + OldEdgeRect := Rect(0, 0, 0, 0); + EdgeRect := OrigEdgeRect; + FIsSplitting := True; + + if not Smooth then + begin + DrawDraggingOutline(ScreenDC, EdgeRect, Rect(0, 0, 0, 0)); + OldEdgeRect := EdgeRect; + EraseEdgeRect := True; + end + else EraseEdgeRect := False; + + while GetCapture = Handle do + begin + case Integer(GetMessage(Msg, 0, 0, 0)) of + -1: Break; + 0: begin + PostQuitMessage(Msg.WParam); + Break; + end; + end; + case Msg.Message of + WM_KEYDOWN, WM_KEYUP: if Msg.WParam = VK_ESCAPE then Break; + WM_MOUSEMOVE: MouseMoved; + WM_LBUTTONDOWN, WM_LBUTTONDBLCLK:Break; + WM_LBUTTONUP: Break; + WM_RBUTTONDOWN..WM_MBUTTONDBLCLK:; + else + TranslateMessage(Msg); + DispatchMessage(Msg); + end; + end; + finally + if GetCapture = Handle then ReleaseCapture; + CommitResizing := True; + if EraseEdgeRect then + begin + DrawDraggingOutline(ScreenDC, Rect(0, 0, 0, 0), OldEdgeRect); + if CommitResizing then SetSizes; + end + else if not CommitResizing then SetSizes(True); + ReleaseDC(0, ScreenDC); + FIsSplitting := False; + if csDesigning in ComponentState then + begin + Form := GetParentForm(Self); + if (Form <> nil) and (Form.Designer <> nil) then Form.Designer.Modified; + end; + end; +end; + +function TTBXDockablePanel.CalcNCSizes: TPoint; +begin + if not Docked then + begin + Result.X := 0; + Result.Y := 0; + end + else + begin + Result.X := DockedBorderSize * 2; + Result.Y := DockedBorderSize * 2; + if ShowCaptionWhenDocked then + if IsVertCaption then Inc(Result.X, GetSystemMetrics(SM_CYSMCAPTION)) + else Inc(Result.Y, GetSystemMetrics(SM_CYSMCAPTION)); + end; +end; + +function TTBXDockablePanel.CalcSize(ADock: TTBDock): TPoint; +begin + if Assigned(ADock) then + begin + if ADock.Position in [dpLeft, dpRight] then + begin + Result.X := FDockedWidth; + Result.Y := ADock.ClientHeight - CalcNCSizes.Y; + end + else + begin + Result.X := ADock.ClientWidth - CalcNCSizes.X; + Result.Y := FDockedHeight; + end; + end + else + begin + { if floating width and height are yet undefined, copy them from docked width and height } + if FFloatingWidth = 0 then + begin + if Docked and (CurrentDock.Position in [dpTop, dpBottom]) then + FFloatingWidth := Width {CurrentDock.ClientWidth} - CalcNCSizes.X + else + FFloatingWidth := FDockedWidth; + end; + + if FFloatingHeight = 0 then + begin + if Docked and (CurrentDock.Position in [dpLeft, dpRight]) then + FFloatingHeight := {CurrentDock.ClientHeight} Height - CalcNCSizes.Y + else + FFloatingHeight := FDockedHeight; + end; + + Result.X := FFloatingWidth; + Result.Y := FFloatingHeight; + end; +end; + +function TTBXDockablePanel.CanAutoSize(var NewWidth, NewHeight: Integer): Boolean; +begin + Result := True; +end; + +function TTBXDockablePanel.CanDockTo(ADock: TTBDock): Boolean; +begin + Result := inherited CanDockTo(ADock); + if Result then + begin + if ADock is TTBXMultiDock then + begin + Result := dkMultiDock in SupportedDocks; + end + else + begin + Result := dkStandardDock in SupportedDocks;; + end; + end; +end; + +function TTBXDockablePanel.CanSplitResize(EdgePosition: TTBDockPosition): Boolean; +var + Dock: TDockAccess; +begin + Result := Docked and (CurrentDock is TTBXMultiDock) and HandleAllocated; + if not Result then Exit; + Dock := TDockAccess(CurrentDock); + ListSortEx(Dock.DockVisibleList, CompareEffectiveDockPos, nil); + if Dock.Position in [dpLeft, dpRight] then + begin + case EdgePosition of + dpTop: Result := EffectiveDockPos > 0; + dpBottom: Result := Dock.DockVisibleList.Last <> Self; + else + Result := False; + end; + end + else + begin + case EdgePosition of + dpLeft: Result := EffectiveDockPos > 0; + dpRight: Result := Dock.DockVisibleList.Last <> Self; + else + Result := False; + end; + end; +end; + +procedure TTBXDockablePanel.CMColorChanged(var Message: TMessage); +begin + UpdateEffectiveColor; + Brush.Color := Color; + if Docked and HandleAllocated then + begin + RedrawWindow(Handle, nil, 0, RDW_FRAME or RDW_INVALIDATE or + RDW_ERASE or RDW_UPDATENOW or RDW_ALLCHILDREN); + end; + Invalidate; + UpdateChildColors; +end; + +procedure TTBXDockablePanel.CMControlChange(var Message: TCMControlChange); +begin + inherited; + if Message.Inserting and (Color = clNone) then + Message.Control.Perform(CM_PARENTCOLORCHANGED, 1, EffectiveColor); +end; + +procedure TTBXDockablePanel.CMTextChanged(var Message: TMessage); +begin + inherited; + if HandleAllocated then + begin + if Docked then RedrawWindow(Handle, nil, 0, RDW_FRAME or RDW_INVALIDATE) + else RedrawWindow(TTBXFloatingWindowParent(Parent).Handle, nil, 0, RDW_FRAME or RDW_INVALIDATE); + end; +end; + +procedure TTBXDockablePanel.ConstrainedResize(var MinWidth, MinHeight, MaxWidth, MaxHeight: Integer); +var + Sz: TPoint; +begin + Sz := CalcNCSizes; + if MinClientWidth > 0 then MinWidth := MinClientWidth + Sz.X; + if MinClientHeight > 0 then MinHeight := MinClientHeight + Sz.Y; + if MaxClientWidth > 0 then MaxWidth := MaxClientWidth + Sz.X; + if MaxClientHeight > 0 then MaxHeight := MaxClientHeight + Sz.Y; +end; + +constructor TTBXDockablePanel.Create(AOwner: TComponent); +begin + inherited; + FMinClientWidth := 32; + FMinClientHeight := 32; + FDockedWidth := 128; + FDockedHeight := 128; + CloseButtonWhenDocked := True; + DblClickUndock := False; + FShowCaptionWhenDocked := True; + FSmoothDockedResize := True; + BlockSizeUpdate := True; + SetBounds(Left, Top, 128, 128); + BlockSizeUpdate := False; + FullSize := True; + Color := clNone; + AddThemeNotification(Self); + SupportedDocks := [dkStandardDock, dkMultiDock]; +end; + +destructor TTBXDockablePanel.Destroy; +begin + RemoveThemeNotification(Self); + inherited; +end; + +function TTBXDockablePanel.DoArrange(CanMoveControls: Boolean; + PreviousDockType: TTBDockType; NewFloating: Boolean; NewDock: TTBDock): TPoint; +begin + Result := CalcSize(NewDock); +end; + +function TTBXDockablePanel.DoBeginDockedResizing(Vertical: Boolean): Boolean; +var + Sz: Integer; +begin + Result := True; + if Vertical then Sz := Height else Sz := Width; + if Assigned(FOnDockedResizing) then FOnDockedResizing(Self, Vertical, Sz, rsBeginResizing, Result); + if Result then + if Vertical then Height := Sz else Width := Sz; +end; + +function TTBXDockablePanel.DoDockedResizing(Vertical: Boolean; var NewSize: Integer): Boolean; +const + MIN_PARENT_CLIENT_SIZE = 32; +var + NCSizes: TPoint; + CW, CH: Integer; + DockParent: TWinControl; + ClientSize: TPoint; +begin + NCSizes := CalcNCSizes; + DockParent := Parent.Parent; + ClientSize := GetClientSizeEx(DockParent); + + Assert(DockParent <> nil); + if not Vertical then + begin + CW := ClientSize.X - MIN_PARENT_CLIENT_SIZE + Width; + if NewSize > CW then NewSize := CW; + CW := NewSize - NCSizes.X; + if CW < MinClientWidth then CW := MinClientWidth + else if (MaxClientWidth > MinClientWidth) and (CW > MaxClientWidth) then CW := MaxClientWidth; + NewSize := CW + NCSizes.X; + end + else + begin + CH := ClientSize.Y - MIN_PARENT_CLIENT_SIZE + Height; + if NewSize > CH then NewSize := CH; + CH := NewSize - NCSizes.Y; + if CH < MinClientHeight then CH := MinClientHeight + else if (MaxClientHeight > MinClientHeight) and (CH > MaxClientHeight) then CH := MaxClientHeight; + NewSize := CH + NCSizes.Y; + end; + Result := True; + if Assigned(FOnDockedResizing) then FOnDockedResizing(Self, Vertical, NewSize, rsResizing, Result); +end; + +function TTBXDockablePanel.DoEndDockedResizing(Vertical: Boolean): Boolean; +var + Sz: Integer; +begin + Result := True; + if Vertical then Sz := Height else Sz := Width; + if Assigned(FOnDockedResizing) then + FOnDockedResizing(Self, Vertical, Sz, rsEndResizing, Result); + if Result then + if Vertical then Height := Sz else Width := Sz; +end; + +procedure TTBXDockablePanel.DrawNCArea(const DrawToDC: Boolean; + const ADC: HDC; const Clip: HRGN); +var + DC: HDC; + R, CR: TRect; + ACanvas: TCanvas; + Sz: Integer; + DockPanelInfo: TTBXDockPanelInfo; + S: string; +begin + if not Docked or not HandleAllocated then Exit; + + if not DrawToDC then DC := GetWindowDC(Handle) + else DC := ADC; + + Assert(DC <> 0, 'TTBXToolWindow.DrawNCArea Error'); + try + GetDockPanelInfo(DockPanelInfo); + GetWindowRect(Handle, R); + OffsetRect(R, -R.Left, -R.Top); + if not DrawToDC then + begin + SelectNCUpdateRgn(Handle, DC, Clip); + CR := R; + with DockPanelInfo.BorderSize, CR do + begin + InflateRect(CR, -X, -Y); + if DockPanelInfo.ShowCaption then + begin + Sz := GetSystemMetrics(SM_CYSMCAPTION); + if DockPanelInfo.IsVertical then Inc(Top, Sz) + else Inc(Left, Sz); + end; + ExcludeClipRect(DC, Left, Top, Right, Bottom); + end; + end; + S := Caption; + DockPanelInfo.Caption := PChar(S); + ACanvas := TCanvas.Create; + try + ACanvas.Handle := DC; + ACanvas.Brush.Color := EffectiveColor; + CurrentTheme.PaintDockPanelNCArea(ACanvas, R, DockPanelInfo); + finally + ACanvas.Handle := 0; + ACanvas.Free; + end; + finally + if not DrawToDC then ReleaseDC(Handle, DC); + end; +end; + +procedure TTBXDockablePanel.GetBaseSize(var ASize: TPoint); +begin + ASize := CalcSize(CurrentDock); +end; + +function TTBXDockablePanel.GetDockedCloseButtonRect(LeftRight: Boolean): TRect; +var + X, Y, Z: Integer; +begin + Z := GetSystemMetrics(SM_CYSMCAPTION) - 1; + if LeftRight or not IsVertCaption then + begin + X := (ClientWidth + DockedBorderSize) - Z; + Y := DockedBorderSize; + end + else + begin + X := DockedBorderSize; + Y := ClientHeight + DockedBorderSize - Z; + end; + Result := Bounds(X, Y, Z, Z); +end; + +procedure TTBXDockablePanel.GetDockPanelInfo(out DockPanelInfo: TTBXDockPanelInfo); +begin + FillChar(DockPanelInfo, SizeOf(DockPanelInfo), 0); + DockPanelInfo.WindowHandle := WindowHandle; + DockPanelInfo.ViewType := GetViewType; + if CurrentDock <> nil then DockPanelInfo.IsVertical := not IsVertCaption; + DockPanelInfo.AllowDrag := CurrentDock.AllowDrag; + DockPanelInfo.BorderStyle := BorderStyle; + CurrentTheme.GetViewBorder(DockPanelInfo.ViewType, DockPanelInfo.BorderSize); + DockPanelInfo.ClientWidth := ClientWidth; + DockPanelInfo.ClientHeight := ClientHeight; + DockPanelInfo.ShowCaption := ShowCaptionWhenDocked; + DockPanelInfo.EffectiveColor := EffectiveColor; + if ShowCaptionWhenDocked and CloseButtonWhenDocked then + begin + DockPanelInfo.CloseButtonState := CDBS_VISIBLE; + if CloseButtonDown then DockPanelInfo.CloseButtonState := DockPanelInfo.CloseButtonState or CDBS_PRESSED; + if CloseButtonHover then DockPanelInfo.CloseButtonState := DockPanelInfo.CloseButtonState or CDBS_HOT; + end; +end; + +function TTBXDockablePanel.GetFloatingBorderSize: TPoint; +begin + CurrentTheme.GetViewBorder(GetViewType or DPVT_FLOATING, Result); +end; + +function TTBXDockablePanel.GetFloatingWindowParentClass: TTBFloatingWindowParentClass; +begin + Result := TTBXFloatingWindowParent; +end; + +procedure TTBXDockablePanel.GetMinMaxSize(var AMinClientWidth, AMinClientHeight, + AMaxClientWidth, AMaxClientHeight: Integer); +begin + AMinClientWidth := FMinClientWidth; + AMinClientHeight := FMinClientHeight; + AMaxClientWidth := FMaxClientWidth; + AMaxClientHeight := FMaxClientHeight; +end; + +function TTBXDockablePanel.GetViewType: Integer; +begin + Result := DPVT_NORMAL; + if Floating then Result := Result or DPVT_FLOATING; + if Resizable then Result := Result or DPVT_RESIZABLE; +end; + +function TTBXDockablePanel.IsVertCaption: Boolean; +begin + case CaptionRotation of + dpcrAlwaysHorz: Result := False; + dpcrAlwaysVert: Result := Docked; + else // dpcrAuto: + Result := Docked and (CurrentDock.Position in [dpTop, dpBottom]); + end; +end; + +procedure TTBXDockablePanel.Loaded; +begin + inherited; + UpdateChildColors; +end; + +procedure TTBXDockablePanel.Paint; +begin + if csDesigning in ComponentState then with Canvas do + begin + Pen.Style := psDot; + Pen.Color := clBtnShadow; + Brush.Style := bsClear; + with ClientRect do Rectangle(Left, Top, Right, Bottom); + Pen.Style := psSolid; + end; +end; + +procedure TTBXDockablePanel.ReadPositionData(const Data: TTBReadPositionData); +begin + with Data do + begin + FDockedWidth := ReadIntProc(Name, rvDockedWidth, FDockedWidth, ExtraData); + FDockedHeight := ReadIntProc(Name, rvDockedHeight, FDockedHeight, ExtraData); + FFloatingWidth := ReadIntProc(Name, rvFloatingWidth, FFloatingWidth, ExtraData); + FFloatingHeight := ReadIntProc(Name, rvFloatingHeight, FFloatingHeight, ExtraData); + FSplitWidth := ReadIntProc(Name, rvSplitWidth, FSplitWidth, ExtraData); + FSplitHeight := ReadIntProc(Name, rvSplitHeight, FSplitHeight, ExtraData); + end; +end; + +procedure TTBXDockablePanel.SetBorderSize(Value: Integer); +begin + if FBorderSize <> Value then + begin + FBorderSize := Value; + Realign; + end; +end; + +procedure TTBXDockablePanel.SetBounds(ALeft, ATop, AWidth, AHeight: Integer); +begin + inherited SetBounds(ALeft, ATop, AWidth, AHeight); +end; + +procedure TTBXDockablePanel.SetCaptionRotation(Value: TDPCaptionRotation); +begin + if FCaptionRotation <> Value then + begin + FCaptionRotation := Value; + if Docked and HandleAllocated then + SetWindowPos(Handle, 0, 0, 0, 0, 0, SWP_FRAMECHANGED or + SWP_NOACTIVATE or SWP_NOMOVE or SWP_NOSIZE or SWP_NOZORDER); + end; +end; + +procedure TTBXDockablePanel.SetDockedHeight(Value: Integer); +begin + if Value < MinClientHeight then Value := MinClientHeight; + if Value <> FDockedHeight then + begin + FDockedHeight := Value; + if Docked and (CurrentDock.Position in [dpTop, dpBottom]) then + begin + BlockSizeUpdate := True; + Height := Value + CalcNCSizes.Y; + BlockSizeUpdate := False; + end; + end; +end; + +procedure TTBXDockablePanel.SetDockedWidth(Value: Integer); +begin + if Value < MinClientWidth then Value := MinClientWidth; + if Value <> FDockedWidth then + begin + FDockedWidth := Value; + if Docked and (CurrentDock.Position in [dpLeft, dpRight]) then + begin + BlockSizeUpdate := True; + Width := Value + CalcNCSizes.X; + BlockSizeUpdate := False; + end; + end; +end; + +procedure TTBXDockablePanel.SetFloatingHeight(Value: Integer); +begin + { FloatingHeight (and floating width) can be set to 0 while panel is docked. + This will force to restore floating dimensions from docked size } + if Value < 0 then Value := 0; + if not Docked and (Value < MinClientHeight) then Value := MinClientHeight; + if Value <> FFloatingHeight then + begin + FFloatingHeight := Value; + if not Docked then + begin + BlockSizeUpdate := True; + Height := Value + CalcNCSizes.Y; + BlockSizeUpdate := False; + end; + end; +end; + +procedure TTBXDockablePanel.SetFloatingWidth(Value: Integer); +begin + { See comment for TTBXDockablePanel.SetFloatingHeight } + if Value < 0 then Value := 0; + if not Docked and (Value < MinClientWidth) then Value := MinClientWidth; + if Value <> FFloatingWidth then + begin + FFloatingWidth := Value; + if not Docked then + begin + BlockSizeUpdate := True; + Width := Value + CalcNCSizes.X; + BlockSizeUpdate := False; + end; + end; +end; + +procedure TTBXDockablePanel.SetMinClientHeight(Value: Integer); +begin + if Value < 8 then Value := 8; + FMinClientHeight := Value; +end; + +procedure TTBXDockablePanel.SetMinClientWidth(Value: Integer); +begin + if Value < 8 then Value := 8; + FMinClientWidth := Value; +end; + +procedure TTBXDockablePanel.SetParent(AParent: TWinControl); +begin + inherited; + if AParent is TTBXFloatingWindowParent then + TTBXFloatingWindowParent(AParent).SnapDistance := SnapDistance; +end; + +procedure TTBXDockablePanel.SetShowCaptionWhenDocked(Value: Boolean); +begin + if FShowCaptionWhenDocked <> Value then + begin + FShowCaptionWhenDocked := Value; + if Docked then + begin + if HandleAllocated then + SetWindowPos(Handle, 0, 0, 0, 0, 0, SWP_FRAMECHANGED or + SWP_NOACTIVATE or SWP_NOMOVE or SWP_NOSIZE or SWP_NOZORDER); + end; + end; +end; + +procedure TTBXDockablePanel.SetSnapDistance(Value: Integer); +begin + if Value < 0 then Value := 0; + FSnapDistance := Value; + if (Parent <> nil) and (Parent is TTBXFloatingWindowParent) then + TTBXFloatingWindowParent(Parent).SnapDistance := Value; +end; + +procedure TTBXDockablePanel.SetSplitHeight(Value: Integer); +begin + if Value < 0 then Value := 0; + if FSplitHeight <> Value then + begin + FSplitHeight := Value; + if Docked and (CurrentDock.Position in [dpLeft, dpRight]) and + (CurrentDock is TTBXMultiDock) then CurrentDock.ArrangeToolbars; + end; +end; + +procedure TTBXDockablePanel.SetSplitWidth(Value: Integer); +begin + if Value < 0 then Value := 0; + if FSplitWidth <> Value then + begin + FSplitWidth := Value; + if Docked and (CurrentDock.Position in [dpTop, dpBottom]) and + (CurrentDock is TTBXMultiDock) then CurrentDock.ArrangeToolbars; + end; +end; + +procedure TTBXDockablePanel.SizeChanging(const AWidth, AHeight: Integer); +begin + if not BlockSizeUpdate then + begin + if Docked and (CurrentDock.Position in [dpLeft, dpRight]) then + FDockedWidth := AWidth - CalcNCSizes.X + else if Floating then + FFloatingWidth := AWidth - CalcNCSizes.X; + + if Docked and (CurrentDock.Position in [dpTop, dpBottom]) then + FDockedHeight := AHeight - CalcNCSizes.Y + else if Floating then + FFloatingHeight := AHeight - CalcNCSizes.Y; + end; +end; + +procedure TTBXDockablePanel.TBMGetEffectiveColor(var Message: TMessage); +begin + Message.WParam := EffectiveColor; + Message.Result := 1; +end; + +procedure TTBXDockablePanel.TBMGetViewType(var Message: TMessage); +begin + Message.Result := GetViewType; +end; + +procedure TTBXDockablePanel.TBMThemeChange(var Message: TMessage); +var + M: TMessage; +begin + case Message.WParam of + TSC_BEFOREVIEWCHANGE: BeginUpdate; + TSC_AFTERVIEWCHANGE: + begin + EndUpdate; + UpdateEffectiveColor; + + if HandleAllocated and not (csDestroying in ComponentState) and + (Parent is TTBXFloatingWindowParent) then + UpdateNCArea(TTBXFloatingWindowParent(Parent), GetViewType) + else + UpdateNCArea(Self, GetViewType); + + Invalidate; + + M.Msg := CM_PARENTCOLORCHANGED; + M.WParam := 1; + M.LParam := EffectiveColor; + M.Result := 0; + Broadcast(M); + end; + end; +end; + +procedure TTBXDockablePanel.UpdateChildColors; +var + M: TMessage; +begin + M.Msg := CM_PARENTCOLORCHANGED; + M.WParam := 1; + M.LParam := EffectiveColor; + M.Result := 0; + Broadcast(M); +end; + +procedure TTBXDockablePanel.UpdateEffectiveColor; +begin + if Color = clNone then FEffectiveColor := CurrentTheme.GetViewColor(GetViewType) + else FEffectiveColor := Color; +end; + +procedure TTBXDockablePanel.WMEraseBkgnd(var Message: TWMEraseBkgnd); +var + BRUSH: HBRUSH; +begin + BRUSH := CreateSolidBrush(ColorToRGB(EffectiveColor)); + FillRect(Message.DC, Clientrect, BRUSH); + DeleteObject(BRUSH); + Message.Result := 1; +end; + +procedure TTBXDockablePanel.WMNCCalcSize(var Message: TWMNCCalcSize); +begin + Message.Result := 0; + if Docked then + with Message.CalcSize_Params^ do + begin + InflateRect(rgrc[0], -DockedBorderSize, -DockedBorderSize); + if ShowCaptionWhenDocked then + if IsVertCaption then Inc(rgrc[0].Left, GetSystemMetrics(SM_CYSMCAPTION)) + else Inc(rgrc[0].Top, GetSystemMetrics(SM_CYSMCAPTION)) + end; +end; + +procedure TTBXDockablePanel.WMNCHitTest(var Message: TWMNCHitTest); +const + CResizeMargin = 2; +var + P: TPoint; + R: TRect; + Sz: Integer; + IsVertical, UseDefaultHandler: Boolean; +begin + if Docked then + begin + UseDefaultHandler := False; + if csDesigning in ComponentState then with Message do + begin + P := SmallPointToPoint(Pos); + GetWindowRect(Handle, R); + if PtInRect(R, P) then + begin + Result := 0; + case CurrentDock.Position of + dpLeft: if P.X >= R.Right - CResizeMargin then Result := HTRIGHT; + dpTop: if P.Y >= R.Bottom - CResizeMargin then Result := HTBOTTOM; + dpRight: if P.X <= R.Left + CResizeMargin then Result := HTLEFT; + dpBottom: if P.Y <= R.Top + CResizeMargin then Result := HTTOP; + end; + if Result = 0 then + begin + if (P.X >= R.Right - CResizeMargin) and CanSplitResize(dpRight) then Result := HT_TBX_SPLITRESIZERIGHT + else if (P.Y >= R.Bottom - CResizeMargin) and CanSplitResize(dpBottom) then Result := HT_TBX_SPLITRESIZEBOTTOM + else if (P.X <= R.Left + CResizeMargin) and CanSplitResize(dpLeft) then Result := HT_TBX_SPLITRESIZELEFT + else if (P.Y <= R.Top + CResizeMargin) and CanSplitResize(dpTop) then Result := HT_TBX_SPLITRESIZETOP; + end; + UseDefaultHandler := Result <> 0; + end; + if UseDefaultHandler then DefaultHandler(Message) + else inherited; + end; + + with Message do + begin + P := SmallPointToPoint(Pos); + GetWindowRect(Handle, R); + if Resizable then + case CurrentDock.Position of + dpLeft: if P.X >= R.Right - CResizeMargin then Result := HTRIGHT; + dpTop: if P.Y >= R.Bottom - CResizeMargin then Result := HTBOTTOM; + dpRight: if P.X <= R.Left + CResizeMargin then Result := HTLEFT; + dpBottom: if P.Y <= R.Top + CResizeMargin then Result := HTTOP; + end; + if Result = 0 then + begin + if (P.X >= R.Right - CResizeMargin) and CanSplitResize(dpRight) then Result := HT_TBX_SPLITRESIZERIGHT + else if (P.Y >= R.Bottom - CResizeMargin) and CanSplitResize(dpBottom) then Result := HT_TBX_SPLITRESIZEBOTTOM + else if (P.X <= R.Left + CResizeMargin) and CanSplitResize(dpLeft) then Result := HT_TBX_SPLITRESIZELEFT + else if (P.Y <= R.Top + CResizeMargin) and CanSplitResize(dpTop) then Result := HT_TBX_SPLITRESIZETOP; + end; + if (Result <> HTCLIENT) and ((Result < HTLEFT) or (Result > HTBOTTOM)) and + ((Result < HT_TBX_SPLITRESIZELEFT) or (Result > HT_TBX_SPLITRESIZEBOTTOM)) then + begin + Result := HTNOWHERE; + InflateRect(R, -DockedBorderSize, -DockedBorderSize); + + if PtInRect(R, P) and ShowCaptionWhenDocked and not (csDesigning in ComponentState) then + begin + { caption area } + IsVertical := not IsVertCaption; + if CloseButtonWhenDocked then + begin + Sz := GetSystemMetrics(SM_CYSMCAPTION); + if IsVertical then Inc(Sz, 4) else Dec(Sz, 4); + end + else Sz := 0; + + if (IsVertical and (P.X >= R.Right - Sz) and (P.Y < R.Top + Sz)) or + (not IsVertical and (P.Y >= R.Bottom - Sz) and (P.X < R.Left + Sz)) then + Result := HT_TB2k_Close + else + Result := HT_TB2k_Border; + end; + end; + end; + end + else inherited; +end; + +procedure TTBXDockablePanel.WMNCLButtonDown(var Message: TWMNCLButtonDown); +var + OldCursor: HCURSOR; +begin + if Message.HitTest in [HTLEFT..HTBOTTOM] then BeginDockedSizing(Message.HitTest) + else if Message.HitTest in [HT_TBX_SPLITRESIZELEFT..HT_TBX_SPLITRESIZEBOTTOM] then BeginSplitResizing(Message.HitTest) + else + begin + if (Message.HitTest = HT_TB2k_Border) and IsMovable then + begin + OldCursor := SetCursor(LoadCursor(0, IDC_SIZEALL)); + try + inherited; + finally + SetCursor(OldCursor); + end; + end + else inherited; + end; +end; + +procedure TTBXDockablePanel.WMSetCursor(var Message: TWMSetCursor); +begin + if Docked and CurrentDock.AllowDrag and + (Message.CursorWnd = WindowHandle) and + (Smallint(Message.HitTest) = HT_TB2k_Border) and + ShowCaptionWhenDocked then + begin + SetCursor(LoadCursor(0, IDC_ARROW)); + Message.Result := 1; + Exit; + end + else if Docked and CurrentDock.AllowDrag and (Message.CursorWnd = WindowHandle) then + begin + if (Message.HitTest = HT_TBX_SPLITRESIZELEFT) or (Message.HitTest = HT_TBX_SPLITRESIZERIGHT) then + begin + SetCursor(LoadCursor(0, IDC_SIZEWE)); + Message.Result := 1; + Exit; + end + else if (Message.HitTest = HT_TBX_SPLITRESIZETOP) or (Message.HitTest = HT_TBX_SPLITRESIZEBOTTOM) then + begin + SetCursor(LoadCursor(0, IDC_SIZENS)); + Message.Result := 1; + Exit; + end; + end; + inherited; +end; + +procedure TTBXDockablePanel.WMWindowPosChanged(var Message: TWMWindowPosChanged); +begin + inherited; + if (Message.WindowPos^.flags and SWP_NOSIZE) = 0 then + begin + Realign; + Update; + end; + if (Message.WindowPos^.flags and SWP_SHOWWINDOW) <> 0 then + begin + UpdateEffectiveColor; + UpdateChildColors; + end; +end; + +procedure TTBXDockablePanel.WritePositionData(const Data: TTBWritePositionData); +begin + with Data do + begin + WriteIntProc(Name, rvDockedWidth, FDockedWidth, ExtraData); + WriteIntProc(Name, rvDockedHeight, FDockedHeight, ExtraData); + WriteIntProc(Name, rvFloatingWidth, FFloatingWidth, ExtraData); + WriteIntProc(Name, rvFloatingHeight, FFloatingHeight, ExtraData); + WriteIntProc(Name, rvSplitWidth, FSplitWidth, ExtraData); + WriteIntProc(Name, rvSplitHeight, FSplitHeight, ExtraData); + end; +end; + +//----------------------------------------------------------------------------// + +{ TTBXTextObject } + +procedure TTBXTextObject.AdjustFont(AFont: TFont); +begin +end; + +procedure TTBXTextObject.AdjustHeight; +var + NewHeight: Integer; +begin + if HandleAllocated and not FUpdating and ([csReading, csLoading] * ComponentState = []) and AutoSize then + begin + FUpdating := True; + try + NewHeight := 0; + DoAdjustHeight(StockCompatibleBitmap.Canvas, NewHeight); + SetBounds(Left, Top, Width, NewHeight); + finally + FUpdating := False; + end; + end; +end; + +function TTBXTextObject.CanAutoSize(var NewWidth, NewHeight: Integer): Boolean; +begin + if not FUpdating and ([csReading, csLoading] * ComponentState = []) and AutoSize then + begin + FUpdating := True; + try + NewHeight := 0; + DoAdjustHeight(StockCompatibleBitmap.Canvas, NewHeight); + Result := True; + finally + FUpdating := False; + end; + end + else Result := False; +end; + +procedure TTBXTextObject.CMEnabledChanged(var Message: TMessage); +begin + inherited; + Invalidate; +end; + +procedure TTBXTextObject.CMFontChanged(var Message: TMessage); +begin + inherited; + Invalidate; + AdjustHeight; +end; + +procedure TTBXTextObject.CMTextChanged(var Message: TMessage); +begin + inherited; + Invalidate; + AdjustHeight; +end; + +constructor TTBXTextObject.Create(AOwner: TComponent); +begin + inherited; + ControlStyle := ControlStyle + [csSetCaption] - [csDoubleClicks]; + FMargins := TTBXControlMargins.Create; + FMargins.OnChange := MarginsChangeHandler; + FShowAccelChar := True; + PaintOptions := [cpoDoubleBuffered]; + AutoSize := True; + Width := 100; +end; + +procedure TTBXTextObject.CreateParams(var Params: TCreateParams); +begin + inherited; + if not (csDesigning in ComponentState) then + with Params.WindowClass do style := style or CS_HREDRAW; +end; + +destructor TTBXTextObject.Destroy; +begin + FMargins.Free; + inherited; +end; + +procedure TTBXTextObject.DoAdjustHeight(ACanvas: TCanvas; var NewHeight: Integer); +const + WordWraps: array [TTextWrapping] of Word = (0, DT_END_ELLIPSIS, DT_PATH_ELLIPSIS, DT_WORDBREAK); +var + R: TRect; + EffectiveMargins: TRect; +begin + R := ClientRect; + EffectiveMargins := GetTextMargins; + with Margins do + begin + Inc(EffectiveMargins.Left, Left); Inc(EffectiveMargins.Right, Right); + Inc(EffectiveMargins.Top, Top); Inc(EffectiveMargins.Bottom, Bottom); + end; + ApplyMargins(R, EffectiveMargins); + NewHeight := DoDrawText(ACanvas, R, (DT_EXPANDTABS or DT_CALCRECT) or WordWraps[Wrapping]); + with EffectiveMargins do Inc(NewHeight, Top + Bottom); +end; + +function TTBXTextObject.DoDrawText(ACanvas: TCanvas; var Rect: TRect; Flags: Integer): Integer; +var + Text: string; +begin + Text := GetLabelText; + if (Flags and DT_CALCRECT <> 0) and ((Text = '') or + (Text[1] = '&') and (Text[2] = #0)) then Text := Text + ' '; + Flags := DrawTextBiDiModeFlags(Flags); + ACanvas.Font := Font; + AdjustFont(ACanvas.Font); + + if Flags and DT_CALCRECT = DT_CALCRECT then + begin + Flags := Flags and not DT_VCENTER; + Result := DrawText(ACanvas.Handle, PChar(Text), Length(Text), Rect, Flags); + end + else if not Enabled then + begin + OffsetRect(Rect, 1, 1); + ACanvas.Font.Color := clBtnHighlight; + DrawText(ACanvas.Handle, PChar(Text), Length(Text), Rect, Flags); + OffsetRect(Rect, -1, -1); + ACanvas.Font.Color := clBtnShadow; + Result := DrawText(ACanvas.Handle, PChar(Text), Length(Text), Rect, Flags); + end + else + begin + Result := DrawText(ACanvas.Handle, PChar(Text), Length(Text), Rect, Flags); + end; +end; + +procedure TTBXTextObject.DoMarginsChanged; +begin + Invalidate; + AdjustHeight; +end; + +function TTBXTextObject.GetControlsAlignment: TAlignment; +begin + Result := FAlignment; +end; + +function TTBXTextObject.GetFocusRect(const R: TRect): TRect; +begin + { R is the client rectangle without the margins } + Result := Rect(0, 0, 0, 0); +end; + +function TTBXTextObject.GetLabelText: string; +begin + Result := Caption; +end; + +function TTBXTextObject.GetTextAlignment: TAlignment; +begin + Result := Alignment; +end; + +function TTBXTextObject.GetTextMargins: TRect; +const + ZeroRect: TRect = (Left: 0; Top: 0; Right: 0; Bottom: 0); +begin + Result := ZeroRect; +end; + +procedure TTBXTextObject.Loaded; +begin + inherited; + AdjustHeight; +end; + +procedure TTBXTextObject.MarginsChangeHandler(Sender: TObject); +begin + DoMarginsChanged; +end; + +procedure TTBXTextObject.Paint; +const + Alignments: array [TAlignment] of Integer = (DT_LEFT, DT_RIGHT, DT_CENTER); + WordWraps: array [TTextWrapping] of Integer = (DT_SINGLELINE, + DT_SINGLELINE or DT_END_ELLIPSIS, + DT_SINGLELINE or DT_PATH_ELLIPSIS, DT_WORDBREAK); + ShowAccelChars: array [Boolean] of Integer = (DT_NOPREFIX, 0); +var + R, R2: TRect; + DrawStyle: Longint; + CaptionHeight: Integer; +begin + with Canvas do + begin + R := ClientRect; + ApplyMargins(R, Margins); + if Focused then DrawFocusRect2(Canvas, GetFocusRect(R)); + DrawStyle := DT_EXPANDTABS or WordWraps[Wrapping] or + Alignments[GetRealAlignment(Self)] or ShowAccelChars[ShowAccelChar]; + Brush.Style := bsClear; + ApplyMargins(R, GetTextMargins); + R2 := R; + CaptionHeight := DoDrawText(Canvas, R2, DrawStyle or DT_CALCRECT); + R.Top := (R.Top + R.Bottom - CaptionHeight) div 2; + R.Bottom := R.Top + CaptionHeight; + DoDrawText(Canvas, R, DrawStyle); + Brush.Style := bsSolid; + end; +end; + +procedure TTBXTextObject.SetAlignment(Value: TLeftRight); +begin + FAlignment := Value; + Invalidate; +end; + +procedure TTBXTextObject.SetMargins(Value: TTBXControlMargins); +begin + FMargins.Assign(Value); +end; + +procedure TTBXTextObject.SetShowAccelChar(Value: Boolean); +begin + if FShowAccelChar <> Value then + begin + FShowAccelChar := Value; + AdjustHeight; + Invalidate; + end; +end; + +procedure TTBXTextObject.SetWrapping(Value: TTextWrapping); +begin + FWrapping := Value; + Invalidate; + AdjustHeight; +end; + +//----------------------------------------------------------------------------// + +{ TTBXCustomLabel } + +procedure TTBXCustomLabel.CMDialogChar(var Message: TCMDialogChar); +begin + if (FFocusControl <> nil) and Enabled and ShowAccelChar and IsAccel(Message.CharCode, Caption) then + with FFocusControl do if CanFocus then + begin + SetFocus; + Message.Result := 1; + end; +end; + +constructor TTBXCustomLabel.Create(AOwner: TComponent); +begin + inherited; + Wrapping := twWrap; + FUnderlineColor := clBtnShadow; + TabStop := False; +end; + +function TTBXCustomLabel.GetTextMargins: TRect; +const + BottomMargin: array [Boolean] of Integer = (0, 1); +begin + with Result do + begin + Left := 0; + Top := 0; + Right := 0; + Result.Bottom := BottomMargin[Underline]; + end; +end; + +procedure TTBXCustomLabel.Notification(AComponent: TComponent; Operation: TOperation); +begin + inherited; + inherited Notification(AComponent, Operation); + if (Operation = opRemove) and (AComponent = FFocusControl) then FFocusControl := nil; +end; + +procedure TTBXCustomLabel.Paint; +var + Rect: TRect; +begin + inherited; + if Underline then with Canvas do + begin + Rect := ClientRect; + ApplyMargins(Rect, Margins); + ApplyMargins(Rect, GetTextMargins); + Pen.Color := UnderlineColor; + MoveTo(Rect.Left, Rect.Bottom); + LineTo(Rect.Right, Rect.Bottom); + end; +end; + +procedure TTBXCustomLabel.SetFocusControl(Value: TWinControl); +begin + if FFocusControl <> Value then + begin + if FFocusControl <> nil then FFocusControl.RemoveFreeNotification(Self); + FFocusControl := Value; + if FFocusControl <> nil then FFocusControl.FreeNotification(Self); + end; +end; + +procedure TTBXCustomLabel.SetUnderline(Value: Boolean); +begin + if Value <> FUnderline then + begin + FUnderline := Value; + Invalidate; + AdjustHeight; + end; +end; + +procedure TTBXCustomLabel.SetUnderlineColor(Value: TColor); +begin + FUnderlineColor := Value; + Invalidate; +end; + +//----------------------------------------------------------------------------// + +{ TTBXCustomLink } + +procedure TTBXCustomLink.AdjustFont(AFont: TFont); +begin + if MouseInControl then AFont.Style := AFont.Style + [fsUnderline]; +end; + +procedure TTBXCustomLink.CMDialogChar(var Message: TCMDialogChar); +begin + with Message do + if Enabled and ShowAccelChar and IsAccel(CharCode, GetLabelText) and CanFocus and Visible then + begin + Click; + Result := 1; + end + else inherited; +end; + +procedure TTBXCustomLink.CMDialogKey(var Message: TCMDialogKey); +begin + with Message do + if (CharCode = VK_RETURN) and Focused and + (KeyDataToShiftState(Message.KeyData) = []) then + begin + Click; + Result := 1; + end + else inherited; +end; + +constructor TTBXCustomLink.Create(AOwner: TComponent); +begin + inherited; + FImageChangeLink := TChangeLink.Create; + FImageChangeLink.OnChange := ImageListChange; + SmartFocus := True; + SpaceAsClick := True; + TabStop := True; + Cursor := crHandPoint; +end; + +destructor TTBXCustomLink.Destroy; +begin + FImageChangeLink.Free; + inherited; +end; + +procedure TTBXCustomLink.DoAdjustHeight(ACanvas: TCanvas; var NewHeight: Integer); +begin + inherited DoAdjustHeight(ACanvas, NewHeight); + if Images <> nil then + if NewHeight < Images.Height + 4 then NewHeight := Images.Height + 4; +end; + +procedure TTBXCustomLink.DoMouseEnter; +begin + inherited; + Invalidate; +end; + +procedure TTBXCustomLink.DoMouseLeave; +begin + inherited; + Invalidate; +end; + +function TTBXCustomLink.GetControlsAlignment: TAlignment; +begin + Result := GetTextAlignment; +end; + +function TTBXCustomLink.GetFocusRect(const R: TRect): TRect; +const + WordWraps: array [TTextWrapping] of Integer = (DT_SINGLELINE or DT_VCENTER, + DT_SINGLELINE or DT_VCENTER or DT_END_ELLIPSIS, + DT_SINGLELINE or DT_VCENTER or DT_PATH_ELLIPSIS, DT_WORDBREAK); +var + TR: TRect; + ShowImage: Boolean; +begin + Result := R; + ShowImage := Assigned(Images) and (ImageIndex >= 0) and (ImageIndex < Images.Count); + + { Text Rectangle } + TR := R; + ApplyMargins(TR, GetTextMargins); + DoDrawText(Canvas, TR, (DT_EXPANDTABS or DT_CALCRECT) or WordWraps[Wrapping] or DT_LEFT); + + if ShowImage then + begin + if GetRealAlignment(Self) = taLeftJustify then + begin + Result.Left := R.Left; + Result.Right := TR.Right; + end + else + begin + Result.Left := TR.Left; + Result.Right := R.Right; + end; + end + else + begin + Result.Right := TR.Right; + Result.Left := TR.Left; + end; + Dec(Result.Left, 2); + Inc(Result.Right, 2); +end; + +function TTBXCustomLink.GetTextAlignment: TAlignment; +begin + Result := taLeftJustify; +end; + +function TTBXCustomLink.GetTextMargins: TRect; +begin + Result := Rect(2, 1, 2, 1); + if Assigned(Images) then with Result do + begin + if GetRealAlignment(Self) = taLeftJustify then Inc(Left, Images.Width + 5) + else Inc(Right, Images.Width + 5); + end; +end; + +procedure TTBXCustomLink.ImageListChange(Sender: TObject); +begin + if Sender = Images then + begin + Invalidate; + AdjustHeight; + end; +end; + +procedure TTBXCustomLink.Notification(AComponent: TComponent; Operation: TOperation); +begin + inherited; + if (AComponent = Images) and (Operation = opRemove) then Images := nil; +end; + +procedure TTBXCustomLink.Paint; +var + Rect, R: TRect; +begin + inherited; + if Assigned(Images) and (ImageIndex >= 0) and (ImageIndex < Images.Count) then + with Canvas do + begin + Rect := ClientRect; + ApplyMargins(Rect, Margins); + + if GetRealAlignment(Self) = taLeftJustify then R.Left := Rect.Left + 2 + else R.Left := Rect.Right - 2 - Images.Width; + + R.Top := (Rect.Top + Rect.Bottom - Images.Height) div 2; + R.Right := R.Left + Images.Width; + R.Bottom := R.Top + Images.Height; + + if Enabled then Images.Draw(Canvas, R.Left, R.Top, ImageIndex) + else DrawTBXImage(Canvas, R, Images, ImageIndex, ISF_DISABLED); + end; +end; + +procedure TTBXCustomLink.SetImageIndex(Value: TImageIndex); +begin + if FImageIndex <> Value then + begin + FImageIndex := Value; + if Assigned(Images) then Invalidate; + end; +end; + +procedure TTBXCustomLink.SetImages(Value: TCustomImageList); +begin + if FImages <> nil then FImages.UnRegisterChanges(FImageChangeLink); + FImages := Value; + if FImages <> nil then + begin + FImages.RegisterChanges(FImageChangeLink); + FImages.FreeNotification(Self); + end; + Invalidate; + AdjustHeight; +end; + +procedure TTBXCustomLink.WMNCHitTest(var Message: TWMNCHitTest); +var + P: TPoint; + R: TRect; +begin + inherited; + if not (csDesigning in ComponentState) then + begin + P := ScreenToClient(SmallPointToPoint(Message.Pos)); + R := ClientRect; + ApplyMargins(R, Margins); + R := GetFocusRect(R); + if not PtInRect(R, P) then Message.Result := HTTRANSPARENT; + end; +end; + +//----------------------------------------------------------------------------// + +{ TTBXCustomButton } + +function TTBXCustomButton.ArrowVisible: Boolean; +begin + Result := DropDownMenu <> nil; +end; + +procedure TTBXCustomButton.Click; +var + Form: TCustomForm; + Pt: TPoint; + R: TRect; + SaveAlignment: TPopupAlignment; + + procedure RemoveClicks; + var + RepostList: TList; + Repost: Boolean; + I: Integer; + Msg: TMsg; + P: TPoint; + begin + RepostList := TList.Create; + try + while PeekMessage(Msg, 0, WM_LBUTTONDOWN, WM_MBUTTONDBLCLK, PM_REMOVE) do + with Msg do + begin + Repost := True; + case Message of + WM_QUIT: begin + { Throw back any WM_QUIT messages } + PostQuitMessage(wParam); + Break; + end; + WM_LBUTTONDOWN, WM_LBUTTONDBLCLK, + WM_RBUTTONDOWN, WM_RBUTTONDBLCLK, + WM_MBUTTONDOWN, WM_MBUTTONDBLCLK: begin + P := SmallPointToPoint(TSmallPoint(lParam)); + Windows.ClientToScreen(hwnd, P); + if FindDragTarget(P, True) = Self then Repost := False; + end; + end; + if Repost then + begin + RepostList.Add(AllocMem(SizeOf(TMsg))); + PMsg(RepostList.Last)^ := Msg; + end; + end; + finally + for I := 0 to RepostList.Count-1 do + begin + with PMsg(RepostList[I])^ do PostMessage(hwnd, message, wParam, lParam); + FreeMem(RepostList[I]); + end; + RepostList.Free; + end; + end; + +begin + if FRepeating and not FMenuVisible then inherited + else + try + FInClick := True; + if (GroupIndex <> 0) and not FMenuVisible then SetChecked(not Checked); + MouseLeft; + if (DropDownMenu = nil) or (DropDownCombo and not FMenuVisible) then + begin + if ModalResult <> 0 then + begin + Form := GetParentForm(Self); + if Form <> nil then Form.ModalResult := ModalResult; + end; + inherited; + end + else + begin + MouseCapture := False; + SaveAlignment := paLeft; // to avoid compiler warnings + if DoDropDown then + try + Pt := Point(0, Height); + Pt := ClientToScreen(Pt); + SaveAlignment := DropDownMenu.Alignment; + DropDownMenu.PopupComponent := Self; + + if DropDownMenu is TTBXPopupMenu then + begin + R := ClientRect; + ApplyMargins(R, Margins); + R.TopLeft := ClientToScreen(R.TopLeft); + R.BottomRight := ClientToScreen(R.BottomRight); + TTBXPopupMenu(DropDownMenu).PopupEx(R); + end + else DropDownMenu.Popup(Pt.X, Pt.Y); + finally + DropDownMenu.Alignment := SaveAlignment; + if Pushed then FPushed := False; + Invalidate; + RemoveClicks; + end + else inherited; + end; + finally + FInClick := False; + end; +end; + +procedure TTBXCustomButton.CMDialogChar(var Message: TCMDialogChar); +begin + with Message do + if Enabled and ShowAccelChar and IsAccel(CharCode, GetLabelText) and CanFocus and Visible then + begin + Click; + Result := 1; + end + else inherited; +end; + +procedure TTBXCustomButton.CMDialogKey(var Message: TCMDialogKey); +begin + with Message do + if (CharCode = VK_RETURN) and Focused and + (KeyDataToShiftState(Message.KeyData) = []) then + begin + Click; + Result := 1; + end + else inherited; +end; + +constructor TTBXCustomButton.Create(AOwner: TComponent); +begin + inherited; + FAlignment := taCenter; + FBorderSize := 4; + FGlyphSpacing := 4; + FImageChangeLink := TChangeLink.Create; + FImageChangeLink.OnChange := ImageListChange; + FRepeatDelay := 400; + FRepeatInterval := 100; + SmartFocus := True; + SpaceAsClick := True; + TabStop := True; +end; + +destructor TTBXCustomButton.Destroy; +begin + FImageChangeLink.Free; + inherited; +end; + +procedure TTBXCustomButton.DoAdjustHeight(ACanvas: TCanvas; var NewHeight: Integer); +var + Sz: Integer; +begin + if Length(GetLabelText) = 0 then + begin + if Images <> nil then NewHeight := Images.Height + BorderSize * 2 + else if BorderSize * 2 >= 16 then NewHeight := BorderSize * 2 + else NewHeight := 16; + end + else + begin + inherited DoAdjustHeight(ACanvas, NewHeight); + if Images <> nil then + if Layout in [blGlyphLeft, blGlyphRight] then + begin + Sz := Images.Height + BorderSize * 2; + if NewHeight < Sz then NewHeight := Sz; + end; + end; +end; + +function TTBXCustomButton.DoDrawText(ACanvas: TCanvas; var Rect: TRect; Flags: Integer): Integer; +var + ItemInfo: TTBXItemInfo; + Text: string; +begin + Text := GetLabelText; + if (Flags and DT_CALCRECT <> 0) and ((Text = '') or + (Text[1] = '&') and (Text[2] = #0)) then Text := Text + ' '; + Flags := DrawTextBiDiModeFlags(Flags); + ACanvas.Font := Font; + AdjustFont(ACanvas.Font); + + if Flags and DT_CALCRECT = DT_CALCRECT then + begin + Flags := Flags and not DT_VCENTER; + Result := DrawText(ACanvas.Handle, PChar(Text), Length(Text), Rect, Flags); + end + else + begin + GetItemInfo(ItemInfo); + ACanvas.Font.Color := clNone; + CurrentTheme.PaintCaption(Canvas, Rect, ItemInfo, Text, Flags, False); + Flags := Flags or DT_CALCRECT; + Result := DrawText(ACanvas.Handle, PChar(Text), Length(Text), Rect, Flags); + end; +end; + +function TTBXCustomButton.DoDropDown: Boolean; +begin + Result := FDropDownMenu <> nil; + if Result and Assigned(FOnDropDown) then FOnDropDown(Self, Result); +end; + +procedure TTBXCustomButton.DoMouseEnter; +begin + inherited; + Invalidate; +end; + +procedure TTBXCustomButton.DoMouseLeave; +begin + inherited; + Invalidate; +end; + +function TTBXCustomButton.GetControlsAlignment: TAlignment; +begin + Result := GetTextAlignment; +end; + +function TTBXCustomButton.GetFocusRect(const R: TRect): TRect; +begin + Result := R; + InflateRect(Result, -2, -2); +end; + +procedure TTBXCustomButton.GetItemInfo(out ItemInfo: TTBXItemInfo); +const + ViewTypes: array [TButtonStyle] of Integer = + (VT_TOOLBAR or TVT_EMBEDDED, VT_TOOLBAR); +begin + FillChar(ItemInfo, SizeOf(ItemInfo), 0); + ItemInfo.ViewType := ViewTypes[ButtonStyle]; + ItemInfo.Enabled := Enabled; + ItemInfo.ItemOptions := IO_TOOLBARSTYLE or IO_APPACTIVE; + ItemInfo.Pushed := Pushed and (MouseInControl or FMenuVisible); + if FMenuVisible and DropDownCombo then ItemInfo.Pushed := False; + if FMenuVisible then ItemInfo.IsPopupParent := True; + ItemInfo.Selected := Checked; + ItemInfo.IsVertical := False; + if ArrowVisible and DropDownCombo then ItemInfo.ComboPart := cpCombo; + if MouseInControl or FMenuVisible then ItemInfo.HoverKind := hkMouseHover; +end; + +function TTBXCustomButton.GetTextAlignment: TAlignment; +begin + Result := FAlignment; +end; + +function TTBXCustomButton.GetTextMargins: TRect; +var + L, Sz: Integer; + IsSpecialDropDown: Boolean; +begin + Result := Rect(BorderSize, BorderSize, BorderSize, BorderSize); + L := Length(GetLabelText); + if (Images <> nil) and (L > 0) then Sz := GlyphSpacing + else Sz := 0; + if Assigned(Images) then with Result do + case Layout of + blGlyphLeft: Inc(Left, Images.Width + Sz); + blGlyphTop: Inc(Top, Images.Height + Sz); + blGlyphRight: Inc(Right, Images.Width + Sz); + blGlyphBottom: Inc(Bottom, Images.Height + Sz); + end; + if ArrowVisible then + begin + if DropDownCombo then Inc(Result.Right, CurrentTheme.SplitBtnArrowWidth) + else + begin + IsSpecialDropDown := (L > 0) and (Images <> nil) and (Layout in [blGlyphTop, blGlyphBottom]); + if not IsSpecialDropDown then Inc(Result.Right, CurrentTheme.DropDownArrowWidth); + end; + end; +end; + +procedure TTBXCustomButton.ImageListChange(Sender: TObject); +begin + if Sender = Images then + begin + Invalidate; + AdjustHeight; + end; +end; + +procedure TTBXCustomButton.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); +var + R: TRect; +begin + inherited; + if Enabled and (Button = mbLeft) then + begin + R := ClientRect; + ApplyMargins(R, Margins); + FMenuVisible := not FInClick and Assigned(DropDownMenu) and + (not DropDownCombo or (X >= R.Right - CurrentTheme.SplitBtnArrowWidth)); + try + if FMenuVisible then + begin + ControlState := ControlState - [csClicked]; + if not FInClick then + begin + Click; + end; + end + else if Repeating then + begin + Click; + ControlState := ControlState - [csClicked]; + if not Assigned(FRepeatTimer) then FRepeatTimer := TTimer.Create(Self); + FRepeatTimer.Interval := RepeatDelay; + FRepeatTimer.OnTimer := RepeatTimerHandler; + FRepeatTimer.Enabled := True; + end; + finally + FMenuVisible := False; + end; + end; +end; + +procedure TTBXCustomButton.MouseMove(Shift: TShiftState; X, Y: Integer); +begin + inherited; + if Assigned(FRepeatTimer) and PtInButtonPart(Point(X, Y)) then FRepeatTimer.Enabled := True; +end; + +procedure TTBXCustomButton.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); +begin + inherited; + if Button = mbLeft then + begin + FRepeatTimer.Free; + FRepeatTimer := nil; + end; +end; + +procedure TTBXCustomButton.Notification(AComponent: TComponent; Operation: TOperation); +begin + inherited; + if Operation = opRemove then + begin + if AComponent = Images then Images := nil + else if AComponent = DropdownMenu then DropdownMenu := nil; + end; +end; + +procedure TTBXCustomButton.Paint; +const + Alignments: array [TAlignment] of Integer = (DT_LEFT, DT_RIGHT, DT_CENTER); + WordWraps: array [TTextWrapping] of Integer = (DT_SINGLELINE, + DT_SINGLELINE or DT_END_ELLIPSIS, + DT_SINGLELINE or DT_PATH_ELLIPSIS, DT_WORDBREAK); + ShowAccelChars: array [Boolean] of Integer = (DT_NOPREFIX, 0); +var + CR, IR, TR: TRect; + W, X: Integer; + Text: string; + ItemInfo: TTBXItemInfo; + RealAlignment: TAlignment; + CaptionHeight: Integer; + DrawStyle: Cardinal; + ShowArrow: Boolean; +begin + CR := ClientRect; + ApplyMargins(CR, Margins); + + ShowArrow := ArrowVisible; + GetItemInfo(ItemInfo); + if ShowArrow and DropDownCombo then + begin + TR := CR; + TR.Left := TR.Right - CurrentTheme.SplitBtnArrowWidth; + CR.Right := TR.Left; + + ItemInfo.ComboPart := cpSplitRight; + ItemInfo.Pushed := FMenuVisible; + CurrentTheme.PaintButton(Canvas, TR, ItemInfo); + + ItemInfo.ComboPart := cpSplitLeft; + ItemInfo.Pushed := Pushed and not FMenuVisible; + CurrentTheme.PaintButton(Canvas, CR, ItemInfo); + end + else CurrentTheme.PaintButton(Canvas, CR, ItemInfo); + if Focused then DrawFocusRect2(Canvas, GetFocusRect(CR)); + InflateRect(CR, -BorderSize, -BorderSize); + + if ShowArrow and not DropDownCombo then + begin + TR := CR; + TR.Left := TR.Right - CurrentTheme.DropdownArrowWidth; + CurrentTheme.PaintDropDownArrow(Canvas, TR, ItemInfo); + CR.Right := TR.Left - CurrentTheme.DropdownArrowMargin; + end; + + Text := GetLabelText; + DrawStyle := 0; + + if (Length(Text) > 0) or (Images <> nil) then + begin + RealAlignment := GetRealAlignment(Self); + + if Length(Text) = 0 then + begin + IR.Top := (CR.Top + CR.Bottom - Images.Height) div 2; + IR.Bottom := IR.Top + Images.Height; + + case RealAlignment of + taLeftJustify: IR.Left := CR.Left; + taRightJustify: IR.Left := CR.Right - Images.Width; + else + IR.Left := (CR.Left + CR.Right - Images.Width) div 2; + end; + IR.Right := IR.Left + Images.Width; + end + else + begin + TR := CR; + DrawStyle := DT_EXPANDTABS or WordWraps[Wrapping] or + Alignments[RealAlignment] or ShowAccelChars[ShowAccelChar]; + if (Images = nil) or (Layout in [blGlyphTop, blGlyphBottom]) then + begin + CaptionHeight := DoDrawText(Canvas, TR, DrawStyle or DT_CALCRECT); + TR := CR; + if Images = nil then + begin + TR.Top := (TR.Top + TR.Bottom - CaptionHeight) div 2; + end + else + begin + TR.Top := (CR.Top + CR.Bottom - Images.Height - GlyphSpacing - CaptionHeight) div 2; + IR.Top := TR.Top; + if Layout = blGlyphTop then Inc(TR.Top, Images.Height + GlyphSpacing) + else Inc(IR.Top, CaptionHeight + GlyphSpacing); + TR.Bottom := TR.Top + CaptionHeight; + IR.Bottom := IR.Top + Images.Height; + case RealAlignment of + taLeftJustify: IR.Left := CR.Left; + taRightJustify: IR.Left := CR.Right - Images.Width; + else + IR.Left := (CR.Left + CR.Right - Images.Width) div 2; + end; + IR.Right := IR.Left + Images.Width; + end; + end + else + begin + IR.Left := CR.Left; + if Layout = blGlyphLeft then Inc(TR.Left, Images.Width + GlyphSpacing) + else Dec(TR.Right, Images.Width + GlyphSpacing); + IR.Right := IR.Left + Images.Width; + IR.Top := (CR.Top + CR.Bottom - Images.Height) div 2; + IR.Bottom := IR.Top + Images.Height; + CaptionHeight := DoDrawText(Canvas, TR, DrawStyle or DT_CALCRECT); + TR.Top := (CR.Top + CR.Bottom - CaptionHeight) div 2; + TR.Bottom := TR.Top + CaptionHeight; + W := Images.Width + GlyphSpacing + TR.Right - TR.Left; + case RealAlignment of + taLeftJustify: X := CR.Left; + taRightJustify: X := CR.Right - W; + else + X := (CR.Left + CR.Right - W) div 2; + end; + case Layout of + blGlyphLeft: + begin + if X < CR.Left then X := CR.Left; + IR.Left := X; + IR.Right := X + Images.Width; + OffsetRect(TR, IR.Right + GlyphSpacing - TR.Left, 0); + if TR.Right > CR.Right then TR.Right := CR.Right; + DrawStyle := DrawStyle and not DT_RIGHT and not DT_CENTER or DT_LEFT; + end; + blGlyphRight: + begin + OffsetRect(TR, X - TR.Left, 0); + IR.Left := TR.Right + GlyphSpacing; + IR.Right := IR.Left + Images.Width; + DrawStyle := DrawStyle and not DT_CENTER and not DT_LEFT or DT_RIGHT; + end; + end; + end; + end; + + if Images <> nil then + CurrentTheme.PaintImage(Canvas, IR, ItemInfo, Images, ImageIndex); + + if Length(Text) > 0 then + begin + Brush.Style := bsClear; + DoDrawText(Canvas, TR, DrawStyle); + Brush.Style := bsSolid; + end; + end; +end; + +function TTBXCustomButton.PtInButtonPart(const Pt: TPoint): Boolean; +var + R: TRect; +begin + R := ClientRect; + ApplyMargins(R, Margins); + Result := PtInRect(R, Pt); +end; + +procedure TTBXCustomButton.RepeatTimerHandler(Sender: TObject); +var + P: TPoint; +begin + FRepeatTimer.Interval := RepeatInterval; + GetCursorPos(P); + P := ScreenToClient(P); + if not MouseCapture then + begin + FRepeatTimer.Free; + FRepeatTimer := nil; + end + else if Repeating and Pushed and PtInButtonPart(P) then Click + else FRepeatTimer.Enabled := False; +end; + +procedure TTBXCustomButton.SetAlignment(Value: TAlignment); +begin + FAlignment := Value; + Invalidate; +end; + +procedure TTBXCustomButton.SetAllowAllUnchecked(Value: Boolean); +begin + if FAllowAllUnchecked <> Value then + begin + FAllowAllUnchecked := Value; + UpdateCheckedState; + end; +end; + +procedure TTBXCustomButton.SetBorderSize(Value: Integer); +begin + FBorderSize := Value; + Invalidate; + AdjustHeight; +end; + +procedure TTBXCustomButton.SetButtonStyle(Value: TButtonStyle); +begin + FButtonStyle := Value; + Invalidate; +end; + +procedure TTBXCustomButton.SetChecked(Value: Boolean); +begin + if FGroupIndex = 0 then Value := False; + if FChecked <> Value then + begin + if FChecked and not AllowAllUnchecked then Exit; + FChecked := Value; + Invalidate; + if Value then UpdateCheckedState; + end; +end; + +procedure TTBXCustomButton.SetDropdownCombo(Value: Boolean); +begin + FDropdownCombo := Value; + Invalidate; +end; + +procedure TTBXCustomButton.SetDropdownMenu(Value: TPopupMenu); +begin + if FDropdownMenu <> Value then + begin + if FDropDownMenu <> nil then RemoveFreeNotification(FDropDownMenu); + FDropDownMenu := Value; + if FDropDownMenu <> nil then FreeNotification(FDropDownMenu); + Invalidate; + end; +end; + +procedure TTBXCustomButton.SetGlyphSpacing(Value: Integer); +begin + FGlyphSpacing := Value; + Invalidate; + AdjustHeight; +end; + +procedure TTBXCustomButton.SetGroupIndex(Value: Integer); +begin + if FGroupIndex <> Value then + begin + FGroupIndex := Value; + UpdateCheckedState; + end; +end; + +procedure TTBXCustomButton.SetImageIndex(Value: TImageIndex); +begin + if FImageIndex <> Value then + begin + FImageIndex := Value; + if Assigned(Images) then Invalidate; + end; +end; + +procedure TTBXCustomButton.SetImages(Value: TCustomImageList); +begin + if FImages <> nil then FImages.UnRegisterChanges(FImageChangeLink); + FImages := Value; + if FImages <> nil then + begin + FImages.RegisterChanges(FImageChangeLink); + FImages.FreeNotification(Self); + end; + Invalidate; + AdjustHeight; +end; + +procedure TTBXCustomButton.SetLayout(Value: TButtonLayout); +begin + FLayout := Value; + Invalidate; + AdjustHeight; +end; + +procedure TTBXCustomButton.UpdateCheckedState; +var + I: Integer; + C: TControl; +begin + if (FGroupIndex <> 0) and (Parent <> nil) then with Parent do + for I := 0 to ControlCount - 1 do + begin + C := Controls[I]; + if (C <> Self) and (C is TTBXCustomButton) then + with TTBXCustomButton(C) do + if FGroupIndex = Self.FGroupIndex then + begin + if Self.Checked and FChecked then + begin + FChecked := False; + Invalidate; + end; + FAllowAllUnchecked := Self.AllowAllUnchecked; + end; + end; +end; + +procedure TTBXCustomButton.WMCancelMode(var Message: TWMCancelMode); +begin + FRepeatTimer.Free; + FRepeatTimer := nil; + MouseLeft; +end; + +procedure TTBXCustomButton.WMLButtonDblClk(var Message: TWMLButtonDblClk); +begin + Perform(WM_LBUTTONDOWN, Message.Keys, Longint(Message.Pos)); +end; + +//----------------------------------------------------------------------------// + +procedure TTBXCustomButton.WMNCHitTest(var Message: TWMNCHitTest); +var + P: TPoint; + R: TRect; +begin + inherited; + if not (csDesigning in ComponentState) then + begin + P := ScreenToClient(SmallPointToPoint(Message.Pos)); + R := ClientRect; + ApplyMargins(R, Margins); + if not PtInRect(R, P) then Message.Result := HTTRANSPARENT; + end; +end; + +{ TTBXAlignmentPanel } + +procedure TTBXAlignmentPanel.AdjustClientRect(var Rect: TRect); +begin + inherited AdjustClientRect(Rect); + with Margins do + begin + Inc(Rect.Left, Left); + Inc(Rect.Top, Top); + Dec(Rect.Right, Right); + Dec(Rect.Bottom, Bottom); + end; +end; + +constructor TTBXAlignmentPanel.Create(AOwner: TComponent); +begin + inherited; + FMargins := TTBXControlMargins.Create; + FMargins.OnChange := MarginsChangeHandler; +end; + +destructor TTBXAlignmentPanel.Destroy; +begin + FMargins.Free; + inherited; +end; + +function TTBXAlignmentPanel.GetMinHeight: Integer; +var + I: Integer; + Control: TControl; +begin + Result := 0; + for I := 0 to ControlCount - 1 do + begin + Control := Controls[I]; + if Control.Visible then + if Control.Align in [alTop, alBottom] then Inc(Result, Control.Height) + else if Control.Align = alClient then Inc(Result, GetMinControlHeight(Control)); + end; + Inc(Result, Margins.Top + Margins.Bottom); +end; + +function TTBXAlignmentPanel.GetMinWidth: Integer; +var + I: Integer; + Control: TControl; +begin + Result := 0; + for I := 0 to ControlCount - 1 do + begin + Control := Controls[I]; + if Control.Visible then + if Control.Align in [alLeft, alRight] then Inc(Result, Control.Width) + else if Control.Align = alClient then Inc(Result, GetMinControlWidth(Control)); + end; + Inc(Result, Margins.Left + Margins.Right); +end; + +procedure TTBXAlignmentPanel.MarginsChangeHandler(Sender: TObject); +begin + Realign; + Invalidate; +end; + +procedure TTBXAlignmentPanel.Paint; +var + R: TRect; + DC: HDC; +begin + if csDesigning in ComponentState then + begin + DC := Canvas.Handle; + R := ClientRect; + SaveDC(DC); + InflateRect(R, -1, -1); + with R do ExcludeClipRect(DC, Left, Top, Right, Bottom); + InflateRect(R, 1, 1); + DitherRect(DC, R, clBtnFace, clBtnShadow); + RestoreDC(DC, -1); + end; +end; + +procedure TTBXAlignmentPanel.SetMargins(Value: TTBXControlMargins); +begin + FMargins.Assign(Value); +end; + +//----------------------------------------------------------------------------// + +{ TTBXCustomPageScroller } + +procedure TTBXCustomPageScroller.AdjustClientRect(var Rect: TRect); +begin + if Orientation = tpsoVertical then + begin + if tpsbPrev in FVisibleButtons then Dec(Rect.Top, ButtonSize); + if tpsbNext in FVisibleButtons then Inc(Rect.Bottom, ButtonSize); + OffsetRect(Rect, 0, -Position); + if Range > Rect.Bottom - Rect.Top then Rect.Bottom := Rect.Top + Range; + end + else + begin + if tpsbPrev in FVisibleButtons then Dec(Rect.Left, ButtonSize); + if tpsbNext in FVisibleButtons then Inc(Rect.Right, ButtonSize); + OffsetRect(Rect, -Position, 0); + if Range > Rect.Right - Rect.Left then Rect.Right := Rect.Left + Range; + end; +end; + +procedure TTBXCustomPageScroller.AlignControls(AControl: TControl; var ARect: TRect); +begin + CalcAutoRange; + UpdateButtons; + ARect := ClientRect; + inherited AlignControls(AControl, ARect); +end; + +function TTBXCustomPageScroller.AutoScrollEnabled: Boolean; +begin + Result := not AutoSize and not (DockSite and UseDockManager); +end; + +procedure TTBXCustomPageScroller.BeginScrolling(HitTest: Integer); +var + Msg: TMsg; +begin + if HitTest = HTSCROLLPREV then FScrollDirection := -1 else FScrollDirection := 1; + try + SetCapture(Handle); + FScrollCounter := FScrollDirection * 8; + FScrollPending := True; + FScrollTimer.Enabled := True; + DrawNCArea(False, 0, 0); + HandleScrollTimer; + FScrollPending := True; + FScrollTimer.Interval := ScrollDelay; + + while GetCapture = Handle do + begin + case Integer(GetMessage(Msg, 0, 0, 0)) of + -1: Break; + 0: begin + PostQuitMessage(Msg.WParam); + Break; + end; + end; + case Msg.Message of + WM_KEYDOWN, WM_KEYUP: if Msg.WParam = VK_ESCAPE then Break; + WM_LBUTTONDOWN, WM_LBUTTONDBLCLK: begin + Break; + end; + WM_LBUTTONUP: + begin + Break; + end; + WM_RBUTTONDOWN..WM_MBUTTONDBLCLK:; + WM_TIMER: + begin + HandleScrollTimer; + end; + else + TranslateMessage(Msg); + DispatchMessage(Msg); + end; + end; + finally + StopScrolling; + if GetCapture = Handle then ReleaseCapture; + end; +end; + +procedure TTBXCustomPageScroller.CalcAutoRange; +var + I: Integer; + Bias: Integer; + NewRange, AlignMargin: Integer; + CW, CH: Integer; + Control: TControl; +begin + if (FAutoRangeCount <= 0) and AutoRange then + begin + if AutoScrollEnabled then + begin + NewRange := 0; + AlignMargin := 0; + if Position > 0 then Bias := ButtonSize + else Bias := 0; + CW := ClientWidth; + CH := ClientHeight; + DisableAlign; + for I := 0 to ControlCount - 1 do + begin + Control := Controls[I]; + if Control.Visible or (csDesigning in Control.ComponentState) and + not (csNoDesignVisible in Control.ControlStyle) then + begin + if Orientation = tpsoVertical then + begin + if Control.Align in [alTop, alBottom, alClient] then + Control.Width := CW; + case Control.Align of + alTop, alNone: + if (Control.Align = alTop) or (Control.Anchors * [akTop, akBottom] = [akTop]) then + NewRange := Max(NewRange, Position + Control.Top + Control.Height + Bias); + alBottom: Inc(AlignMargin, Control.Height); + alClient: Inc(AlignMargin, GetMinControlHeight(Control)); + end + end + else + begin + if Control.Align in [alLeft, alRight, alClient] then + Control.Height := CH; + case Control.Align of + alLeft, alNone: + if (Control.Align = alLeft) or (Control.Anchors * [akLeft, akRight] = [akLeft]) then + NewRange := Max(NewRange, Position + Control.Left + Control.Width + Bias); + alRight: Inc(AlignMargin, Control.Width); + alClient: Inc(AlignMargin, GetMinControlWidth(Control)); + end; + end; + end; + end; + EnableAlign; + DoSetRange(NewRange + AlignMargin + Margin); + end + else DoSetRange(0); + end; +end; + +function TTBXCustomPageScroller.CalcClientArea: TRect; +begin + Result := ClientRect; + if Orientation = tpsoVertical then + begin + if tpsbPrev in FVisibleButtons then Dec(Result.Top, ButtonSize); + if tpsbNext in FVisibleButtons then Inc(Result.Bottom, ButtonSize); + end + else + begin + if tpsbPrev in FVisibleButtons then Dec(Result.Left, ButtonSize); + if tpsbNext in FVisibleButtons then Inc(Result.Right, ButtonSize); + end; +end; + +function TTBXCustomPageScroller.CanAutoSize(var NewWidth, NewHeight: Integer): Boolean; +begin + Result := NewHeight > FButtonSize * 3; +end; + +procedure TTBXCustomPageScroller.CMParentColorChanged(var Message: TMessage); +begin + if (Message.WParam = 0) then + begin + Message.WParam := 1; + Message.LParam := GetEffectiveColor(Parent); + end; + inherited; +end; + +procedure TTBXCustomPageScroller.ConstrainedResize(var MinWidth, MinHeight, MaxWidth, MaxHeight: Integer); +begin + // do not call inherited here +end; + +constructor TTBXCustomPageScroller.Create(AOwner: TComponent); +begin + inherited; + ControlStyle := ControlStyle + [csAcceptsControls, csClickEvents, csDoubleClicks]; + FAutoScroll := True; + FButtonSize := 10; + FScrollTimer := TTimer.Create(Self); + FScrollTimer.Enabled := False; + FScrollTimer.Interval := 60; + FScrollTimer.OnTimer := ScrollTimerTimer; + Width := 64; + Height := 64; +end; + +procedure TTBXCustomPageScroller.CreateParams(var Params: TCreateParams); +begin + inherited CreateParams(Params); + with Params.WindowClass do style := style and not (CS_HREDRAW or CS_VREDRAW); +end; + +procedure TTBXCustomPageScroller.DisableAutoRange; +begin + Inc(FAutoRangeCount); +end; + +procedure TTBXCustomPageScroller.DoSetRange(Value: Integer); +begin + FRange := Value; + if FRange < 0 then FRange := 0; + UpdateButtons; +end; + +procedure TTBXCustomPageScroller.DrawNCArea(const DrawToDC: Boolean; + const ADC: HDC; const Clip: HRGN); +const + CBtns: array [TTBXPageScrollerOrientation, Boolean] of Integer = + ((PSBT_UP, PSBT_DOWN), (PSBT_LEFT, PSBT_RIGHT)); +var + DC: HDC; + R, CR, BR: TRect; + ACanvas: TCanvas; + PrevBtnSize, NextBtnSize: Integer; +begin + if FVisibleButtons = [] then Exit; + if not DrawToDC then DC := GetWindowDC(Handle) + else DC := ADC; + try + GetWindowRect(Handle, R); + OffsetRect(R, -R.Left, -R.Top); + if not DrawToDC then + begin + SelectNCUpdateRgn(Handle, DC, Clip); + CR := R; + PrevBtnSize := 0; + NextBtnSize := 0; + if tpsbPrev in FVisibleButtons then PrevBtnSize := ButtonSize; + if tpsbNext in FVisibleButtons then NextBtnSize := ButtonSize; + if Orientation = tpsoVertical then + begin + Inc(CR.Top, PrevBtnSize); + Dec(CR.Bottom, NextBtnSize); + end + else + begin + Inc(CR.Left, PrevBtnSize); + Dec(CR.Right, NextBtnSize); + end; + with CR do ExcludeClipRect(DC, Left, Top, Right, Bottom); + end; + + ACanvas := TCanvas.Create; + try + ACanvas.Handle := DC; + ACanvas.Brush.Color := Color; + ACanvas.FillRect(R); + + if tpsbPrev in FVisibleButtons then + begin + BR := R; + if Orientation = tpsoVertical then BR.Bottom := BR.Top + ButtonSize + else BR.Right := BR.Left + ButtonSize; + CurrentTheme.PaintPageScrollButton(ACanvas, BR, CBtns[Orientation, False], + FScrollDirection < 0); + end; + if tpsbNext in FVisibleButtons then + begin + BR := R; + if Orientation = tpsoVertical then BR.Top := BR.Bottom - ButtonSize + else BR.Left := BR.Right - ButtonSize; + CurrentTheme.PaintPageScrollButton(ACanvas, BR, CBtns[Orientation, True], + FScrollDirection > 0); + end; + finally + ACanvas.Handle := 0; + ACanvas.Free; + end; + finally + if not DrawToDC then ReleaseDC(Handle, DC); + end; +end; + +procedure TTBXCustomPageScroller.EnableAutoRange; +begin + if FAutoRangeCount > 0 then + begin + Dec(FAutoRangeCount); + if FAutoRangeCount = 0 then CalcAutoRange; + end; +end; + +procedure TTBXCustomPageScroller.HandleScrollTimer; +var + Pt: TPoint; + R: TRect; + OldPosition: Integer; + OldDirection: Integer; +begin + GetCursorPos(Pt); + GetWindowRect(Handle, R); + if not PtInRect(R, Pt) then + begin + StopScrolling; + end + else if FScrollDirection = 0 then + begin + FScrollTimer.Enabled := False; + FScrollCounter := 0; + end + else + begin + OldPosition := Position; + OldDirection := FScrollDirection; + if ((FScrollDirection > 0) and (FScrollCounter < 0)) or + ((FScrollDirection < 0) and (FScrollCounter > 0)) then FScrollCounter := 0; + if FScrollDirection > 0 then Inc(FScrollCounter) + else Dec(FScrollCounter); + Position := Position + FScrollCounter; + if Position = OldPosition then + begin + ReleaseCapture; + FScrollTimer.Enabled := False; + DrawNCArea(False, 0, 0); + end + else + begin + if FScrollPending or (FScrollDirection * OldDirection <= 0) or + (FScrollDirection * OldDirection <= 0) then + DrawNCArea(False, 0, 0); + end; + end; + if FScrollPending then FScrollTimer.Interval := ScrollInterval; + FScrollPending := False; +end; + +function TTBXCustomPageScroller.IsRangeStored: Boolean; +begin + Result := not AutoRange; +end; + +procedure TTBXCustomPageScroller.Loaded; +begin + inherited; + UpdateButtons; +end; + +procedure TTBXCustomPageScroller.RecalcNCArea; +begin + SetWindowPos(Handle, 0, 0, 0, 0, 0, + SWP_FRAMECHANGED or SWP_NOACTIVATE or SWP_NOZORDER or SWP_NOMOVE or SWP_NOSIZE); +end; + +procedure TTBXCustomPageScroller.Resizing; +begin + // do nothing by default +end; + +procedure TTBXCustomPageScroller.ScrollTimerTimer(Sender: TObject); +begin + HandleScrollTimer; +end; + +procedure TTBXCustomPageScroller.ScrollToCenter(ARect: TRect); +var + X, Y: Integer; +begin + if Orientation = tpsoVertical then + begin + if ARect.Bottom - ARect.Top < Range then Y := (ARect.Top + ARect.Bottom) div 2 + else Y := ARect.Top; + Position := Position + Y - Height div 2; + end + else + begin + if ARect.Right - ARect.Left < Range then X := (ARect.Left + ARect.Right) div 2 + else X := ARect.Left; + Position := Position + X - Width div 2; + end; +end; + +procedure TTBXCustomPageScroller.ScrollToCenter(AControl: TControl); +var + R: TRect; +begin + R := AControl.ClientRect; + R.TopLeft := ScreenToClient(AControl.ClientToScreen(R.TopLeft)); + R.BottomRight := ScreenToClient(AControl.ClientToScreen(R.BottomRight)); + ScrollToCenter(R); +end; + +procedure TTBXCustomPageScroller.SetAutoRange(Value: Boolean); +begin + if FAutoRange <> Value then + begin + FAutoRange := Value; + if Value then CalcAutoRange else Range := 0; + end; +end; + +procedure TTBXCustomPageScroller.SetButtonSize(Value: Integer); +begin + if FButtonSize <> Value then + begin + FButtonSize := Value; + UpdateButtons; + end; +end; + +procedure TTBXCustomPageScroller.SetOrientation(Value: TTBXPageScrollerOrientation); +begin + if Orientation <> Value then + begin + FOrientation := Value; + Realign; + end; +end; + +procedure TTBXCustomPageScroller.SetPosition(Value: Integer); +var + OldPos: Integer; +begin + if csReading in ComponentState then FPosition := Value + else + begin + ValidatePosition(Value); + if FPosition <> Value then + begin + OldPos := FPosition; + FPosition := Value; + + if OldPos > 0 then Inc(OldPos, ButtonSize); + if Value > 0 then Inc(Value, ButtonSize); + + if Orientation = tpsoHorizontal then ScrollBy(OldPos - Value, 0) + else ScrollBy(0, OldPos - Value); + UpdateButtons; + end; + end; +end; + +procedure TTBXCustomPageScroller.SetRange(Value: Integer); +begin + FAutoRange := False; + DoSetRange(Value); +end; + +procedure TTBXCustomPageScroller.StopScrolling; +begin + if (FScrollDirection <> 0) or (FScrollCounter <> 0) or (FScrollTimer.Enabled) then + begin + FScrollDirection := 0; + FScrollCounter := 0; + FScrollTimer.Enabled := False; + if HandleAllocated and IsWindowVisible(Handle) then DrawNCArea(False, 0, 0); + end; +end; + +procedure TTBXCustomPageScroller.UpdateButtons; +var + Sz: Integer; + OldVisibleButtons: TTBXPageScrollerButtons; + RealignNeeded: Boolean; +begin + RealignNeeded := False; + if not FUpdatingButtons and HandleAllocated then + try + FUpdatingButtons := True; + if Orientation = tpsoHorizontal then Sz := Width + else Sz := Height; + OldVisibleButtons := FVisibleButtons; + FVisibleButtons := []; + + FPosRange := Range - Sz; + if FPosRange < 0 then FPosRange := 0; + if FPosition > FPosRange - 1 then + begin + FPosition := FPosRange; + RealignNeeded := True; + end; + + if Sz > ButtonSize * 3 then + begin + if Position > 0 then Include(FVisibleButtons, tpsbPrev); + if Range - Position > Sz then Include(FVisibleButtons, tpsbNext); + end; + if FVisibleButtons <> OldVisibleButtons then + begin + RecalcNCArea; + RealignNeeded := True; + end; + finally + FUpdatingButtons := False; + if RealignNeeded then Realign; + end; +end; + +procedure TTBXCustomPageScroller.ValidatePosition(var NewPos: Integer); +begin + if NewPos < 0 then NewPos := 0; + if NewPos > FPosRange then NewPos := FPosRange; +end; + +procedure TTBXCustomPageScroller.WMEraseBkgnd(var Message: TWmEraseBkgnd); +begin + if Color = clNone then + begin + DrawParentBackground(Self, Message.DC, ClientRect); + Message.Result := 1; + end + else inherited; +end; + +procedure TTBXCustomPageScroller.WMMouseMove(var Message: TWMMouseMove); +begin + if AutoScroll then StopScrolling; + inherited; +end; + +procedure TTBXCustomPageScroller.WMNCCalcSize(var Message: TWMNCCalcSize); +begin + with Message.CalcSize_Params^ do + begin + if Orientation = tpsoVertical then + begin + if tpsbPrev in FVisibleButtons then Inc(rgrc[0].Top, ButtonSize); + if tpsbNext in FVisibleButtons then Dec(rgrc[0].Bottom, ButtonSize); + end + else + begin + if tpsbPrev in FVisibleButtons then Inc(rgrc[0].Left, ButtonSize); + if tpsbNext in FVisibleButtons then Dec(rgrc[0].Right, ButtonSize); + end; + Message.Result := 0; + end; +end; + +procedure TTBXCustomPageScroller.WMNCHitTest(var Message: TWMNCHitTest); +var + Pt: TPoint; + R: TRect; +begin + DefaultHandler(Message); + with Message do if Result <> HTCLIENT then + begin + Pt := SmallPointToPoint(Pos); + GetWindowRect(Handle, R); + if PtInRect(R, Pt) then + begin + if (tpsbPrev in FVisibleButtons) then + begin + if Orientation = tpsoVertical then + begin + if Pt.Y < R.Top + ButtonSize then Result := HTSCROLLPREV + end + else + begin + if Pt.X < R.Left + ButtonSize then Result := HTSCROLLPREV + end; + end; + if (tpsbNext in FVisibleButtons) then + begin + if Orientation = tpsoVertical then + begin + if Pt.Y >= R.Bottom - ButtonSize then Result := HTSCROLLNEXT; + end + else + begin + if Pt.X >= R.Right - ButtonSize then Result := HTSCROLLNEXT; + end; + end; + end; + end; +end; + +procedure TTBXCustomPageScroller.WMNCLButtonDown(var Message: TWMNCLButtonDown); +begin + if (Win32MajorVersion >= 5) or + (Win32MajorVersion = 4) and (Win32MinorVersion >= 10) then + CallTrackMouseEvent(Handle, TME_LEAVE or $10 {TME_NONCLIENT}); + + if not AutoScroll and (Message.HitTest in [HTSCROLLPREV, HTSCROLLNEXT]) then + BeginScrolling(Message.HitTest) + else + inherited; +end; + +procedure TTBXCustomPageScroller.WMNCMouseLeave(var Message: TMessage); +begin + if AutoScroll then StopScrolling; + inherited; +end; + +procedure TTBXCustomPageScroller.WMNCMouseMove(var Message: TWMNCMouseMove); +var + OldScrollDirection: Integer; +begin + if (Win32MajorVersion >= 5) or + (Win32MajorVersion = 4) and (Win32MinorVersion >= 10) then + CallTrackMouseEvent(Handle, TME_LEAVE or $10 {TME_NONCLIENT}); + + if AutoScroll then + begin + OldScrollDirection := FScrollDirection; + case Message.HitTest of + HTSCROLLPREV: FScrollDirection := -1; + HTSCROLLNEXT: FScrollDirection := 1; + else + StopScrolling; + inherited; + Exit; + end; + if OldScrollDirection <> FScrollDirection then + begin + FScrollCounter := 0; + FScrollPending := True; + FScrollTimer.Interval := ScrollDelay; + FScrollTimer.Enabled := True; + DrawNCArea(False, 0, 0); + end; + end; +end; + +procedure TTBXCustomPageScroller.WMNCPaint(var Message: TMessage); +begin + DrawNCArea(False, 0, HRGN(Message.WParam)); +end; + +procedure TTBXCustomPageScroller.WMSize(var Message: TWMSize); +begin + FUpdatingButtons := True; + try + CalcAutoRange; + finally + FUpdatingButtons := False; + end; + Inc(FAutoRangeCount); + inherited; + Resizing; + Dec(FAutoRangeCount); +end; + +{ TTBXCustomCheckBox } + +procedure TTBXCustomCheckBox.Click; +begin + Toggle; + Invalidate; + inherited; +end; + +procedure TTBXCustomCheckBox.CMDialogChar(var Message: TCMDialogChar); +begin + with Message do + if Enabled and ShowAccelChar and IsAccel(CharCode, GetLabelText) and CanFocus and Visible then + begin + Click; + Result := 1; + end + else inherited; +end; + +procedure TTBXCustomCheckBox.CMDialogKey(var Message: TCMDialogKey); +begin + with Message do + if (CharCode = VK_RETURN) and Focused and + (KeyDataToShiftState(Message.KeyData) = []) then + begin + Click; + Result := 1; + end + else inherited; +end; + +procedure TTBXCustomCheckBox.CNCommand(var Message: TWMCommand); +begin + if Message.NotifyCode = BN_CLICKED then Toggle; +end; + +constructor TTBXCustomCheckBox.Create(AOwner: TComponent); +begin + inherited; + SmartFocus := True; + SpaceAsClick := True; + TabStop := True; +end; + +procedure TTBXCustomCheckBox.DoAdjustHeight(ACanvas: TCanvas; var NewHeight: Integer); +begin + inherited DoAdjustHeight(ACanvas, NewHeight); + if NewHeight < GetGlyphSize + 4 then NewHeight := GetGlyphSize + 4; +end; + +procedure TTBXCustomCheckBox.DoChange; +begin + if Assigned(FOnChange) then FOnChange(Self); +end; + +procedure TTBXCustomCheckBox.DoMouseEnter; +begin + inherited; + Invalidate; +end; + +procedure TTBXCustomCheckBox.DoMouseLeave; +begin + inherited; + Invalidate; +end; + +function TTBXCustomCheckBox.DoSetState(var NewState: TCheckBoxState): Boolean; +begin + Result := True; +end; + +function TTBXCustomCheckBox.GetChecked: Boolean; +begin + Result := State = cbChecked; +end; + +function TTBXCustomCheckBox.GetFocusRect(const R: TRect): TRect; +const + Alignments: array [TLeftRight] of Word = (DT_LEFT, DT_RIGHT); + WordWraps: array [TTextWrapping] of Integer = (DT_SINGLELINE or DT_VCENTER, + DT_SINGLELINE or DT_VCENTER or DT_END_ELLIPSIS, + DT_SINGLELINE or DT_VCENTER or DT_PATH_ELLIPSIS, DT_WORDBREAK); +var + TR: TRect; +begin + TR := R; + ApplyMargins(TR, GetTextMargins); + DoDrawText(Canvas, TR, (DT_EXPANDTABS or DT_CALCRECT) or WordWraps[Wrapping] or Alignments[Alignment]); + Result := R; + Result.Right := TR.Right + 2; + Result.Left := TR.Left - 2; +end; + +function TTBXCustomCheckBox.GetGlyphSize: Integer; +begin + Result := 13; +end; + +function TTBXCustomCheckBox.GetTextAlignment: TAlignment; +begin + Result := taLeftJustify; +end; + +function TTBXCustomCheckBox.GetTextMargins: TRect; +begin + Result := Rect(2, 2, 2, 2); + with Result do + if GetRealAlignment(Self) = taLeftJustify then Inc(Left, GetGlyphSize + 6) + else Inc(Right, GetGlyphSize + 6); +end; + +procedure TTBXCustomCheckBox.Paint; +const + EnabledState: array [Boolean] of Integer = (PFS_DISABLED, 0); + StateFlags: array [TCheckBoxState] of Integer = (0, PFS_CHECKED, PFS_MIXED); + HotState: array [Boolean] of Integer = (0, PFS_HOT); + PushedState: array [Boolean] of Integer = (0, PFS_PUSHED); + FocusedState: array [Boolean] of Integer = (0, PFS_FOCUSED); +var + Rect: TRect; + Sz, Flags: Integer; +begin + inherited; + with Canvas do + begin + Rect := ClientRect; + ApplyMargins(Rect, Margins); + Sz := GetGlyphSize; + if Alignment = taLeftJustify then Rect.Right := Rect.Left + GetGlyphSize + else Rect.Left := Rect.Right - GetGlyphSize; + Rect.Top := (Rect.Top + Rect.Bottom + 1 - Sz) div 2; + Rect.Bottom := Rect.Top + Sz; + Brush.Color := clBtnShadow; + Flags := EnabledState[Enabled]; + if Enabled then Flags := Flags or StateFlags[State] or + HotState[MouseInControl] or PushedState[Pushed and MouseInControl] or FocusedState[Focused]; + CurrentTheme.PaintFrameControl(Canvas, Rect, PFC_CHECKBOX, Flags, nil); + end; +end; + +procedure TTBXCustomCheckBox.SetChecked(Value: Boolean); +begin + if Value then State := cbChecked else State := cbUnchecked; +end; + +procedure TTBXCustomCheckBox.SetState(Value: TCheckBoxState); +begin + if (FState <> Value) and DoSetState(Value) then + begin + FState := Value; + Invalidate; + DoChange; + end; +end; + +procedure TTBXCustomCheckBox.Toggle; +begin + case State of + cbUnchecked: if AllowGrayed then State := cbGrayed else State := cbChecked; + cbChecked: State := cbUnchecked; + cbGrayed: State := cbChecked; + end; +end; + +procedure TTBXCustomCheckBox.WMNCHitTest(var Message: TWMNCHitTest); +var + P: TPoint; + R: TRect; + SL, SR: Integer; +begin + inherited; + if not (csDesigning in ComponentState) then + begin + P := ScreenToClient(SmallPointToPoint(Message.Pos)); + R := ClientRect; + ApplyMargins(R, Margins); + SL := R.Left; SR := R.Right; + R := GetFocusRect(R); + if GetRealAlignment(Self) = taLeftJustify then R.Left := SL + else R.Right := SR; + if not PtInRect(R, P) then Message.Result := HTTRANSPARENT; + end; +end; + +{ TTBXCustomRadioButton } + +procedure TTBXCustomRadioButton.Click; +begin + if not Checked then Checked := True; + Invalidate; + inherited; +end; + +procedure TTBXCustomRadioButton.CMDialogChar(var Message: TCMDialogChar); +begin + with Message do + if Enabled and ShowAccelChar and IsAccel(CharCode, GetLabelText) and CanFocus and Visible then + begin + Click; + Result := 1; + end + else inherited; +end; + +procedure TTBXCustomRadioButton.CNCommand(var Message: TWMCommand); +begin + if Message.NotifyCode = BN_CLICKED then Checked := not Checked; +end; + +constructor TTBXCustomRadioButton.Create(AOwner: TComponent); +begin + inherited; + SmartFocus := True; + SpaceAsClick := True; + TabStop := True; +end; + +procedure TTBXCustomRadioButton.DoAdjustHeight(ACanvas: TCanvas; var NewHeight: Integer); +begin + inherited DoAdjustHeight(ACanvas, NewHeight); + if NewHeight < GetGlyphSize + 4 then NewHeight := GetGlyphSize + 4; +end; + +procedure TTBXCustomRadioButton.DoChange; +begin + if Assigned(FOnChange) then FOnChange(Self); +end; + +procedure TTBXCustomRadioButton.DoMouseEnter; +begin + inherited; + Invalidate; +end; + +procedure TTBXCustomRadioButton.DoMouseLeave; +begin + inherited; + Invalidate; +end; + +function TTBXCustomRadioButton.DoSetChecked(var Value: Boolean): Boolean; +begin + Result := True; +end; + +function TTBXCustomRadioButton.GetFocusRect(const R: TRect): TRect; +const + Alignments: array [TLeftRight] of Word = (DT_LEFT, DT_RIGHT); + WordWraps: array [TTextWrapping] of Integer = (DT_SINGLELINE or DT_VCENTER, + DT_SINGLELINE or DT_VCENTER or DT_END_ELLIPSIS, + DT_SINGLELINE or DT_VCENTER or DT_PATH_ELLIPSIS, DT_WORDBREAK); +var + TR: TRect; +begin + TR := R; + ApplyMargins(TR, GetTextMargins); + DoDrawText(Canvas, TR, (DT_EXPANDTABS or DT_CALCRECT) or WordWraps[Wrapping] or Alignments[Alignment]); + Result := R; + Result.Right := TR.Right + 2; + Result.Left := TR.Left - 2; +end; + +function TTBXCustomRadioButton.GetGlyphSize: Integer; +begin + Result := 13; +end; + +function TTBXCustomRadioButton.GetTextAlignment: TAlignment; +begin + Result := taLeftJustify; +end; + +function TTBXCustomRadioButton.GetTextMargins: TRect; +begin + Result := Rect(2, 2, 2, 2); + with Result do + if GetRealAlignment(Self) = taLeftJustify then Inc(Left, GetGlyphSize + 6) + else Inc(Right, GetGlyphSize + 6); +end; + +procedure TTBXCustomRadioButton.Paint; +const + EnabledState: array [Boolean] of Integer = (PFS_DISABLED, 0); + CheckedState: array [Boolean] of Integer = (0, PFS_CHECKED); + HotState: array [Boolean] of Integer = (0, PFS_HOT); + PushedState: array [Boolean] of Integer = (0, PFS_PUSHED); + FocusedState: array [Boolean] of Integer = (0, PFS_FOCUSED); +var + Rect: TRect; + Sz, Flags: Integer; +begin + inherited; + with Canvas do + begin + Rect := ClientRect; + with Margins do + begin + Inc(Rect.Left, Left); + Inc(Rect.Top, Top); + Dec(Rect.Right, Right); + Dec(Rect.Bottom, Bottom); + end; + Sz := GetGlyphSize; + if Alignment = taLeftJustify then Rect.Right := Rect.Left + GetGlyphSize + else Rect.Left := Rect.Right - GetGlyphSize; + Rect.Top := (Rect.Top + Rect.Bottom + 1 - Sz) div 2; + Rect.Bottom := Rect.Top + Sz; + Brush.Color := clBtnShadow; + Flags := EnabledState[Enabled]; + if Enabled then Flags := Flags or CheckedState[Checked] or + HotState[MouseInControl] or PushedState[Pushed and MouseInControl] or FocusedState[Focused]; + CurrentTheme.PaintFrameControl(Canvas, Rect, PFC_RADIOBUTTON, Flags, nil); + end; +end; + +procedure TTBXCustomRadioButton.SetChecked(Value: Boolean); +begin + if (Value <> FChecked) and DoSetChecked(Value) then + begin + FChecked := Value; + TabStop := Value; + if Value then TurnSiblingsOff; + Invalidate; + DoChange; + end; +end; + +procedure TTBXCustomRadioButton.SetGroupIndex(Value: Integer); +begin + FGroupIndex := Value; + if Checked then TurnSiblingsOff; +end; + +procedure TTBXCustomRadioButton.TurnSiblingsOff; +var + I: Integer; + Sibling: TControl; +begin + if Parent <> nil then + with Parent do + for I := 0 to ControlCount - 1 do + begin + Sibling := Controls[I]; + if (Sibling <> Self) and (Sibling is TTBXCustomRadioButton) then + with TTBXCustomRadioButton(Sibling) do + begin + if GroupIndex = Self.GroupIndex then SetChecked(False); + end; + end; +end; + +procedure TTBXCustomRadioButton.WMNCHitTest(var Message: TWMNCHitTest); +var + P: TPoint; + R: TRect; + SL, SR: Integer; +begin + inherited; + if not (csDesigning in ComponentState) then + begin + P := ScreenToClient(SmallPointToPoint(Message.Pos)); + R := ClientRect; + ApplyMargins(R, Margins); + SL := R.Left; SR := R.Right; + R := GetFocusRect(R); + if GetRealAlignment(Self) = taLeftJustify then R.Left := SL + else R.Right := SR; + if not PtInRect(R, P) then Message.Result := HTTRANSPARENT; + end; +end; + +end. diff --git a/official/2.1.6+2.1.beta1/TBX/TBXExtItems.pas b/official/2.1.6+2.1.beta1/TBX/TBXExtItems.pas new file mode 100644 index 0000000..618a993 --- /dev/null +++ b/official/2.1.6+2.1.beta1/TBX/TBXExtItems.pas @@ -0,0 +1,2376 @@ +unit TBXExtItems; + +// TBX Package +// Copyright 2001-2004 Alex A. Denisov. All Rights Reserved +// See TBX.chm for license and installation instructions +// +// $Id: TBXExtItems.pas 16 2004-05-26 02:02:55Z Alex@ZEISS $ + +interface + +{$I ..\..\Source\TB2Ver.inc} +{$I TBX.inc} + +{$DEFINE COMPATIBLE} + +uses + Windows, Messages, Classes, SysUtils, Graphics, Controls, StdCtrls, ExtCtrls, + TBX, TBXThemes, TB2Item, TB2Toolbar, TB2ExtItems, TBXLists, TB2MRU; + +const + tcrNumericProperty = 3; + tcrSpinButton = 4; + tcrList = 5; + +type + TTBXEditItemViewer = class; + TTBXEditChange = procedure(Sender: TObject; const Text: string) of object; + + { TTBXEditItem } + { Extends standard TTBEditItem, providing additional features and some + combo box functionality, which is used in descendants } + + TTBXEditItem = class(TTBEditItem) + private + FAlignment: TAlignment; + FAutoCompleteCounter: Integer; + FEditorFontSettings: TFontSettings; + FFontSettings: TFontSettings; + FIsChanging: Boolean; + FLastEditChange: string; + FPasswordChar: Char; + FReadOnly: Boolean; + FShowImage: Boolean; + FOnChange: TTBXEditChange; + procedure FontSettingsChanged(Sender: TObject); + procedure SetAlignment(Value: TAlignment); + procedure SetPasswordChar(Value: Char); + procedure SetShowImage(const Value: Boolean); + procedure SetFontSettings(Value: TFontSettings); + protected + function DoAcceptText(var NewText: string): Boolean; override; + function DoAutoComplete(var AText: string): Boolean; virtual; + procedure DoBeginEdit(Viewer: TTBEditItemViewer); override; + procedure DoChange(const AText: string); virtual; + procedure DoTextChanged(Reason: Integer); override; + function GetImageIndex: Integer; virtual; + function GetItemViewerClass(AView: TTBView): TTBItemViewerClass; override; + procedure GetPopupPosition(ParentView: TTBView; PopupWindow: TTBPopupWindow; var PopupPositionRec: TTBPopupPositionRec); override; + function GetPopupWindowClass: TTBPopupWindowClass; override; + procedure HandleEditChange(Edit: TEdit); virtual; + public + function StartEditing(AView: TTBView): Boolean; + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + published + property Alignment: TAlignment read FAlignment write SetAlignment default taLeftJustify; + property EditorFontSettings: TFontSettings read FEditorFontSettings write FEditorFontSettings; + property ExtendedAccept; + property FontSettings: TFontSettings read FFontSettings write SetFontSettings; + property ImageIndex; + property Images; + property PasswordChar: Char read FPasswordChar write SetPasswordChar default #0; + property ReadOnly: Boolean read FReadOnly write FReadOnly default False; + property ShowImage: Boolean read FShowImage write SetShowImage default False; + property OnChange: TTBXEditChange read FOnChange write FOnChange; + property OnSelect; + end; + + TTBXEditItemViewer = class(TTBEditItemViewer) + private + procedure EditChangeHandler(Sender: TObject); + function MeasureEditCaption: TSize; + function MeasureTextHeight: Integer; + procedure HandleEditChange(Edit: TEdit); + protected + OldWndProc: TWndMethod; + procedure CalcSize(const Canvas: TCanvas; var AWidth, AHeight: Integer); override; + function DoExecute: Boolean; override; + function HandleEditMessage(var Message: TMessage): Boolean; virtual; + function GetAccRole: Integer; override; + procedure GetItemInfo(out ItemInfo: TTBXItemInfo; IsHoverItem, IsPushed, UseMenuColor: Boolean); virtual; + function GetEditControlClass: TEditClass; override; + procedure GetEditInfo(out EditInfo: TTBXEditInfo; const ItemInfo: TTBXItemInfo); virtual; + function GetIndentBefore: Integer; virtual; + function GetIndentAfter: Integer; virtual; + procedure GetEditRect(var R: TRect); override; + function IsToolbarSize: Boolean; override; + procedure NewEditWndProc(var Message: TMessage); + procedure Paint(const Canvas: TCanvas; const ClientAreaRect: TRect; IsHoverItem, IsPushed, UseDisabledShadow: Boolean); override; + function ShowImage: Boolean; virtual; + public + function IsToolbarStyle: Boolean; override; + end; + + { TTBXSpinEditItem } + TTBXCustomSpinEditItem = class; + + TSEValueType = (evtInteger, evtFloat, evtHex); + TDecimal = 0..10; + TSEChangeEvent = procedure(Sender: TTBXCustomSpinEditItem; const AValue: Extended) of object; + TSEConvertEvent = procedure(Sender: TTBXCustomSpinEditItem; const APrefix, APostfix: string; var AValue: Extended; var CanConvert: Boolean) of object; + TSEStepEvent = procedure(Sender: TTBXCustomSpinEditItem; Step: Integer; const OldValue: Extended; var NewValue: Extended) of object; + TSETextToValueEvent = procedure(Sender: TTBXCustomSpinEditItem; const AText: string; out AValue: Extended; var CanConvert: Boolean) of object; + TSEValueToTextEvent = procedure(Sender: TTBXCustomSpinEditItem; const AValue: Extended; var Text: string) of object; + + TTBXCustomSpinEditItem = class(TTBXEditItem) + private + FDecimal: TDecimal; + FLastGoodValue: Extended; + FMaxValue: Extended; + FMinValue: Extended; + FIncrement: Extended; + FSpaceBeforePostfix: Boolean; + FSpaceAfterPrefix: Boolean; + FPostfix: string; + FPrefix: string; + FSnap: Boolean; + FValueType: TSEValueType; + FOnConvert: TSEConvertEvent; + FOnTextToValue: TSETextToValueEvent; + FOnValueChange: TSEChangeEvent; + FOnValueToText: TSEValueToTextEvent; + FOnStep: TSEStepEvent; + function IsIncrementStored: Boolean; + function IsMinValueStored: Boolean; + function IsMaxValueStored: Boolean; + function IsValueStored: Boolean; + function GetValue: Extended; + procedure SetValue(NewValue: Extended); + procedure SetValueType(NewType: TSEValueType); + procedure SetDecimal(NewDecimal: TDecimal); + procedure SetIncrement(const NewIncrement: Extended); + procedure SetPostfix(const NewPostfix: string); + procedure SetPrefix(const NewPrefix: string); + procedure SetSpaceAfterPrefix(UseSpace: Boolean); + procedure SetSpaceBeforePostfix(UseSpace: Boolean); + function ValidateUnits(const S: string): Boolean; + function GetAsInteger: Integer; + procedure SetAsInteger(AValue: Integer); + protected + function CheckValue(const V: Extended): Extended; + procedure ClickUp; + procedure ClickDown; + function DoAcceptText(var NewText: string): Boolean; override; + function DoConvert(const APrefix, APostfix: string; var AValue: Extended): Boolean; virtual; + procedure DoStep(Step: Integer; const OldValue: Extended; var NewValue: Extended); virtual; + procedure DoTextChanged(Reason: Integer); override; + function DoTextToValue(const AText: string; out AValue: Extended): Boolean; virtual; + procedure DoValueChange(const V: Extended); virtual; + procedure DoValueToText(const NewValue: Extended; var NewText: string); virtual; + function GetAsText(AValue: Extended): string; + function GetItemViewerClass(AView: TTBView): TTBItemViewerClass; override; + function ParseValue(const S: string; out V: Extended): Boolean; + procedure SetValueEx(NewValue: Extended; Reason: Integer); + property Alignment default taRightJustify; + property OnConvert: TSEConvertEvent read FOnConvert write FOnConvert; + property OnStep: TSEStepEvent read FOnStep write FOnStep; + property OnTextToValue: TSETextToValueEvent read FOnTextToValue write FOnTextToValue; + property OnValueChange: TSEChangeEvent read FOnValueChange write FOnValueChange; + property OnValueToText: TSEValueToTextEvent read FOnValueToText write FOnValueToText; + public + constructor Create(AOwner: TComponent); override; + property ValueType: TSEValueType read FValueType write SetValueType default evtInteger; + property AsInteger: Integer read GetAsInteger write SetAsInteger stored False; + property Decimal: TDecimal read FDecimal write SetDecimal default 2; + property Increment: Extended read FIncrement write SetIncrement stored IsIncrementStored; + property MaxValue: Extended read FMaxValue write FMaxValue stored IsMaxValueStored; + property MinValue: Extended read FMinValue write FMinValue stored IsMinValueStored; + property Postfix: string read FPostfix write SetPostfix; + property Prefix: string read FPrefix write SetPrefix; + property Snap: Boolean read FSnap write FSnap default True; + property SpaceAfterPrefix: Boolean read FSpaceAfterPrefix write SetSpaceAfterPrefix; + property SpaceBeforePostfix: Boolean read FSpaceBeforePostfix write SetSpaceBeforePostfix; + property Value: Extended read GetValue write SetValue stored IsValueStored; + published + property Text stored False; + end; + + TTBXSpinEditItem = class(TTBXCustomSpinEditItem) + published + property ValueType; + property Alignment; + property Decimal; + property Increment; + property MaxValue; + property MinValue; + property Postfix; + property Prefix; + property Snap; + property SpaceAfterPrefix; + property SpaceBeforePostfix; + property Value; + property OnConvert; + property OnStep; + property OnTextToValue; + property OnValueChange; + property OnValueToText; + end; + + TSEBtnState = (ebsNone, ebsUp, ebsDown); + + TTBXSpinEditViewer = class(TTBXEditItemViewer) + private + FBtnState: TSEBtnState; + FBtnTimer: TTimer; + procedure TimerHandler(Sender: TObject); + protected + function GetIndentAfter: Integer; override; + procedure GetEditInfo(out EditInfo: TTBXEditInfo; const ItemInfo: TTBXItemInfo); override; + function HandleEditMessage(var Message: TMessage): Boolean; override; + procedure InvalidateButtons; + function IsPtInButtonPart(X, Y: Integer): Boolean; override; + procedure LosingCapture; override; + procedure MouseDown(Shift: TShiftState; X, Y: Integer; var MouseDownOnMenu: Boolean); override; + procedure MouseUp(X, Y: Integer; MouseWasDownOnMenu: Boolean); override; + public + destructor Destroy; override; + end; + + { TTBXCustomDropDownItem } + { An extended edit item tb2k with a button. The dropdown list support is + implemented in descendants, such as TTBXComboBoxItem } + + TTBXCustomDropDownItem = class(TTBXEditItem) + private + FAlwaysSelectFirst: Boolean; + FDropDownList: Boolean; + protected + function CreatePopup(const ParentView: TTBView; const ParentViewer: TTBItemViewer; + const PositionAsSubmenu, SelectFirstItem, Customizing: Boolean; + const APopupPoint: TPoint; const Alignment: TTBPopupAlignment): TTBPopupWindow; override; + function GetItemViewerClass(AView: TTBView): TTBItemViewerClass; override; + public + constructor Create(AOwner: TComponent); override; + property AlwaysSelectFirst: Boolean read FAlwaysSelectFirst write FAlwaysSelectFirst default True; + property DropDownList: Boolean read FDropDownList write FDropDownList default False; + end; + + TTBXDropDownItem = class(TTBXCustomDropDownItem) + published + property AlwaysSelectFirst; + property DropDownList; + property LinkSubitems; + property SubMenuImages; + end; + + TTBXDropDownItemViewer = class(TTBXEditItemViewer) + protected + procedure GetCursor(const Pt: TPoint; var ACursor: HCURSOR); override; + procedure GetEditInfo(out EditInfo: TTBXEditInfo; const ItemInfo: TTBXItemInfo); override; + function GetIndentAfter: Integer; override; + function HandleEditMessage(var Message: TMessage): Boolean; override; + function IsPtInButtonPart(X, Y: Integer): Boolean; override; + procedure KeyDown(var Key: Word; Shift: TShiftState); override; + end; + +{$IFDEF COMPATIBLE} + { For compatibility with previous versions } + TTBXComboItem = class(TTBXDropDownItem); +{$ENDIF} + + { TTBXComboBoxItem } + { A combination of dropdown combo with a stringlist subitem } + TTBXComboBoxItem = class; + TTBXCAdjustImageIndex = procedure(Sender: TTBXComboBoxItem; const AText: string; + AIndex: Integer; var ImageIndex: Integer) of object; + + TTBXComboBoxItem = class(TTBXCustomDropDownItem) + private + FAutoComplete: Boolean; + FList: TTBXStringList; + FOnItemClick: TNotifyEvent; + FOnAdjustImageIndex: TTBXCAdjustImageIndex; + procedure AdjustImageIndexHandler(Sender: TTBXCustomList; AItemIndex: Integer; var ImageIndex: Integer); + function GetItemIndex: Integer; + function GetMaxVisibleItems: Integer; + function GetMaxWidth: Integer; + function GetMinWidth: Integer; + function GetStrings: TStrings; + function GetShowListImages: Boolean; + function GetOnClearItem: TTBXLPaintEvent; + function GetOnDrawItem: TTBXLPaintEvent; + function GetOnMeasureHeight: TTBXLMeasureHeight; + function GetOnMeasureWidth: TTBXLMeasureWidth; + procedure ListChangeHandler(Sender: TObject); + procedure ListClickHandler(Sender: TObject); + procedure SetItemIndex(Value: Integer); + procedure SetMaxVisibleItems(Value: Integer); + procedure SetMaxWidth(Value: Integer); + procedure SetMinWidth(Value: Integer); + procedure SetOnClearItem(Value: TTBXLPaintEvent); + procedure SetOnDrawItem(Value: TTBXLPaintEvent); + procedure SetOnMeasureHeight(Value: TTBXLMeasureHeight); + procedure SetOnMeasureWidth(Value: TTBXLMeasureWidth); + procedure SetStrings(Value: TStrings); + procedure SetShowListImages(Value: Boolean); + protected + CachedImageIndex: Integer; + CacheValid: Boolean; + IsChanging: Boolean; + procedure AdjustImageIndex(const AText: string; AIndex: Integer; var ImageIndex: Integer); virtual; + function DoAutoComplete(var AText: string): Boolean; override; + procedure DoListChange; virtual; + procedure DoListClick; virtual; + procedure DoPopup(Sender: TTBCustomItem; FromLink: Boolean); override; + function GetImageIndex: Integer; override; + function GetItemViewerClass(AView: TTBView): TTBItemViewerClass; override; + function GetStringListClass: TTBXStringListClass; virtual; + procedure HandleEditChange(Edit: TEdit); override; + public + constructor Create(AOwner: TComponent); override; + procedure Loaded; override; + property ItemIndex: Integer read GetItemIndex write SetItemIndex default -1; + published + property AutoComplete: Boolean read FAutoComplete write FAutoComplete default True; + property DropDownList; + property MaxListWidth: Integer read GetMaxWidth write SetMaxWidth default 0; + property MaxVisibleItems: Integer read GetMaxVisibleItems write SetMaxVisibleItems default 8; + property MinListWidth: Integer read GetMinWidth write SetMinWidth default 64; + property ShowListImages: Boolean read GetShowListImages write SetShowListImages default False; + property Strings: TStrings read GetStrings write SetStrings; + property SubMenuImages; + property OnChange; + property OnAdjustImageIndex: TTBXCAdjustImageIndex read FOnAdjustImageIndex write FOnAdjustImageIndex; + property OnClearItem: TTBXLPaintEvent read GetOnClearItem write SetOnClearItem; + property OnDrawItem: TTBXLPaintEvent read GetOnDrawItem write SetOnDrawItem; + property OnItemClick: TNotifyEvent read FOnItemClick write FOnItemClick; + property OnMeasureHeight: TTBXLMeasureHeight read GetOnMeasureHeight write SetOnMeasureHeight; + property OnMeasureWidth: TTBXLMeasureWidth read GetOnMeasureWidth write SetOnMeasureWidth; + property OnPopup; + end; + +{$IFDEF COMPATIBLE} + { For compatibility with previous versions } + TTBXComboList = class(TTBXComboBoxItem); +{$ENDIF} + + TTBXComboBoxItemViewer = class(TTBXDropDownItemViewer) + protected + function HandleEditMessage(var Message: TMessage): Boolean; override; + end; + + { TTBXLabelItem } + + TTBXLabelOrientation = (tbxoAuto, tbxoHorizontal, tbxoVertical); + TNonNegativeInt = 0..MaxInt; + + TTBXLabelItem = class(TTBCustomItem) + private + FCaption: TCaption; + FFontSettings: TFontSettings; + FMargin: Integer; + FShowAccelChar: Boolean; + FOrientation: TTBXLabelOrientation; + FOnAdjustFont: TAdjustFontEvent; + procedure FontSettingsChanged(Sender: TObject); + procedure SetMargin(Value: Integer); + procedure SetOrientation(Value: TTBXLabelOrientation); + procedure SetCaption(const Value: TCaption); + procedure SetFontSettings(Value: TFontSettings); + procedure SetShowAccelChar(Value: Boolean); + protected + function GetItemViewerClass (AView: TTBView): TTBItemViewerClass; override; + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + procedure UpdateCaption(const Value: TCaption); + published + property Caption: TCaption read FCaption write SetCaption; + property Enabled; + property FontSettings: TFontSettings read FFontSettings write SetFontSettings; + property Margin: Integer read FMargin write SetMargin default 0; + property Orientation: TTBXLabelOrientation read FOrientation write SetOrientation default tbxoAuto; + property ShowAccelChar: Boolean read FShowAccelChar write SetShowAccelChar default True; + property Visible; + property OnAdjustFont: TAdjustFontEvent read FOnAdjustFont write FOnAdjustFont; + end; + + TTBXLabelItemViewer = class(TTBItemViewer) + protected + function GetCaptionText: string; override; + function GetIsHoriz: Boolean; virtual; + procedure DoAdjustFont(AFont: TFont; StateFlags: Integer); virtual; + procedure CalcSize(const Canvas: TCanvas; var AWidth, AHeight: Integer); override; + procedure Paint(const Canvas: TCanvas; const ClientAreaRect: TRect; + IsHoverItem, IsPushed, UseDisabledShadow: Boolean); override; + function IsToolbarSize: Boolean; override; + public + function IsToolbarStyle: Boolean; override; + end; + + { TTBXColorItem } + + TTBXColorItem = class(TTBXCustomItem) + private + FColor: TColor; + procedure SetColor(Value: TColor); + protected + function GetItemViewerClass (AView: TTBView): TTBItemViewerClass; override; + public + constructor Create(AOwner: TComponent); override; + published + property Action; + property AutoCheck; + property Caption; + property Checked; + property Color: TColor read FColor write SetColor default clWhite; + property DisplayMode; + property Enabled; + property FontSettings; + property GroupIndex; + property HelpContext; + property Hint; + property InheritOptions; + property MaskOptions; + property MinHeight; + property MinWidth; + property Options; + property ShortCut; + property Visible; + property OnAdjustFont; + property OnClick; + end; + + TTBXColorItemViewer = class(TTBXItemViewer) + protected + procedure DoPaintCaption(Canvas: TCanvas; const ClientAreaRect: TRect; + var CaptionRect: TRect; IsTextRotated: Boolean; var PaintDefault: Boolean); override; + function GetImageShown: Boolean; override; + function GetImageSize: TSize; override; + procedure DrawItemImage(Canvas: TCanvas; ARect: TRect; ItemInfo: TTBXItemInfo); override; + public + constructor Create(AView: TTBView; AItem: TTBCustomItem; AGroupLevel: Integer); override; + end; + + { TTBXMRUList } + + TTBXMRUList = class(TTBMRUList) + private + FKeyShift: Integer; + procedure SetKeyShift(Value: Integer); + protected + function GetFirstKey: Integer; override; + function GetItemClass: TTBCustomItemClass; override; + procedure SetItemCaptions; override; + published + property KeyShift: Integer read FKeyShift write SetKeyShift default 0; + end; + + { TTBXMRUListItem } + + TTBXMRUListItem = class(TTBXCustomItem) + private + FMRUList: TTBMRUList; + procedure SetMRUList(Value: TTBMRUList); + protected + procedure Notification(AComponent: TComponent; Operation: TOperation); override; + public + constructor Create(AOwner: TComponent); override; + published + property MRUList: TTBMRUList read FMRUList write SetMRUList; + end; + +implementation + +uses TB2Common, TB2Consts, TypInfo, Math, ImgList {$IFNDEF JR_D5}, DsgnIntf{$ENDIF}; + +const + { Repeat intervals for spin edit items } + SE_FIRSTINTERVAL = 400; + SE_INTERVAL = 100; + +type + TTBViewAccess = class(TTBView); + TTBItemAccess = class(TTBCustomItem); + TTBMRUListAccess = class(TTBMRUList); + TCustomEditAccess = class(TCustomEdit); + TFontSettingsAccess = class(TFontSettings); + +{ Misc. functions } + +function StartsText(const ASubText, AText: string): Boolean; +var + P: PChar; + L, L2: Integer; +begin + P := PChar(AText); + L := Length(ASubText); + L2 := Length(AText); + if L > L2 then Result := False + else Result := CompareString(LOCALE_USER_DEFAULT, NORM_IGNORECASE, + P, L, PChar(ASubText), L) = 2; +end; + +//============================================================================// + +{ TTBXEdit } + +type + TTBXEdit = class(TEdit) + private + FAlignment: TAlignment; + procedure SetAlignment(Value: TAlignment); + protected + procedure CreateParams(var Params: TCreateParams); override; + public + property Alignment: TAlignment read FAlignment write SetAlignment; + end; + +procedure TTBXEdit.CreateParams(var Params: TCreateParams); +const + Alignments: array[TAlignment] of Cardinal = (ES_LEFT, ES_RIGHT, ES_CENTER); +begin + inherited CreateParams(Params); + Params.Style := Params.Style or Alignments[FAlignment]; +end; + +procedure TTBXEdit.SetAlignment(Value: TAlignment); +begin + if Value <> FAlignment then + begin + FAlignment := Value; + RecreateWnd; + end; +end; + + +//============================================================================// + +{ TTBXEditItem } + +constructor TTBXEditItem.Create(AOwner: TComponent); +begin + inherited; + FEditorFontSettings := TFontSettings.Create; + FFontSettings := TFontSettings.Create; + TFontSettingsAccess(FEditorFontSettings).OnChange := FontSettingsChanged; + TFontSettingsAccess(FFontSettings).OnChange := FontSettingsChanged; +end; + +destructor TTBXEditItem.Destroy; +begin + FFontSettings.Free; + FEditorFontSettings.Free; + inherited; +end; + +function TTBXEditItem.DoAcceptText(var NewText: string): Boolean; +begin + Result := inherited DoAcceptText(NewText); +// if not Result then DoChange(Text); +end; + +function TTBXEditItem.DoAutoComplete(var AText: string): Boolean; +begin + Result := False; +end; + +procedure TTBXEditItem.DoBeginEdit(Viewer: TTBEditItemViewer); +begin + with Viewer do + begin + TTBXEdit(EditControl).Alignment := Alignment; + EditControl.PasswordChar := PasswordChar; + EditControl.SelectAll; + EditControl.ReadOnly := ReadOnly; + EditorFontSettings.Apply(EditControl.Font); + FAutoCompleteCounter := 0; + inherited; + if Viewer is TTBXEditItemViewer then + begin + EditControl.OnChange := TTBXEditItemViewer(Viewer).EditChangeHandler; + TTBXEditItemViewer(Viewer).OldWndProc := EditControl.WindowProc; + EditControl.WindowProc := TTBXEditItemViewer(Viewer).NewEditWndProc; + end; + end; +end; + +procedure TTBXEditItem.DoChange(const AText: string); +begin + if Assigned(FOnChange) then FOnChange(Self, AText); +end; + +procedure TTBXEditItem.DoTextChanged(Reason: Integer); +begin + if not ((Reason = tcrEditControl) and (Text = FLastEditChange)) then + DoChange(Text); +end; + +procedure TTBXEditItem.FontSettingsChanged(Sender: TObject); +begin + Change(True); +end; + +function TTBXEditItem.GetImageIndex: Integer; +begin + Result := ImageIndex; +end; + +function TTBXEditItem.GetItemViewerClass(AView: TTBView): TTBItemViewerClass; +begin + if not (tboUseEditWhenVertical in EditOptions) and + (AView.Orientation = tbvoVertical) then + Result := TTBXItemViewer + else + Result := TTBXEditItemViewer; +end; + +procedure TTBXEditItem.GetPopupPosition(ParentView: TTBView; + PopupWindow: TTBPopupWindow; var PopupPositionRec: TTBPopupPositionRec); +var + VT: Integer; +begin + inherited; + VT := GetWinViewType(PopupWindow); + PopupPositionRec.PlaySound := not (VT and PVT_LISTBOX = PVT_LISTBOX); +end; + +function TTBXEditItem.GetPopupWindowClass: TTBPopupWindowClass; +begin + Result := TTBXPopupWindow; +end; + +procedure TTBXEditItem.HandleEditChange(Edit: TEdit); +var + S, S2: string; +begin + if not FIsChanging then + begin + FIsChanging := True; + try + S := Edit.Text; + S2 := S; + if (Length(S) > 0) and (FAutoCompleteCounter > 0) and DoAutoComplete(S2) then + begin + Edit.Text := S2; + Edit.SelStart := Length(S); + Edit.SelLength := Length(S2) - Length(S); + S := S2; + end; + {if S <> FLastEditChange then} {vb-} + if AnsiCompareText(S, FLastEditChange) <> 0 then {vb+} + begin + DoChange(S); // note, Edit.Text may be different from Self.Text + FLastEditChange := S; + end; + finally + FIsChanging := False; + end; + end; +end; + +procedure TTBXEditItem.SetAlignment(Value: TAlignment); +begin + if Value <> FAlignment then + begin + FAlignment := Value; + Change(True); + end; +end; + +procedure TTBXEditItem.SetFontSettings(Value: TFontSettings); +begin + FFontSettings.Assign(Value); +end; + +procedure TTBXEditItem.SetPasswordChar(Value: Char); +begin + if Value <> FPasswordChar then + begin + FPasswordChar := Value; + Change(True); + end; +end; + +procedure TTBXEditItem.SetShowImage(const Value: Boolean); +begin + FShowImage := Value; + Change(True); +end; + +function TTBXEditItem.StartEditing(AView: TTBView): Boolean; +var + V: TTBItemViewer; + SaveText: string; +begin + Result := False; + V := AView.Find(Self); + if V is TTBXEditItemViewer then + begin + SaveText := Text; + TTBXEditItemViewer(V).DoExecute; + Result := Text <> SaveText; + end; +end; + + +//============================================================================// + +{ TTBXEditItemViewer } + +procedure TTBXEditItemViewer.CalcSize(const Canvas: TCanvas; var AWidth, AHeight: Integer); +var + W, B: Integer; + EditBoxHeight: Integer; + EditCaptionSize: TSize; +begin + if Self.Item is TTBXEditItem then with CurrentTheme do + begin + B := EditFrameWidth; + + AWidth := TTBXEditItem(Item).EditWidth; + if not IsToolbarStyle then + begin + EditCaptionSize := MeasureEditCaption; + W := EditCaptionSize.CX; + if W > 0 then Inc(W, MenuLeftCaptionMargin + MenuRightCaptionMargin + MenuImageTextSpace); + Inc(AWidth, GetPopupMargin(Self) + MenuImageTextSpace + W + EditMenuRightIndent); + end + else + begin + EditCaptionSize.CX := 0; + EditCaptionSize.CY := 0; + end; + + EditBoxHeight := MeasureTextHeight + 1; + Inc(EditBoxHeight, EditTextMarginVert * 2 + B * 2); + AHeight := Max(EditBoxHeight, EditCaptionSize.CY); + if not IsToolbarStyle then AHeight := AHeight; + if EditHeightEven then AHeight := (AHeight + 1) and not $01 + else AHeight := AHeight or $01; + end + else inherited; +end; + +procedure TTBXEditItemViewer.EditChangeHandler(Sender: TObject); +begin + HandleEditChange((Sender as TEdit)); +end; + +procedure TTBXEditItemViewer.HandleEditChange(Edit: TEdit); +begin + TTBXEditItem(Item).HandleEditChange(Edit); +end; + +procedure TTBXEditItemViewer.GetEditInfo(out EditInfo: TTBXEditInfo; const ItemInfo: TTBXItemInfo); +begin + FillChar(EditInfo, SizeOf(EditInfo), 0); + EditInfo.LeftBtnWidth := GetIndentBefore; + EditInfo.RightBtnWidth := GetIndentAfter; +end; + +function TTBXEditItemViewer.GetAccRole: Integer; +const + ROLE_SYSTEM_SPINBUTTON = $34; + ROLE_SYSTEM_COMBOBOX = $2E; +begin + Result := inherited GetAccRole; + if Self is TTBXSpinEditViewer then Result := ROLE_SYSTEM_SPINBUTTON + else if Self is TTBXDropDownItemViewer then Result := ROLE_SYSTEM_COMBOBOX; +end; + +procedure TTBXEditItemViewer.GetItemInfo(out ItemInfo: TTBXItemInfo; IsHoverItem, IsPushed, UseMenuColor: Boolean); +const + CToolbarStyle: array [Boolean] of Integer = (0, IO_TOOLBARSTYLE); + CDesigning: array [Boolean] of Integer = (0, IO_DESIGNING); +var + Item: TTBXEditItem; +begin + Item := TTBXEditItem(Self.Item); + + FillChar(ItemInfo, SizeOf(TTBXItemInfo), 0); + ItemInfo.ViewType := GetViewType(View); + ItemInfo.ItemOptions := CToolbarStyle[IsToolbarStyle] + or CDesigning[csDesigning in Item.ComponentState]; + ItemInfo.Enabled := Item.Enabled or View.Customizing; + ItemInfo.Pushed := IsPushed; + ItemInfo.Selected := Item.Checked; + if IsHoverItem then + begin + if not ItemInfo.Enabled and not View.MouseOverSelected then + ItemInfo.HoverKind := hkKeyboardHover + else + if ItemInfo.Enabled then ItemInfo.HoverKind := hkMouseHover; + end + else ItemInfo.HoverKind := hkNone; + if not IsToolbarStyle then ItemInfo.PopupMargin := GetPopupMargin(Self); +end; + +procedure TTBXEditItemViewer.GetEditRect(var R: TRect); +const + TB2K_EDIT_BORDER = 3; +var + W, B: Integer; +begin + if Item is TTBXEditItem then with CurrentTheme do + begin + R := BoundsRect; + if not IsToolbarStyle then + begin + W := MeasureEditCaption.CX; + if W > 0 then Inc(W, MenuLeftCaptionMargin + MenuRightCaptionMargin + MenuImageTextSpace); + Inc(R.Left, GetPopupMargin(Self) + MenuImageTextSpace + W); + Dec(R.Right, EditMenuRightIndent); + end; + + B := EditFrameWidth - TB2K_EDIT_BORDER; + InflateRect(R, -B - EditTextMarginHorz , -B - EditTextMarginVert); + Inc(R.Left, GetIndentBefore); + Dec(R.Right, GetIndentAfter); + end + else inherited; +end; + +function TTBXEditItemViewer.GetIndentAfter: Integer; +begin + Result := 0; +end; + +function TTBXEditItemViewer.GetIndentBefore: Integer; +var + ImgList: TCustomImageList; +begin + if ShowImage then + begin + ImgList := GetImageList; + if ImgList <> nil then Result := ImgList.Width + 2 + else Result := 0; + end + else Result := 0; +end; + +function TTBXEditItemViewer.HandleEditMessage(var Message: TMessage): Boolean; +const + CharKeys = [VK_SPACE, $30..$5A, VK_NUMPAD0..VK_DIVIDE, $BA..$F5]; +begin + if Message.Msg = WM_KEYDOWN then + begin + if Message.WParam in CharKeys then Inc(TTBXEditItem(Item).FAutoCompleteCounter) + end + else if Message.Msg = WM_KEYUP then + begin + if Message.WParam in CharKeys then Dec(TTBXEditItem(Item).FAutoCompleteCounter); + end; + Result := False; +end; + +procedure TTBXEditItemViewer.NewEditWndProc(var Message: TMessage); +begin + if Assigned(OldWndProc) and not HandleEditMessage(Message) then OldWndProc(Message); +end; + +procedure TTBXEditItemViewer.Paint(const Canvas: TCanvas; + const ClientAreaRect: TRect; IsHoverItem, IsPushed, UseDisabledShadow: Boolean); +const + FillColors: array [Boolean] of Integer = (COLOR_BTNFACE, COLOR_WINDOW); + TextColors: array [Boolean] of Integer = (COLOR_GRAYTEXT, COLOR_WINDOWTEXT); + Alignments: array [TAlignment] of Integer = (DT_LEFT, DT_RIGHT, DT_CENTER); +var + DC: HDC; + Item: TTBXEditItem; + S: string; + R, R2: TRect; + M, W: Integer; + ItemInfo: TTBXItemInfo; + EditInfo: TTBXEditInfo; + ImgList: TCustomImageList; + ImgIndex: Integer; + Fnt, OldFnt: HFont; + C, OldColor: TColor; +begin + DC := Canvas.Handle; + Item := TTBXEditItem(Self.Item); + GetItemInfo(ItemInfo, IsHoverItem, IsPushed, UseDisabledShadow); + GetEditInfo(EditInfo, ItemInfo); + R := ClientAreaRect; + + if not IsToolbarStyle then with CurrentTheme do + begin + S := Item.EditCaption; + + if Length(S) > 0 then + begin + { measure EditCaption } + Fnt := TTBXEditItem(Item).FontSettings.CreateTransformedFont(TTBViewAccess(View).GetFont.Handle, C); + OldFnt := SelectObject(DC, Fnt); + W := GetTextWidth(DC, S, True) + MenuImageTextSpace + MenuLeftCaptionMargin + MenuRightCaptionMargin; + SelectObject(DC, OldFnt); + end + else + begin + Fnt := 0; // to suppress compiler warning + W := 0; + end; + + M := GetPopupMargin(Self); + if not EditMenuFullSelect then R.Right := M + W + else Dec(R.Right, EditMenuRightIndent); + PaintMenuItemFrame(Canvas, R, ItemInfo); + Inc(R.Left, M + MenuImageTextSpace); + R.Right := ClientAreaRect.Right - EditMenuRightIndent; + + if Length(S) > 0 then + begin + Inc(R.Left, MenuLeftCaptionMargin); + C := ColorToRGB(GetItemTextColor(ItemInfo)); + OldFnt := SelectObject(DC, Fnt); + OldColor := SetTextColor(DC, C); + PaintCaption(Canvas, R, ItemInfo, S, DT_SINGLELINE or DT_LEFT or DT_VCENTER, False); + SetTextColor(DC, OldColor); + W := GetTextWidth(DC, S, True); + SelectObject(DC, OldFnt); + DeleteObject(Fnt); + Inc(R.Left, W + MenuRightCaptionMargin + MenuImageTextSpace); + end; + end; + + CurrentTheme.PaintEditFrame(Canvas, R, ItemInfo, EditInfo); + W := CurrentTheme.EditFrameWidth; + InflateRect(R, -W - CurrentTheme.EditTextMarginHorz, -W - CurrentTheme.EditTextMarginVert); + + if ShowImage then + begin + ImgList := GetImageList; + if ImgList <> nil then + begin + R2.Left := R.Left; + R2.Right := R.Left + ImgList.Width; + R2.Top := (R.Top + R.Bottom + 1 - ImgList.Height) div 2; + R2.Bottom := R2.Top + ImgList.Height; + ImgIndex := TTBXEditItem(Item).GetImageIndex; + if Item.Enabled then ImgList.Draw(Canvas, R.Left, R2.Top, ImgIndex) + else DrawTBXImage(Canvas, R2, ImgList, ImgIndex, ISF_DISABLED); + end; + end; + Inc(R.Left, EditInfo.LeftBtnWidth); + Dec(R.Right, EditInfo.RightBtnWidth + 1); + + if Item.Text <> '' then + begin + S := Item.Text; + if TTBXEditItem(Item).PasswordChar <> #0 then S := StringOfChar(TTBXEditItem(Item).PasswordChar, Length(S)); + Fnt := Item.EditorFontSettings.CreateTransformedFont(TTBViewAccess(View).GetFont.Handle, C); + OldFnt := SelectObject(DC, Fnt); + SetBkMode(DC, TRANSPARENT); + SetBkColor(DC, GetSysColor(FillColors[Item.Enabled])); + SetTextColor(DC, GetSysColor(TextColors[Item.Enabled])); + DrawText(DC, PChar(S), Length(S), R, DT_SINGLELINE or DT_NOPREFIX or Alignments[Item.Alignment]); + SelectObject(DC, OldFnt); + DeleteObject(Fnt); + end; + +{ if not IsToolbarStyle then + begin + R := ClientAreaRect; + Self.GetEditRect(R); + OffsetRect(R, -BoundsRect.Left, -BoundsRect.Top); + Canvas.FrameRect(R); + end; } +end; + +function TTBXEditItemViewer.GetEditControlClass: TEditClass; +begin + Result := TTBXEdit; +end; + +function TTBXEditItemViewer.ShowImage: Boolean; +begin + Result := TTBXEditItem(Item).ShowImage; +end; + +function TTBXEditItemViewer.IsToolbarSize: Boolean; +begin + Result := inherited IsToolbarSize; + Result := Result or ((GetViewType(View) and PVT_TOOLBOX) = PVT_TOOLBOX); +end; + +function TTBXEditItemViewer.IsToolbarStyle: Boolean; +begin + Result := inherited IsToolbarStyle; + Result := Result or ((GetViewType(View) and PVT_TOOLBOX) = PVT_TOOLBOX); +end; + +function TTBXEditItemViewer.MeasureEditCaption: TSize; +var + DC: HDC; + Fnt, OldFnt: HFont; + DummyColor: TColor; + TextMetric: TTextMetric; + S: string; +begin + Result.cx := 0; + Result.cy := 0; + if Item is TTBXEditItem then + begin + S := StripAccelChars(TTBXEditItem(Item).EditCaption); + if Length(S) > 0 then + begin + DummyColor := clWhite; + DC := GetDC(0); + Fnt := TTBXEditItem(Item).FontSettings.CreateTransformedFont(TTBViewAccess(View).GetFont.Handle, DummyColor); + OldFnt := SelectObject(DC, Fnt); + GetTextExtentPoint32(DC, PChar(S), Length(S), Result); + GetTextMetrics(DC, TextMetric); + Inc(Result.cy, TextMetric.tmExternalLeading); + SelectObject(DC, OldFnt); + DeleteObject(Fnt); + ReleaseDC(0, DC); + end; + end; +end; + +function TTBXEditItemViewer.MeasureTextHeight: Integer; +var + DC: HDC; + Fnt, OldFnt: HFont; + DummyColor: TColor; + TextMetric: TTextMetric; +begin + Result := 0; + if Item is TTBXEditItem then + begin + DummyColor := clWhite; + DC := GetDC(0); + Fnt := TTBXEditItem(Item).EditorFontSettings.CreateTransformedFont(TTBViewAccess(View).GetFont.Handle, DummyColor); + OldFnt := SelectObject(DC, Fnt); + Result := GetTextHeight(DC); + GetTextMetrics(DC, TextMetric); + Inc(Result, TextMetric.tmExternalLeading); + SelectObject(DC, OldFnt); + DeleteObject(Fnt); + ReleaseDC(0, DC); + end; +end; + +function TTBXEditItemViewer.DoExecute: Boolean; +begin + if Item is TTBXEditItem then + begin + TTBXEditItem(Item).FLastEditChange := ''; + Result := inherited DoExecute; + with TTBXEditItem(Item) do + begin + if FLastEditChange <> Text then DoChange(Text); + FLastEditChange := ''; + end; + end + else Result := inherited DoExecute; +end; + + +//============================================================================// + +{ TTBXCustomDropDownItem } + +constructor TTBXCustomDropDownItem.Create(AOwner: TComponent); +begin + inherited; + ItemStyle := ItemStyle + [tbisCombo, tbisSubmenu, tbisSubitemsEditable] - [tbisDontSelectFirst]; + FAlwaysSelectFirst := True; +end; + +function TTBXCustomDropDownItem.CreatePopup(const ParentView: TTBView; + const ParentViewer: TTBItemViewer; const PositionAsSubmenu, + SelectFirstItem, Customizing: Boolean; const APopupPoint: TPoint; + const Alignment: TTBPopupAlignment): TTBPopupWindow; +var + SelectFirst: Boolean; +begin + if AlwaysSelectFirst then SelectFirst := True + else SelectFirst := SelectFirstItem; + Result := inherited CreatePopup(ParentView, ParentViewer, PositionAsSubmenu, + SelectFirst, Customizing, APopupPoint, Alignment); +end; + +function TTBXCustomDropDownItem.GetItemViewerClass(AView: TTBView): TTBItemViewerClass; +begin + if not (tboUseEditWhenVertical in EditOptions) and (AView.Orientation = tbvoVertical) then + Result := TTBXItemViewer + else + Result := TTBXDropDownItemViewer; +end; + + +//----------------------------------------------------------------------------// + +{ TTBXDropDownItemViewer } + +procedure TTBXDropDownItemViewer.GetCursor(const Pt: TPoint; var ACursor: HCURSOR); +begin + if not TTBXCustomDropDownItem(Item).DropDownList then inherited; +end; + +procedure TTBXDropDownItemViewer.GetEditInfo(out EditInfo: TTBXEditInfo; const ItemInfo: TTBXItemInfo); +const + CDisabled: array [Boolean] of Integer = (EBDS_DISABLED, 0); + CHot: array [Boolean] of Integer = (0, EBDS_HOT); + CPressed: array [Boolean] of Integer = (0, EBDS_PRESSED); +begin + inherited GetEditInfo(EditInfo, ItemInfo); + EditInfo.RightBtnInfo.ButtonType := EBT_DROPDOWN; + EditInfo.RightBtnInfo.ButtonState := CDisabled[ItemInfo.Enabled] or + CHot[ItemInfo.HoverKind = hkMouseHover] or CPressed[ItemInfo.Pushed]; +end; + +function TTBXDropDownItemViewer.GetIndentAfter: Integer; +begin + if IsToolbarStyle then Result := CurrentTheme.EditBtnWidth + else Result := GetSystemMetrics(SM_CXMENUCHECK) + 2; +end; + +function TTBXDropDownItemViewer.HandleEditMessage(var Message: TMessage): Boolean; +begin + if Message.Msg = WM_KEYDOWN then + begin + if TWMKeyDown(Message).CharCode = VK_F4 then + begin + {TTBViewAccess(View).OpenChildPopup(True);} {vb-} + if (View.OpenViewer = Self) // WasAlreadyOpen {vb+} + then View.CloseChildPopups + else View.OpenChildPopup(True); + Result := True; + Exit; + end; + end; + + Result := inherited HandleEditMessage(Message); +end; + +function TTBXDropDownItemViewer.IsPtInButtonPart(X, Y: Integer): Boolean; +begin + Result := not (tbisSubmenu in TTBXCustomDropDownItem(Item).ItemStyle); + if TTBXCustomDropDownItem(Item).DropDownList then Result := False + else if (tbisCombo in TTBXCustomDropDownItem(Item).ItemStyle) then + Result := X < (BoundsRect.Right - BoundsRect.Left) - GetIndentAfter; +end; + +procedure TTBXDropDownItemViewer.KeyDown(var Key: Word; Shift: TShiftState); +begin + if not TTBXCustomDropDownItem(Item).DropDownList then inherited; +end; + +//============================================================================// + +{ TTBXComboBoxItem } + +procedure TTBXComboBoxItem.AdjustImageIndex(const AText: string; + AIndex: Integer; var ImageIndex: Integer); +begin + if Assigned(FOnAdjustImageIndex) then FOnAdjustImageIndex(Self, AText, AIndex, ImageIndex); +end; + +procedure TTBXComboBoxItem.AdjustImageIndexHandler(Sender: TTBXCustomList; + AItemIndex: Integer; var ImageIndex: Integer); +begin + AdjustImageIndex(FList.Strings[AItemIndex], AItemIndex, ImageIndex); +end; + +constructor TTBXComboBoxItem.Create(AOwner: TComponent); +begin + inherited; + ItemStyle := ItemStyle - [tbisSubItemsEditable]; + FAutoComplete := True; + FList := GetStringListClass.Create(Self); + FList.OnChange := ListChangeHandler; + FList.OnClick := ListClickHandler; + FList.OnAdjustImageIndex := AdjustImageIndexHandler; + MinListWidth := 64; +end; + +function TTBXComboBoxItem.DoAutoComplete(var AText: string): Boolean; +var + I: Integer; + S, R: string; + TemplateL, MinL, L: Integer; +begin + Result := False; + if Length(AText) > 0 then + begin + { choose the shortest matching string from items } + TemplateL := Length(AText); + MinL := MaxInt; + SetLength(R, 0); + for I := 0 to FList.Strings.Count - 1 do + begin + S := FList.Strings[I]; + L := Length(S); + if (L >= TemplateL) and (L < MinL) and StartsText(AText, S) then + begin + R := S; + MinL := L; + if MinL = TemplateL then Break; + end; + end; + Result := Length(R) > 0; + if Result then AText := R; + end; +end; + +procedure TTBXComboBoxItem.DoListChange; +begin + { Update text in edit item. This will call OnChange automatically } + if (FList.ItemIndex >= 0) and (FList.ItemIndex < FList.Strings.Count) then + begin + IsChanging := True; + try + if Text <> FList.Strings[Flist.ItemIndex] then + begin + SetTextEx(FList.Strings[FList.ItemIndex], tcrList); + end; + finally + IsChanging := False; + end; + end; +end; + +procedure TTBXComboBoxItem.DoListClick; +begin + if Assigned(FOnItemClick) then FOnItemClick(Self); +end; + +procedure TTBXComboBoxItem.DoPopup(Sender: TTBCustomItem; FromLink: Boolean); +begin + inherited; + FList.ItemIndex := FList.Strings.IndexOf(Text); +end; + +function TTBXComboBoxItem.GetImageIndex: Integer; +begin + if not CacheValid then + begin + CachedImageIndex := ImageIndex; + if ItemIndex >= 0 then CachedImageIndex := ItemIndex; + AdjustImageIndex(Text, -1, CachedImageIndex); + CacheValid := True; + end; + Result := CachedImageIndex; +end; + +function TTBXComboBoxItem.GetItemIndex: Integer; +begin + Result := FList.ItemIndex; +end; + +function TTBXComboBoxItem.GetItemViewerClass(AView: TTBView): TTBItemViewerClass; +begin + if not (tboUseEditWhenVertical in EditOptions) and + (AView.Orientation = tbvoVertical) then + Result := TTBXItemViewer + else + Result := TTBXComboBoxItemViewer; +end; + +function TTBXComboBoxItem.GetMaxVisibleItems: Integer; +begin + Result := FList.MaxVisibleItems; +end; + +function TTBXComboBoxItem.GetMaxWidth: Integer; +begin + Result := FList.MaxWidth; +end; + +function TTBXComboBoxItem.GetMinWidth: Integer; +begin + Result := FList.MinWidth; +end; + +function TTBXComboBoxItem.GetOnClearItem: TTBXLPaintEvent; +begin + Result := FList.OnClearItem; +end; + +function TTBXComboBoxItem.GetOnDrawItem: TTBXLPaintEvent; +begin + Result := FList.OnDrawItem; +end; + +function TTBXComboBoxItem.GetOnMeasureHeight: TTBXLMeasureHeight; +begin + Result := FList.OnMeasureHeight; +end; + +function TTBXComboBoxItem.GetOnMeasureWidth: TTBXLMeasureWidth; +begin + Result := FList.OnMeasureWidth; +end; + +function TTBXComboBoxItem.GetShowListImages: Boolean; +begin + Result := FList.ShowImages; +end; + +function TTBXComboBoxItem.GetStringListClass: TTBXStringListClass; +begin + Result := TTBXStringList; +end; + +function TTBXComboBoxItem.GetStrings: TStrings; +begin + Result := FList.Strings; +end; + +procedure TTBXComboBoxItem.HandleEditChange(Edit: TEdit); +begin + CacheValid := False; + inherited; +end; + +procedure TTBXComboBoxItem.ListChangeHandler(Sender: TObject); +begin + CacheValid := False; + DoListChange; +end; + +procedure TTBXComboBoxItem.ListClickHandler(Sender: TObject); +begin + CacheValid := False; + DoListClick; +end; + +procedure TTBXComboBoxItem.Loaded; +begin + inherited; + if FList.Strings.IndexOf(Text) >= 0 then + begin + IsChanging := True; + try + FList.ItemIndex := FList.Strings.IndexOf(Text); + finally + IsChanging := False; + end; + end; + if not (csDesigning in ComponentState) then Add(FList); +end; + +procedure TTBXComboBoxItem.SetItemIndex(Value: Integer); +begin + FList.ItemIndex := Value; +end; + +procedure TTBXComboBoxItem.SetMaxVisibleItems(Value: Integer); +begin + FList.MaxVisibleItems := Value; +end; + +procedure TTBXComboBoxItem.SetMaxWidth(Value: Integer); +begin + FList.MaxWidth := Value; +end; + +procedure TTBXComboBoxItem.SetMinWidth(Value: Integer); +begin + FList.MinWidth := Value; +end; + +procedure TTBXComboBoxItem.SetOnClearItem(Value: TTBXLPaintEvent); +begin + FList.OnClearItem := Value; +end; + +procedure TTBXComboBoxItem.SetOnDrawItem(Value: TTBXLPaintEvent); +begin + FList.OnDrawItem := Value; +end; + +procedure TTBXComboBoxItem.SetOnMeasureHeight(Value: TTBXLMeasureHeight); +begin + FList.OnMeasureHeight := Value; +end; + +procedure TTBXComboBoxItem.SetOnMeasureWidth(Value: TTBXLMeasureWidth); +begin + FList.OnMeasureWidth := Value; +end; + +procedure TTBXComboBoxItem.SetShowListImages(Value: Boolean); +begin + FList.ShowImages := Value; +end; + +procedure TTBXComboBoxItem.SetStrings(Value: TStrings); +begin + FList.Strings := Value; +end; + + +//============================================================================// + +{ TTBXComboBoxItemViewer } + +function TTBXComboBoxItemViewer.HandleEditMessage(var Message: TMessage): Boolean; +begin + if (Message.Msg = WM_KEYDOWN) then with TTBXComboBoxItem(Item) do + begin + case Message.wParam of + VK_UP: + begin + if ItemIndex > 0 then {vb+} + ItemIndex := ItemIndex- 1; + EditControl.Text := Text; + EditControl.SelectAll; + Result := True; + end; + + VK_DOWN: + begin + if ItemIndex < Strings.Count- 1 then {vb+} + ItemIndex := ItemIndex+ 1; + EditControl.Text := Text; + EditControl.SelectAll; + Result := True; + end; + else + Result := inherited HandleEditMessage(Message); + end + end + else Result := inherited HandleEditMessage(Message); +end; + + +//============================================================================// + +{ TTBXLabelItem } + +constructor TTBXLabelItem.Create(AOwner: TComponent); +begin + inherited; + FFontSettings := TFontSettings.Create; + TFontSettingsAccess(FFontSettings).OnChange := FontSettingsChanged; + FShowAccelChar := True; + ItemStyle := ItemStyle - [tbisSelectable] + [tbisClicksTransparent, tbisStretch]; +end; + +destructor TTBXLabelItem.Destroy; +begin + FFontSettings.Free; + inherited; +end; + +procedure TTBXLabelItem.FontSettingsChanged(Sender: TObject); +begin + Change(True); +end; + +function TTBXLabelItem.GetItemViewerClass(AView: TTBView): TTBItemViewerClass; +begin + Result := TTBXLabelItemViewer; +end; + +procedure TTBXLabelItem.SetCaption(const Value: TCaption); +begin + FCaption := Value; + Change(True); +end; + +procedure TTBXLabelItem.SetFontSettings(Value: TFontSettings); +begin + FFontSettings := Value; +end; + +{procedure TTBXLabelItem.SetFontSize(Value: TTBXFontSize); +begin + FFontSize := Value; + Change(True); +end; } + +procedure TTBXLabelItem.SetMargin(Value: Integer); +begin + FMargin := Value; + Change(True); +end; + +procedure TTBXLabelItem.SetOrientation(Value: TTBXLabelOrientation); +begin + FOrientation := Value; + Change(True); +end; + +procedure TTBXLabelItem.SetShowAccelChar(Value: Boolean); +begin + FShowAccelChar := Value; + Change(True); +end; + +procedure TTBXLabelItem.UpdateCaption(const Value: TCaption); +begin + FCaption := Value; + Change(False); +end; + + +//============================================================================// + +{ TTBXLabelItemViewer } + +procedure TTBXLabelItemViewer.CalcSize(const Canvas: TCanvas; var AWidth, AHeight: Integer); +var + DC: HDC; + S: string; + TextMetrics: TTextMetric; + RotatedFont, SaveFont: HFont; +begin + Canvas.Font := TTBViewAccess(View).GetFont; + DoAdjustFont(Canvas.Font, 0); + S := GetCaptionText; + if Length(S) = 0 then S := '0'; + DC := Canvas.Handle; + if IsToolbarStyle then + begin + AWidth := TTBXLabelItem(Item).Margin; + AHeight := AWidth; + if Length(S) > 0 then + begin + if GetIsHoriz then + begin + GetTextMetrics(DC, TextMetrics); + Inc(AHeight, TextMetrics.tmHeight); + Inc(AWidth, GetTextWidth(DC, S, TTBXLabelItem(Item).ShowAccelChar)); + end + else + begin + RotatedFont := CreateRotatedFont(DC); + SaveFont := SelectObject(DC, RotatedFont); + GetTextMetrics(DC, TextMetrics); + Inc(AWidth, TextMetrics.tmHeight); + Inc(AHeight, GetTextWidth(DC, S, TTBXLabelItem(Item).ShowAccelChar)); + SelectObject(DC, SaveFont); + DeleteObject(RotatedFont); + end; + end; + end + else + begin + if Length(S) > 0 then + begin + GetTextMetrics(DC, TextMetrics); + AHeight := TextMetrics.tmHeight; + AWidth := GetTextWidth(DC, S, TTBXLabelItem(Item).ShowAccelChar); + end; + end; + + if AWidth < 6 then AWidth := 6; + if AHeight < 6 then AHeight := 6; + with TTBXLabelItem(Item) do + begin + Inc(AWidth, Margin shl 1 + 1); + Inc(AHeight, Margin shl 1 + 1); + end; +end; + +procedure TTBXLabelItemViewer.DoAdjustFont(AFont: TFont; StateFlags: Integer); +begin + if Item is TTBXLabelItem then + with TTBXLabelItem(Item) do + begin + FontSettings.Apply(AFont); + if Assigned(FOnAdjustFont) then FOnAdjustFont(Item, Self, AFont, StateFlags); + end; +end; + +function TTBXLabelItemViewer.GetCaptionText: string; +var + P: Integer; +begin + Result := TTBXLabelItem(Item).Caption; + P := Pos(#9, Result); + if P <> 0 then SetLength(Result, P - 1); +end; + +function TTBXLabelItemViewer.GetIsHoriz: Boolean; +begin + with TTBXLabelItem(Item) do + case Orientation of + tbxoHorizontal: Result := True; + tbxoVertical: Result := False; + else // tbxoAuto + Result := View.Orientation <> tbvoVertical; + end; +end; + +function TTBXLabelItemViewer.IsToolbarSize: Boolean; +begin + Result := inherited IsToolbarSize; + Result := Result or ((GetViewType(View) and PVT_TOOLBOX) = PVT_TOOLBOX); +end; + +function TTBXLabelItemViewer.IsToolbarStyle: Boolean; +begin + Result := inherited IsToolbarStyle; + Result := Result or ((GetViewType(View) and PVT_TOOLBOX) = PVT_TOOLBOX); +end; + +procedure TTBXLabelItemViewer.Paint(const Canvas: TCanvas; + const ClientAreaRect: TRect; IsHoverItem, IsPushed, UseDisabledShadow: Boolean); +const + CEnabledStates: array [Boolean] of Integer = (ISF_DISABLED, 0); + CDesigning: array [Boolean] of Integer = (0, IO_DESIGNING); + CPrefixes: array [Boolean] of Integer = (DT_NOPREFIX, 0); +var + Fmt: Cardinal; + ItemInfo: TTBXItemInfo; + R: TRect; +begin + FillChar(ItemInfo, SizeOf(ItemInfo), 0); + ItemInfo.ViewType := GetViewType(View); + ItemInfo.ItemOptions := IO_TOOLBARSTYLE or CDesigning[csDesigning in Item.ComponentState]; + ItemInfo.Enabled := Item.Enabled or View.Customizing; + ItemInfo.Pushed := False; + ItemInfo.Selected := False; + ItemInfo.ImageShown := False; + ItemInfo.ImageWidth := 0; + ItemInfo.ImageHeight := 0; + ItemInfo.HoverKind := hkNone; + ItemInfo.IsPopupParent := False; + ItemInfo.IsVertical := not GetIsHoriz; + + Canvas.Font := TTBViewAccess(View).GetFont; + Canvas.Font.Color := CurrentTheme.GetItemTextColor(ItemInfo); + DoAdjustFont(Canvas.Font, CEnabledStates[ItemInfo.Enabled]); + Canvas.Brush.Style := bsClear; + Fmt := DT_SINGLELINE or DT_CENTER or DT_VCENTER or CPrefixes[TTBXLabelItem(Item).ShowAccelChar]; + R := ClientAreaRect; + CurrentTheme.PaintCaption(Canvas, R, ItemInfo, GetCaptionText, Fmt, ItemInfo.IsVertical); + Canvas.Brush.Style := bsSolid; +end; + + +//============================================================================// + +{ TTBXColorItem } + +constructor TTBXColorItem.Create(AOwner: TComponent); +begin + inherited; + FColor := clWhite; +end; + +function TTBXColorItem.GetItemViewerClass(AView: TTBView): TTBItemViewerClass; +begin + Result := TTBXColorItemViewer; +end; + +procedure TTBXColorItem.SetColor(Value: TColor); +begin + if FColor <> Value then + begin + FColor := Value; + Change(False); + end; +end; + + +//============================================================================// + +{ TTBXColorItemViewer } + +procedure TTBXColorItemViewer.DrawItemImage(Canvas: TCanvas; ARect: TRect; ItemInfo: TTBXItemInfo); +begin + with ItemInfo, Canvas do if Enabled then + begin + if ((ItemOptions and IO_TOOLBARSTYLE) = 0) then InflateRect(ARect, -2, -2); + if TTBXColorItem(Item).Color <> clNone then + begin + Brush.Color := clBtnShadow; + FrameRect(ARect); + InflateRect(ARect, -1, -1); + Brush.Color := TTBXColorItem(Item).Color; + FillRect(ARect); + end; + end + else + begin + Inc(ARect.Right); + Inc(ARect.Bottom); + DrawEdge(Handle, ARect, BDR_SUNKENOUTER or BDR_RAISEDINNER, BF_RECT); + end; +end; + +procedure TTBXColorItemViewer.DoPaintCaption(Canvas: TCanvas; + const ClientAreaRect: TRect; var CaptionRect: TRect; + IsTextRotated: Boolean; var PaintDefault: Boolean); +begin + if (GetViewType(View) and PVT_TOOLBOX) = PVT_TOOLBOX then + begin + { Center Caption } + OffsetRect(CaptionRect, -CaptionRect.Left, 0); + OffsetRect(CaptionRect, (ClientAreaRect.Right - CaptionRect.Right) div 2, 0); + end; +end; + +function TTBXColorItemViewer.GetImageSize: TSize; +begin + if IsToolbarStyle then + begin + Result.CX := 12; + Result.CY := 12; + end + else + begin + Result.CX := 16; + Result.CY := 16; + end; +end; + +function TTBXColorItemViewer.GetImageShown: Boolean; +begin + Result := ((Item.DisplayMode in [nbdmDefault, nbdmImageAndText]) or + (IsToolbarStyle and (Item.DisplayMode = nbdmTextOnlyInMenus))); +end; + +constructor TTBXColorItemViewer.Create(AView: TTBView; AItem: TTBCustomItem; AGroupLevel: Integer); +begin + inherited; + Wide := False; +end; + +//============================================================================// + +{ TTBXMRUList } + +function TTBXMRUList.GetFirstKey:Integer; +begin + Result := FKeyShift; +end; + +function TTBXMRUList.GetItemClass: TTBCustomItemClass; +begin + Result := TTBXCustomItem; +end; + +procedure TTBXMRUList.SetItemCaptions; +var + I: Integer; +begin + inherited; + if Container is TTBXCustomItem then + for I := 0 to Items.Count - 1 do + TTBXCustomItem(Items[I]).FontSettings := TTBXCustomItem(Container).FontSettings; +end; + +procedure TTBXMRUList.SetKeyShift(Value: Integer); +begin + if Value < 0 then Value := 0; + FKeyShift := Value; + SetItemCaptions; +end; + + +//============================================================================// + +{ TTBXMRUListItem } + +constructor TTBXMRUListItem.Create(AOwner: TComponent); +begin + inherited; + ItemStyle := ItemStyle + [tbisEmbeddedGroup]; + Caption := STBMRUListItemDefCaption[1] + 'TBX ' + + Copy(STBMRUListItemDefCaption, 2, Length(STBMRUListItemDefCaption) - 1); +end; + +procedure TTBXMRUListItem.Notification(AComponent: TComponent; + Operation: TOperation); +begin + inherited; + if (AComponent = FMRUList) and (Operation = opRemove) then MRUList := nil; +end; + +procedure TTBXMRUListItem.SetMRUList(Value: TTBMRUList); +begin + if FMRUList <> Value then + begin + FMRUList := Value; + if Assigned(Value) then + begin + Value.FreeNotification(Self); + LinkSubitems := TTBMRUListAccess(Value).Container; + end + else LinkSubitems := nil; + end; +end; + +{ TTBXCustomSpinEditItem } + +function TTBXCustomSpinEditItem.CheckValue(const V: Extended): Extended; +begin + Result := V; + if FMaxValue <> FMinValue then + begin + if V < FMinValue then Result := FMinValue + else if V > FMaxValue then Result := FMaxValue; + end; +end; + +procedure TTBXCustomSpinEditItem.ClickDown; +var + OldValue, NewValue: Extended; +begin + OldValue := GetValue; + if Snap then + NewValue := Ceil(OldValue / Increment - 1 - Increment * 0.0001) * Increment + else + NewValue := OldValue - FIncrement; + DoStep(-1, OldValue, NewValue); + SetValueEx(NewValue, tcrSpinButton); +end; + +procedure TTBXCustomSpinEditItem.ClickUp; +var + OldValue, NewValue: Extended; +begin + OldValue := GetValue; + if Snap then + NewValue := Floor(OldValue / Increment + 1 + Increment * 0.0001) * Increment + else + NewValue := OldValue + FIncrement; + DoStep(+1, OldValue, NewValue); + SetValueEx(NewValue, tcrSpinButton); +end; + +constructor TTBXCustomSpinEditItem.Create(AOwner: TComponent); +begin + inherited; + FAlignment := taRightJustify; + FDecimal := 2; + FIncrement := 1; + FSnap := True; + Text := '0'; +end; + +function TTBXCustomSpinEditItem.DoAcceptText(var NewText: string): Boolean; +var + V: Extended; +begin + if ParseValue(NewText, V) then + begin + NewText := GetAsText(V); + Result := True; + end + else Result := False; +end; + +function TTBXCustomSpinEditItem.DoConvert(const APrefix, APostfix: string; var AValue: Extended): Boolean; +begin + Result := True; + if Assigned(FOnConvert) then FOnConvert(Self, APrefix, APostfix, AValue, Result); +end; + +procedure TTBXCustomSpinEditItem.DoStep(Step: Integer; const OldValue: Extended; var NewValue: Extended); +begin + if Assigned(FOnStep) then FOnStep(Self, Step, OldValue, NewValue); +end; + +procedure TTBXCustomSpinEditItem.DoTextChanged(Reason: Integer); +begin + if Reason = tcrEditControl then + SetValueEx(GetValue, tcrNumericProperty); +end; + +function TTBXCustomSpinEditItem.DoTextToValue(const AText: string; out AValue: Extended): Boolean; +begin + Result := False; + if Assigned(FOnTextToValue) then FOnTextToValue(Self, AText, AValue, Result); +end; + +procedure TTBXCustomSpinEditItem.DoValueChange(const V: Extended); +begin + if Assigned(FOnValueChange) then FOnValueChange(Self, V); +end; + +procedure TTBXCustomSpinEditItem.DoValueToText(const NewValue: Extended; var NewText: string); +begin + if Assigned(FOnValueToText) then FOnValueToText(Self, NewValue, NewText); +end; + +function TTBXCustomSpinEditItem.GetAsInteger: Integer; +begin + Result := Round(Value); +end; + +function TTBXCustomSpinEditItem.GetAsText(AValue: Extended): string; +begin + AValue := CheckValue(AValue); + if ValueType = evtFloat then Result := FloatToStrF(AValue, ffFixed, 15, FDecimal) + else if ValueType = evtHex then Result := IntToHex(Round(AValue), 1) + else Result := IntToStr(Round(AValue)); + + if Length(Prefix) > 0 then + begin + if SpaceAfterPrefix then Result := ' ' + Result; + Result := Prefix + Result; + end; + if Length(Postfix) > 0 then + begin + if SpaceBeforePostfix then Result := Result + ' '; + Result := Result + Postfix; + end; + DoValueToText(AValue, Result); +end; + +function TTBXCustomSpinEditItem.GetItemViewerClass(AView: TTBView): TTBItemViewerClass; +begin + if not (tboUseEditWhenVertical in EditOptions) and + (AView.Orientation = tbvoVertical) then + Result := TTBXItemViewer + else + Result := TTBXSpinEditViewer; +end; + +function TTBXCustomSpinEditItem.GetValue: Extended; +begin + if not ParseValue(Text, Result) then + Result := FLastGoodValue; +end; + +function TTBXCustomSpinEditItem.IsIncrementStored: Boolean; +begin + Result := FIncrement <> 1; +end; + +function TTBXCustomSpinEditItem.IsMaxValueStored: Boolean; +begin + Result := FMaxValue <> 0; +end; + +function TTBXCustomSpinEditItem.IsMinValueStored: Boolean; +begin + Result := FMinValue <> 0; +end; + +function TTBXCustomSpinEditItem.IsValueStored: Boolean; +begin + Result := GetValue <> 0; +end; + +function TTBXCustomSpinEditItem.ParseValue(const S: string; out V: Extended): Boolean; +const + CWhiteSpace = [' ', #9]; + CDigits = ['0'..'9']; + CHexDigits = CDigits + ['A'..'F']; + CInvalidUnitChars = [#0..#31, ' ', '*', '+', ',', '-', '.', '/', '0'..'9', '^']; + CInvalidHexUnitChars = CInvalidUnitChars + ['A'..'F']; +var + P: PChar; + Sign1: Integer; + Value1: Extended; + Value2: Extended; + Operator: Char; + PrefixString, PostfixString: string; + + procedure SkipWhiteSpace; + begin + while P^ in CWhiteSpace do Inc(P); + end; + + function GetInt: Integer; + begin + Result := 0; + while P^ in CDigits do + begin + Result := Result * 10 + (Integer(P^) - Integer('0')); + Inc(P); + end; + end; + + function GetInt2: Extended; + begin + Result := 0; + while P^ in CDigits do + begin + Result := Result * 10 + (Integer(P^) - Integer('0')); + Inc(P); + end; + end; + + function GetNumber(out PrefixString, PostfixString: string; out R: Extended): Boolean; + var + PStart: PChar; + Tmp: Integer; + ExponentSign, IR: Integer; + Count1, Count2: Integer; + E: Extended; + begin + R := 0; + Result := False; + + { Read prefix } + PStart := P; + if ValueType <> evtHex then while not (P^ in CInvalidUnitChars) do Inc(P) + else while not (P^ in CInvalidHexUnitChars) do Inc(P); + SetString(PrefixString, PStart, P - PStart); + SkipWhiteSpace; + + { Read value } + if ValueType in [evtFloat, evtInteger] then + begin + if (ValueType = evtInteger) and not (P^ in CDigits) then Exit; + + { get the integer part } + PStart := P; + R := GetInt2; + Count1 := P - PStart; + + if (ValueType = evtFloat) and (P^ = DecimalSeparator) then + begin + Inc(P); + PStart := P; + E := GetInt2; + R := R + E / IntPower(10, P - PStart); + Count2 := P - PStart; + end + else Count2 := 0; + + if (Count1 = 0) and (Count2 = 0) then Exit; // '.' (or ',') is not a number + + if (ValueType = evtFloat) and (P^ in ['e', 'E']) and (PChar(P + 1)^ in ['+', '-', '0'..'9']) then + begin + Inc(P); + ExponentSign := 1; + if P^ = '-' then + begin + ExponentSign := -1; + Inc(P); + end + else if P^ = '+' then Inc(P); + if not (P^ in CDigits) then Exit; + Tmp := GetInt; + if Tmp >= 5000 then Exit; + R := R * IntPower(10, Tmp * ExponentSign); + end; + end + else { evtHex } + begin + IR := 0; + if not (P^ in CHexDigits) then Exit; + while P^ in CHexDigits do + begin + IR := IR shl 4; + if P^ in CDigits then Inc(IR, Integer(P^) - Integer('0')) + else if P^ in ['a'..'f'] then Inc(IR, Integer(P^) - Integer('a') + 10) + else Inc(IR, Integer(P^) - Integer('A') + 10); + Inc(P); + end; + R := IR; + end; + SkipWhiteSpace; + + { Read postfix } + PStart := P; + if ValueType <> evtHex then while not (P^ in CInvalidUnitChars) do Inc(P) + else while not (P^ in CInvalidHexUnitChars) do Inc(P); + SetString(PostfixString, PStart, P - PStart); + SkipWhiteSpace; + + Result := True; + end; + +begin + V := 0; + + { Try text-to-value conversion for predefined "constants" } + Result := DoTextToValue(S, V); + if Result then Exit; + + { Parse the string for values and expressions } + if Length(S) = 0 then Exit; + P := PChar(S); + SkipWhiteSpace; + + { Read the sign } + Sign1 := 1; + if P^ = '-' then + begin + Sign1 := -1; + Inc(P); + SkipWhiteSpace; + end + else if P^ = '+' then + begin + Inc(P); + SkipWhiteSpace; + end; + + { Read value } + if not GetNumber(PrefixString, PostfixString, Value1) then Exit; + if not DoConvert(PrefixString, PostfixString, Value1) then Exit; + Value1 := Value1 * Sign1; + V := Value1; + + { Read operator } + if P^ in ['*', '+', '-', '/'] then + begin + Operator := P^; + Inc(P); + SkipWhiteSpace; + if not GetNumber(PrefixString, PostfixString, Value2) then Exit; + if not DoConvert(PrefixString, PostfixString, Value2) then Exit; + case Operator of + '*': V := V * Value2; + '+': V := V + Value2; + '-': V := V - Value2; + '/': if Value2 <> 0 then V := V / Value2 else Exit; + end; + end; + + if P^ = #0 then Result := True; +end; + +procedure TTBXCustomSpinEditItem.SetAsInteger(AValue: Integer); +begin + Value := AValue; +end; + +procedure TTBXCustomSpinEditItem.SetDecimal(NewDecimal: TDecimal); +begin + if NewDecimal <> FDecimal then + begin + FDecimal := NewDecimal; + SetValueEx(GetValue, tcrNumericProperty); + end; +end; + +procedure TTBXCustomSpinEditItem.SetIncrement(const NewIncrement: Extended); +begin + if NewIncrement <= 0 then + raise EPropertyError.Create('Increment should be a positive value'); + FIncrement := NewIncrement; +end; + +procedure TTBXCustomSpinEditItem.SetPostfix(const NewPostfix: string); +begin + if not ValidateUnits(NewPostfix) then + raise EPropertyError.Create('Invalid postfix'); + FPostfix := NewPostfix; + SetValueEx(GetValue, tcrNumericProperty); +end; + +procedure TTBXCustomSpinEditItem.SetPrefix(const NewPrefix: string); +begin + if not ValidateUnits(NewPrefix) then + raise EPropertyError.Create('Invalid prefix'); + FPrefix := NewPrefix; + SetValueEx(GetValue, tcrNumericProperty); +end; + +procedure TTBXCustomSpinEditItem.SetSpaceAfterPrefix(UseSpace: Boolean); +begin + FSpaceAfterPrefix := UseSpace; + SetValueEx(GetValue, tcrNumericProperty); +end; + +procedure TTBXCustomSpinEditItem.SetSpaceBeforePostfix(UseSpace: Boolean); +begin + FSpaceBeforePostfix := UseSpace; + SetValueEx(GetValue, tcrNumericProperty); +end; + +procedure TTBXCustomSpinEditItem.SetValue(NewValue: Extended); +begin + SetTextEx(GetAsText(NewValue), tcrNumericProperty); + if FLastGoodValue <> NewValue then + begin + FLastGoodValue := NewValue; + DoValueChange(NewValue); + end; +end; + +procedure TTBXCustomSpinEditItem.SetValueEx(NewValue: Extended; Reason: Integer); +begin + SetTextEx(GetAsText(NewValue), Reason); + if FLastGoodValue <> NewValue then + begin + FLastGoodValue := NewValue; + DoValueChange(NewValue); + end; +end; + +procedure TTBXCustomSpinEditItem.SetValueType(NewType: TSEValueType); +var + V: Extended; +begin + if NewType <> FValueType then + begin + V := GetValue; + FValueType := NewType; + SetValueEx(V, tcrNumericProperty); + if NewType in [evtInteger, evtHex] then FIncrement := Max(Round(FIncrement), 1); + end; +end; + +function TTBXCustomSpinEditItem.ValidateUnits(const S: string): Boolean; +const + InvalidChars = [#0..#31, ' ', '*', '+', ',', '-', '.', '/', '0'..'9', '^']; +var + I: Integer; +begin + Result := False; + if Length(S) > 0 then + for I := 1 to Length(S) do + if S[I] in InvalidChars then Exit; + Result := True; +end; + +{ TTBXSpinEditViewer } + +destructor TTBXSpinEditViewer.Destroy; +begin + FBtnTimer.Free; + inherited; +end; + +procedure TTBXSpinEditViewer.GetEditInfo(out EditInfo: TTBXEditInfo; const ItemInfo: TTBXItemInfo); +const + CDisabled: array [Boolean] of Integer = (EBSS_DISABLED, 0); + CHot: array [Boolean] of Integer = (0, EBSS_HOT); + CUpDnState: array [TSEBtnState] of Integer = (0, EBSS_UP, EBSS_DOWN); +begin + inherited GetEditInfo(EditInfo, ItemInfo); + EditInfo.RightBtnInfo.ButtonType := EBT_SPIN; + EditInfo.RightBtnInfo.ButtonState := CDisabled[ItemInfo.Enabled] or + CHot[ItemInfo.HoverKind = hkMouseHover] or CUpDnState[FBtnState]; +end; + +function TTBXSpinEditViewer.GetIndentAfter: Integer; +begin + if IsToolbarStyle then Result := CurrentTheme.EditBtnWidth + 2 + else Result := GetSystemMetrics(SM_CXMENUCHECK) + 2; +end; + +function TTBXSpinEditViewer.HandleEditMessage(var Message: TMessage): Boolean; +var + Item: TTBXCustomSpinEditItem; + + function Val: Extended; + begin + if not Item.ParseValue(EditControl.Text, Result) then Result := Item.FLastGoodValue; + end; + +begin + Item := TTBXCustomSpinEditItem(Self.Item); + if Message.Msg = WM_CHAR then + case TWMChar(Message).CharCode of + VK_TAB: + begin + Item.Value := Val; + EditControl.Text := Item.Text; + end; + VK_RETURN: + begin + Item.Value := Val; + EditControl.Text := Item.Text; + end; + VK_ESCAPE: + begin +// Item.Value := Item.GetValue; + end; + end + else if Message.Msg = WM_KEYDOWN then + case TWMKeyDown(Message).CharCode of + VK_UP: + begin + Item.ClickUp; + EditControl.Text := Item.Text; + EditControl.SelectAll; + Result := True; + Exit; + end; + VK_DOWN: + begin + Item.ClickDown; + EditControl.Text := Item.Text; + EditControl.SelectAll; + Result := True; + Exit; + end; + end; + + Result := inherited HandleEditMessage(Message); +end; + +procedure TTBXSpinEditViewer.InvalidateButtons; +var + R: TRect; +begin + with TTBXSpinEditItem(Item) do + if Show and not IsRectEmpty(BoundsRect) then + begin + R := BoundsRect; + R.Left := R.Right - GetIndentAfter; + InvalidateRect(View.Window.Handle, @R, False); + Include(State, tbisInvalidated); + end; +end; + +function TTBXSpinEditViewer.IsPtInButtonPart(X, Y: Integer): Boolean; +begin + Result := X <= (BoundsRect.Right - BoundsRect.Left) - GetIndentAfter; +end; + +procedure TTBXSpinEditViewer.LosingCapture; +begin + FBtnTimer.Free; + FBtnTimer := nil; + inherited; +end; + +procedure TTBXSpinEditViewer.MouseDown(Shift: TShiftState; X, Y: Integer; var MouseDownOnMenu: Boolean); +begin + if not Item.Enabled then Exit; + FBtnState := ebsNone; + if X >= BoundsRect.Right - BoundsRect.Left - GetIndentAfter then + begin + if Y < (BoundsRect.Bottom - BoundsRect.Top) div 2 then + begin + FBtnState := ebsUp; + TTBXSpinEditItem(Item).ClickUp; + end + else + begin + FBtnState := ebsDown; + TTBXSpinEditItem(Item).ClickDown; + end; + + if FBtnTimer = nil then + begin + FBtnTimer := TTimer.Create(nil); + FBtnTimer.OnTimer := TimerHandler; + end; + FBtnTimer.Interval := SE_FIRSTINTERVAL; + FBtnTimer.Enabled := True; + end; + + if FBtnState <> ebsNone then + begin + InvalidateButtons; + inherited; + View.SetCapture; + end + else inherited; +end; + +procedure TTBXSpinEditViewer.MouseUp(X, Y: Integer; MouseWasDownOnMenu: Boolean); +begin + if FBtnState <> ebsNone then + begin + FBtnState := ebsNone; + FBtnTimer.Free; + FBtnTimer := nil; + InvalidateButtons; + end; + inherited; +end; + +procedure TTBXSpinEditViewer.TimerHandler(Sender: TObject); +begin + FBtnTimer.Interval := SE_INTERVAL; + if FBtnState = ebsUp then TTBXSpinEditItem(Item).ClickUp + else if FBtnState = ebsDown then TTBXSpinEditItem(Item).ClickDown + else + begin + FBtnTimer.Free; + FBtnTimer := nil; + end; +end; + +end. diff --git a/official/2.1.6+2.1.beta1/TBX/TBXExtItems.pas.orig b/official/2.1.6+2.1.beta1/TBX/TBXExtItems.pas.orig new file mode 100644 index 0000000..5e1f2d0 --- /dev/null +++ b/official/2.1.6+2.1.beta1/TBX/TBXExtItems.pas.orig @@ -0,0 +1,2370 @@ +unit TBXExtItems; + +// TBX Package +// Copyright 2001-2004 Alex A. Denisov. All Rights Reserved +// See TBX.chm for license and installation instructions +// +// $Id: TBXExtItems.pas 16 2004-05-26 02:02:55Z Alex@ZEISS $ + +interface + +{$I TB2Ver.inc} +{$I TBX.inc} + +{$DEFINE COMPATIBLE} + +uses + Windows, Messages, Classes, SysUtils, Graphics, Controls, StdCtrls, ExtCtrls, + TBX, TBXThemes, TB2Item, TB2Toolbar, TB2ExtItems, TBXLists, TB2MRU; + +const + tcrNumericProperty = 3; + tcrSpinButton = 4; + tcrList = 5; + +type + TTBXEditItemViewer = class; + TTBXEditChange = procedure(Sender: TObject; const Text: string) of object; + + { TTBXEditItem } + { Extends standard TTBEditItem, providing additional features and some + combo box functionality, which is used in descendants } + + TTBXEditItem = class(TTBEditItem) + private + FAlignment: TAlignment; + FAutoCompleteCounter: Integer; + FEditorFontSettings: TFontSettings; + FFontSettings: TFontSettings; + FIsChanging: Boolean; + FLastEditChange: string; + FPasswordChar: Char; + FReadOnly: Boolean; + FShowImage: Boolean; + FOnChange: TTBXEditChange; + procedure FontSettingsChanged(Sender: TObject); + procedure SetAlignment(Value: TAlignment); + procedure SetPasswordChar(Value: Char); + procedure SetShowImage(const Value: Boolean); + procedure SetFontSettings(Value: TFontSettings); + protected + function DoAcceptText(var NewText: string): Boolean; override; + function DoAutoComplete(var AText: string): Boolean; virtual; + procedure DoBeginEdit(Viewer: TTBEditItemViewer); override; + procedure DoChange(const AText: string); virtual; + procedure DoTextChanged(Reason: Integer); override; + function GetImageIndex: Integer; virtual; + function GetItemViewerClass(AView: TTBView): TTBItemViewerClass; override; + procedure GetPopupPosition(ParentView: TTBView; PopupWindow: TTBPopupWindow; var PopupPositionRec: TTBPopupPositionRec); override; + function GetPopupWindowClass: TTBPopupWindowClass; override; + procedure HandleEditChange(Edit: TEdit); virtual; + public + function StartEditing(AView: TTBView): Boolean; + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + published + property Alignment: TAlignment read FAlignment write SetAlignment default taLeftJustify; + property EditorFontSettings: TFontSettings read FEditorFontSettings write FEditorFontSettings; + property ExtendedAccept; + property FontSettings: TFontSettings read FFontSettings write SetFontSettings; + property ImageIndex; + property Images; + property PasswordChar: Char read FPasswordChar write SetPasswordChar default #0; + property ReadOnly: Boolean read FReadOnly write FReadOnly default False; + property ShowImage: Boolean read FShowImage write SetShowImage default False; + property OnChange: TTBXEditChange read FOnChange write FOnChange; + property OnSelect; + end; + + TTBXEditItemViewer = class(TTBEditItemViewer) + private + procedure EditChangeHandler(Sender: TObject); + function MeasureEditCaption: TSize; + function MeasureTextHeight: Integer; + procedure HandleEditChange(Edit: TEdit); + protected + OldWndProc: TWndMethod; + procedure CalcSize(const Canvas: TCanvas; var AWidth, AHeight: Integer); override; + function DoExecute: Boolean; override; + function HandleEditMessage(var Message: TMessage): Boolean; virtual; + function GetAccRole: Integer; override; + procedure GetItemInfo(out ItemInfo: TTBXItemInfo; IsHoverItem, IsPushed, UseMenuColor: Boolean); virtual; + function GetEditControlClass: TEditClass; override; + procedure GetEditInfo(out EditInfo: TTBXEditInfo; const ItemInfo: TTBXItemInfo); virtual; + function GetIndentBefore: Integer; virtual; + function GetIndentAfter: Integer; virtual; + procedure GetEditRect(var R: TRect); override; + function IsToolbarSize: Boolean; override; + procedure NewEditWndProc(var Message: TMessage); + procedure Paint(const Canvas: TCanvas; const ClientAreaRect: TRect; IsHoverItem, IsPushed, UseDisabledShadow: Boolean); override; + function ShowImage: Boolean; virtual; + public + function IsToolbarStyle: Boolean; override; + end; + + { TTBXSpinEditItem } + TTBXCustomSpinEditItem = class; + + TSEValueType = (evtInteger, evtFloat, evtHex); + TDecimal = 0..10; + TSEChangeEvent = procedure(Sender: TTBXCustomSpinEditItem; const AValue: Extended) of object; + TSEConvertEvent = procedure(Sender: TTBXCustomSpinEditItem; const APrefix, APostfix: string; var AValue: Extended; var CanConvert: Boolean) of object; + TSEStepEvent = procedure(Sender: TTBXCustomSpinEditItem; Step: Integer; const OldValue: Extended; var NewValue: Extended) of object; + TSETextToValueEvent = procedure(Sender: TTBXCustomSpinEditItem; const AText: string; out AValue: Extended; var CanConvert: Boolean) of object; + TSEValueToTextEvent = procedure(Sender: TTBXCustomSpinEditItem; const AValue: Extended; var Text: string) of object; + + TTBXCustomSpinEditItem = class(TTBXEditItem) + private + FDecimal: TDecimal; + FLastGoodValue: Extended; + FMaxValue: Extended; + FMinValue: Extended; + FIncrement: Extended; + FSpaceBeforePostfix: Boolean; + FSpaceAfterPrefix: Boolean; + FPostfix: string; + FPrefix: string; + FSnap: Boolean; + FValueType: TSEValueType; + FOnConvert: TSEConvertEvent; + FOnTextToValue: TSETextToValueEvent; + FOnValueChange: TSEChangeEvent; + FOnValueToText: TSEValueToTextEvent; + FOnStep: TSEStepEvent; + function IsIncrementStored: Boolean; + function IsMinValueStored: Boolean; + function IsMaxValueStored: Boolean; + function IsValueStored: Boolean; + function GetValue: Extended; + procedure SetValue(NewValue: Extended); + procedure SetValueType(NewType: TSEValueType); + procedure SetDecimal(NewDecimal: TDecimal); + procedure SetIncrement(const NewIncrement: Extended); + procedure SetPostfix(const NewPostfix: string); + procedure SetPrefix(const NewPrefix: string); + procedure SetSpaceAfterPrefix(UseSpace: Boolean); + procedure SetSpaceBeforePostfix(UseSpace: Boolean); + function ValidateUnits(const S: string): Boolean; + function GetAsInteger: Integer; + procedure SetAsInteger(AValue: Integer); + protected + function CheckValue(const V: Extended): Extended; + procedure ClickUp; + procedure ClickDown; + function DoAcceptText(var NewText: string): Boolean; override; + function DoConvert(const APrefix, APostfix: string; var AValue: Extended): Boolean; virtual; + procedure DoStep(Step: Integer; const OldValue: Extended; var NewValue: Extended); virtual; + procedure DoTextChanged(Reason: Integer); override; + function DoTextToValue(const AText: string; out AValue: Extended): Boolean; virtual; + procedure DoValueChange(const V: Extended); virtual; + procedure DoValueToText(const NewValue: Extended; var NewText: string); virtual; + function GetAsText(AValue: Extended): string; + function GetItemViewerClass(AView: TTBView): TTBItemViewerClass; override; + function ParseValue(const S: string; out V: Extended): Boolean; + procedure SetValueEx(NewValue: Extended; Reason: Integer); + property Alignment default taRightJustify; + property OnConvert: TSEConvertEvent read FOnConvert write FOnConvert; + property OnStep: TSEStepEvent read FOnStep write FOnStep; + property OnTextToValue: TSETextToValueEvent read FOnTextToValue write FOnTextToValue; + property OnValueChange: TSEChangeEvent read FOnValueChange write FOnValueChange; + property OnValueToText: TSEValueToTextEvent read FOnValueToText write FOnValueToText; + public + constructor Create(AOwner: TComponent); override; + property ValueType: TSEValueType read FValueType write SetValueType default evtInteger; + property AsInteger: Integer read GetAsInteger write SetAsInteger stored False; + property Decimal: TDecimal read FDecimal write SetDecimal default 2; + property Increment: Extended read FIncrement write SetIncrement stored IsIncrementStored; + property MaxValue: Extended read FMaxValue write FMaxValue stored IsMaxValueStored; + property MinValue: Extended read FMinValue write FMinValue stored IsMinValueStored; + property Postfix: string read FPostfix write SetPostfix; + property Prefix: string read FPrefix write SetPrefix; + property Snap: Boolean read FSnap write FSnap default True; + property SpaceAfterPrefix: Boolean read FSpaceAfterPrefix write SetSpaceAfterPrefix; + property SpaceBeforePostfix: Boolean read FSpaceBeforePostfix write SetSpaceBeforePostfix; + property Value: Extended read GetValue write SetValue stored IsValueStored; + published + property Text stored False; + end; + + TTBXSpinEditItem = class(TTBXCustomSpinEditItem) + published + property ValueType; + property Alignment; + property Decimal; + property Increment; + property MaxValue; + property MinValue; + property Postfix; + property Prefix; + property Snap; + property SpaceAfterPrefix; + property SpaceBeforePostfix; + property Value; + property OnConvert; + property OnStep; + property OnTextToValue; + property OnValueChange; + property OnValueToText; + end; + + TSEBtnState = (ebsNone, ebsUp, ebsDown); + + TTBXSpinEditViewer = class(TTBXEditItemViewer) + private + FBtnState: TSEBtnState; + FBtnTimer: TTimer; + procedure TimerHandler(Sender: TObject); + protected + function GetIndentAfter: Integer; override; + procedure GetEditInfo(out EditInfo: TTBXEditInfo; const ItemInfo: TTBXItemInfo); override; + function HandleEditMessage(var Message: TMessage): Boolean; override; + procedure InvalidateButtons; + function IsPtInButtonPart(X, Y: Integer): Boolean; override; + procedure LosingCapture; override; + procedure MouseDown(Shift: TShiftState; X, Y: Integer; var MouseDownOnMenu: Boolean); override; + procedure MouseUp(X, Y: Integer; MouseWasDownOnMenu: Boolean); override; + public + destructor Destroy; override; + end; + + { TTBXCustomDropDownItem } + { An extended edit item tb2k with a button. The dropdown list support is + implemented in descendants, such as TTBXComboBoxItem } + + TTBXCustomDropDownItem = class(TTBXEditItem) + private + FAlwaysSelectFirst: Boolean; + FDropDownList: Boolean; + protected + function CreatePopup(const ParentView: TTBView; const ParentViewer: TTBItemViewer; + const PositionAsSubmenu, SelectFirstItem, Customizing: Boolean; + const APopupPoint: TPoint; const Alignment: TTBPopupAlignment): TTBPopupWindow; override; + function GetItemViewerClass(AView: TTBView): TTBItemViewerClass; override; + public + constructor Create(AOwner: TComponent); override; + property AlwaysSelectFirst: Boolean read FAlwaysSelectFirst write FAlwaysSelectFirst default True; + property DropDownList: Boolean read FDropDownList write FDropDownList default False; + end; + + TTBXDropDownItem = class(TTBXCustomDropDownItem) + published + property AlwaysSelectFirst; + property DropDownList; + property LinkSubitems; + property SubMenuImages; + end; + + TTBXDropDownItemViewer = class(TTBXEditItemViewer) + protected + procedure GetCursor(const Pt: TPoint; var ACursor: HCURSOR); override; + procedure GetEditInfo(out EditInfo: TTBXEditInfo; const ItemInfo: TTBXItemInfo); override; + function GetIndentAfter: Integer; override; + function HandleEditMessage(var Message: TMessage): Boolean; override; + function IsPtInButtonPart(X, Y: Integer): Boolean; override; + procedure KeyDown(var Key: Word; Shift: TShiftState); override; + end; + +{$IFDEF COMPATIBLE} + { For compatibility with previous versions } + TTBXComboItem = class(TTBXDropDownItem); +{$ENDIF} + + { TTBXComboBoxItem } + { A combination of dropdown combo with a stringlist subitem } + TTBXComboBoxItem = class; + TTBXCAdjustImageIndex = procedure(Sender: TTBXComboBoxItem; const AText: string; + AIndex: Integer; var ImageIndex: Integer) of object; + + TTBXComboBoxItem = class(TTBXCustomDropDownItem) + private + FAutoComplete: Boolean; + FList: TTBXStringList; + FOnItemClick: TNotifyEvent; + FOnAdjustImageIndex: TTBXCAdjustImageIndex; + procedure AdjustImageIndexHandler(Sender: TTBXCustomList; AItemIndex: Integer; var ImageIndex: Integer); + function GetItemIndex: Integer; + function GetMaxVisibleItems: Integer; + function GetMaxWidth: Integer; + function GetMinWidth: Integer; + function GetStrings: TStrings; + function GetShowListImages: Boolean; + function GetOnClearItem: TTBXLPaintEvent; + function GetOnDrawItem: TTBXLPaintEvent; + function GetOnMeasureHeight: TTBXLMeasureHeight; + function GetOnMeasureWidth: TTBXLMeasureWidth; + procedure ListChangeHandler(Sender: TObject); + procedure ListClickHandler(Sender: TObject); + procedure SetItemIndex(Value: Integer); + procedure SetMaxVisibleItems(Value: Integer); + procedure SetMaxWidth(Value: Integer); + procedure SetMinWidth(Value: Integer); + procedure SetOnClearItem(Value: TTBXLPaintEvent); + procedure SetOnDrawItem(Value: TTBXLPaintEvent); + procedure SetOnMeasureHeight(Value: TTBXLMeasureHeight); + procedure SetOnMeasureWidth(Value: TTBXLMeasureWidth); + procedure SetStrings(Value: TStrings); + procedure SetShowListImages(Value: Boolean); + protected + CachedImageIndex: Integer; + CacheValid: Boolean; + IsChanging: Boolean; + procedure AdjustImageIndex(const AText: string; AIndex: Integer; var ImageIndex: Integer); virtual; + function DoAutoComplete(var AText: string): Boolean; override; + procedure DoListChange; virtual; + procedure DoListClick; virtual; + procedure DoPopup(Sender: TTBCustomItem; FromLink: Boolean); override; + function GetImageIndex: Integer; override; + function GetItemViewerClass(AView: TTBView): TTBItemViewerClass; override; + function GetStringListClass: TTBXStringListClass; virtual; + procedure HandleEditChange(Edit: TEdit); override; + public + constructor Create(AOwner: TComponent); override; + procedure Loaded; override; + property ItemIndex: Integer read GetItemIndex write SetItemIndex default -1; + published + property AutoComplete: Boolean read FAutoComplete write FAutoComplete default True; + property DropDownList; + property MaxListWidth: Integer read GetMaxWidth write SetMaxWidth default 0; + property MaxVisibleItems: Integer read GetMaxVisibleItems write SetMaxVisibleItems default 8; + property MinListWidth: Integer read GetMinWidth write SetMinWidth default 64; + property ShowListImages: Boolean read GetShowListImages write SetShowListImages default False; + property Strings: TStrings read GetStrings write SetStrings; + property SubMenuImages; + property OnChange; + property OnAdjustImageIndex: TTBXCAdjustImageIndex read FOnAdjustImageIndex write FOnAdjustImageIndex; + property OnClearItem: TTBXLPaintEvent read GetOnClearItem write SetOnClearItem; + property OnDrawItem: TTBXLPaintEvent read GetOnDrawItem write SetOnDrawItem; + property OnItemClick: TNotifyEvent read FOnItemClick write FOnItemClick; + property OnMeasureHeight: TTBXLMeasureHeight read GetOnMeasureHeight write SetOnMeasureHeight; + property OnMeasureWidth: TTBXLMeasureWidth read GetOnMeasureWidth write SetOnMeasureWidth; + property OnPopup; + end; + +{$IFDEF COMPATIBLE} + { For compatibility with previous versions } + TTBXComboList = class(TTBXComboBoxItem); +{$ENDIF} + + TTBXComboBoxItemViewer = class(TTBXDropDownItemViewer) + protected + function HandleEditMessage(var Message: TMessage): Boolean; override; + end; + + { TTBXLabelItem } + + TTBXLabelOrientation = (tbxoAuto, tbxoHorizontal, tbxoVertical); + TNonNegativeInt = 0..MaxInt; + + TTBXLabelItem = class(TTBCustomItem) + private + FCaption: TCaption; + FFontSettings: TFontSettings; + FMargin: Integer; + FShowAccelChar: Boolean; + FOrientation: TTBXLabelOrientation; + FOnAdjustFont: TAdjustFontEvent; + procedure FontSettingsChanged(Sender: TObject); + procedure SetMargin(Value: Integer); + procedure SetOrientation(Value: TTBXLabelOrientation); + procedure SetCaption(const Value: TCaption); + procedure SetFontSettings(Value: TFontSettings); + procedure SetShowAccelChar(Value: Boolean); + protected + function GetItemViewerClass (AView: TTBView): TTBItemViewerClass; override; + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + procedure UpdateCaption(const Value: TCaption); + published + property Caption: TCaption read FCaption write SetCaption; + property Enabled; + property FontSettings: TFontSettings read FFontSettings write SetFontSettings; + property Margin: Integer read FMargin write SetMargin default 0; + property Orientation: TTBXLabelOrientation read FOrientation write SetOrientation default tbxoAuto; + property ShowAccelChar: Boolean read FShowAccelChar write SetShowAccelChar default True; + property Visible; + property OnAdjustFont: TAdjustFontEvent read FOnAdjustFont write FOnAdjustFont; + end; + + TTBXLabelItemViewer = class(TTBItemViewer) + protected + function GetCaptionText: string; override; + function GetIsHoriz: Boolean; virtual; + procedure DoAdjustFont(AFont: TFont; StateFlags: Integer); virtual; + procedure CalcSize(const Canvas: TCanvas; var AWidth, AHeight: Integer); override; + procedure Paint(const Canvas: TCanvas; const ClientAreaRect: TRect; + IsHoverItem, IsPushed, UseDisabledShadow: Boolean); override; + function IsToolbarSize: Boolean; override; + public + function IsToolbarStyle: Boolean; override; + end; + + { TTBXColorItem } + + TTBXColorItem = class(TTBXCustomItem) + private + FColor: TColor; + procedure SetColor(Value: TColor); + protected + function GetItemViewerClass (AView: TTBView): TTBItemViewerClass; override; + public + constructor Create(AOwner: TComponent); override; + published + property Action; + property AutoCheck; + property Caption; + property Checked; + property Color: TColor read FColor write SetColor default clWhite; + property DisplayMode; + property Enabled; + property FontSettings; + property GroupIndex; + property HelpContext; + property Hint; + property InheritOptions; + property MaskOptions; + property MinHeight; + property MinWidth; + property Options; + property ShortCut; + property Visible; + property OnAdjustFont; + property OnClick; + end; + + TTBXColorItemViewer = class(TTBXItemViewer) + protected + procedure DoPaintCaption(Canvas: TCanvas; const ClientAreaRect: TRect; + var CaptionRect: TRect; IsTextRotated: Boolean; var PaintDefault: Boolean); override; + function GetImageShown: Boolean; override; + function GetImageSize: TSize; override; + procedure DrawItemImage(Canvas: TCanvas; ARect: TRect; ItemInfo: TTBXItemInfo); override; + public + constructor Create(AView: TTBView; AItem: TTBCustomItem; AGroupLevel: Integer); override; + end; + + { TTBXMRUList } + + TTBXMRUList = class(TTBMRUList) + private + FKeyShift: Integer; + procedure SetKeyShift(Value: Integer); + protected + function GetFirstKey: Integer; override; + function GetItemClass: TTBCustomItemClass; override; + procedure SetItemCaptions; override; + published + property KeyShift: Integer read FKeyShift write SetKeyShift default 0; + end; + + { TTBXMRUListItem } + + TTBXMRUListItem = class(TTBXCustomItem) + private + FMRUList: TTBMRUList; + procedure SetMRUList(Value: TTBMRUList); + protected + procedure Notification(AComponent: TComponent; Operation: TOperation); override; + public + constructor Create(AOwner: TComponent); override; + published + property MRUList: TTBMRUList read FMRUList write SetMRUList; + end; + +implementation + +uses TB2Common, TB2Consts, TypInfo, Math, ImgList {$IFNDEF JR_D5}, DsgnIntf{$ENDIF}; + +const + { Repeat intervals for spin edit items } + SE_FIRSTINTERVAL = 400; + SE_INTERVAL = 100; + +type + TTBViewAccess = class(TTBView); + TTBItemAccess = class(TTBCustomItem); + TTBMRUListAccess = class(TTBMRUList); + TCustomEditAccess = class(TCustomEdit); + TFontSettingsAccess = class(TFontSettings); + +{ Misc. functions } + +function StartsText(const ASubText, AText: string): Boolean; +var + P: PChar; + L, L2: Integer; +begin + P := PChar(AText); + L := Length(ASubText); + L2 := Length(AText); + if L > L2 then Result := False + else Result := CompareString(LOCALE_USER_DEFAULT, NORM_IGNORECASE, + P, L, PChar(ASubText), L) = 2; +end; + +//============================================================================// + +{ TTBXEdit } + +type + TTBXEdit = class(TEdit) + private + FAlignment: TAlignment; + procedure SetAlignment(Value: TAlignment); + protected + procedure CreateParams(var Params: TCreateParams); override; + public + property Alignment: TAlignment read FAlignment write SetAlignment; + end; + +procedure TTBXEdit.CreateParams(var Params: TCreateParams); +const + Alignments: array[TAlignment] of Cardinal = (ES_LEFT, ES_RIGHT, ES_CENTER); +begin + inherited CreateParams(Params); + Params.Style := Params.Style or Alignments[FAlignment]; +end; + +procedure TTBXEdit.SetAlignment(Value: TAlignment); +begin + if Value <> FAlignment then + begin + FAlignment := Value; + RecreateWnd; + end; +end; + + +//============================================================================// + +{ TTBXEditItem } + +constructor TTBXEditItem.Create(AOwner: TComponent); +begin + inherited; + FEditorFontSettings := TFontSettings.Create; + FFontSettings := TFontSettings.Create; + TFontSettingsAccess(FEditorFontSettings).OnChange := FontSettingsChanged; + TFontSettingsAccess(FFontSettings).OnChange := FontSettingsChanged; +end; + +destructor TTBXEditItem.Destroy; +begin + FFontSettings.Free; + FEditorFontSettings.Free; + inherited; +end; + +function TTBXEditItem.DoAcceptText(var NewText: string): Boolean; +begin + Result := inherited DoAcceptText(NewText); +// if not Result then DoChange(Text); +end; + +function TTBXEditItem.DoAutoComplete(var AText: string): Boolean; +begin + Result := False; +end; + +procedure TTBXEditItem.DoBeginEdit(Viewer: TTBEditItemViewer); +begin + with Viewer do + begin + TTBXEdit(EditControl).Alignment := Alignment; + EditControl.PasswordChar := PasswordChar; + EditControl.SelectAll; + EditControl.ReadOnly := ReadOnly; + EditorFontSettings.Apply(EditControl.Font); + FAutoCompleteCounter := 0; + inherited; + if Viewer is TTBXEditItemViewer then + begin + EditControl.OnChange := TTBXEditItemViewer(Viewer).EditChangeHandler; + TTBXEditItemViewer(Viewer).OldWndProc := EditControl.WindowProc; + EditControl.WindowProc := TTBXEditItemViewer(Viewer).NewEditWndProc; + end; + end; +end; + +procedure TTBXEditItem.DoChange(const AText: string); +begin + if Assigned(FOnChange) then FOnChange(Self, AText); +end; + +procedure TTBXEditItem.DoTextChanged(Reason: Integer); +begin + if not ((Reason = tcrEditControl) and (Text = FLastEditChange)) then + DoChange(Text); +end; + +procedure TTBXEditItem.FontSettingsChanged(Sender: TObject); +begin + Change(True); +end; + +function TTBXEditItem.GetImageIndex: Integer; +begin + Result := ImageIndex; +end; + +function TTBXEditItem.GetItemViewerClass(AView: TTBView): TTBItemViewerClass; +begin + if not (tboUseEditWhenVertical in EditOptions) and + (AView.Orientation = tbvoVertical) then + Result := TTBXItemViewer + else + Result := TTBXEditItemViewer; +end; + +procedure TTBXEditItem.GetPopupPosition(ParentView: TTBView; + PopupWindow: TTBPopupWindow; var PopupPositionRec: TTBPopupPositionRec); +var + VT: Integer; +begin + inherited; + VT := GetWinViewType(PopupWindow); + PopupPositionRec.PlaySound := not (VT and PVT_LISTBOX = PVT_LISTBOX); +end; + +function TTBXEditItem.GetPopupWindowClass: TTBPopupWindowClass; +begin + Result := TTBXPopupWindow; +end; + +procedure TTBXEditItem.HandleEditChange(Edit: TEdit); +var + S, S2: string; +begin + if not FIsChanging then + begin + FIsChanging := True; + try + S := Edit.Text; + S2 := S; + if (Length(S) > 0) and (FAutoCompleteCounter > 0) and DoAutoComplete(S2) then + begin + Edit.Text := S2; + Edit.SelStart := Length(S); + Edit.SelLength := Length(S2) - Length(S); + S := S2; + end; + if S <> FLastEditChange then + begin + DoChange(S); // note, Edit.Text may be different from Self.Text + FLastEditChange := S; + end; + finally + FIsChanging := False; + end; + end; +end; + +procedure TTBXEditItem.SetAlignment(Value: TAlignment); +begin + if Value <> FAlignment then + begin + FAlignment := Value; + Change(True); + end; +end; + +procedure TTBXEditItem.SetFontSettings(Value: TFontSettings); +begin + FFontSettings.Assign(Value); +end; + +procedure TTBXEditItem.SetPasswordChar(Value: Char); +begin + if Value <> FPasswordChar then + begin + FPasswordChar := Value; + Change(True); + end; +end; + +procedure TTBXEditItem.SetShowImage(const Value: Boolean); +begin + FShowImage := Value; + Change(True); +end; + +function TTBXEditItem.StartEditing(AView: TTBView): Boolean; +var + V: TTBItemViewer; + SaveText: string; +begin + Result := False; + V := AView.Find(Self); + if V is TTBXEditItemViewer then + begin + SaveText := Text; + TTBXEditItemViewer(V).DoExecute; + Result := Text <> SaveText; + end; +end; + + +//============================================================================// + +{ TTBXEditItemViewer } + +procedure TTBXEditItemViewer.CalcSize(const Canvas: TCanvas; var AWidth, AHeight: Integer); +var + W, B: Integer; + EditBoxHeight: Integer; + EditCaptionSize: TSize; +begin + if Self.Item is TTBXEditItem then with CurrentTheme do + begin + B := EditFrameWidth; + + AWidth := TTBXEditItem(Item).EditWidth; + if not IsToolbarStyle then + begin + EditCaptionSize := MeasureEditCaption; + W := EditCaptionSize.CX; + if W > 0 then Inc(W, MenuLeftCaptionMargin + MenuRightCaptionMargin + MenuImageTextSpace); + Inc(AWidth, GetPopupMargin(Self) + MenuImageTextSpace + W + EditMenuRightIndent); + end + else + begin + EditCaptionSize.CX := 0; + EditCaptionSize.CY := 0; + end; + + EditBoxHeight := MeasureTextHeight + 1; + Inc(EditBoxHeight, EditTextMarginVert * 2 + B * 2); + AHeight := Max(EditBoxHeight, EditCaptionSize.CY); + if not IsToolbarStyle then AHeight := AHeight; + if EditHeightEven then AHeight := (AHeight + 1) and not $01 + else AHeight := AHeight or $01; + end + else inherited; +end; + +procedure TTBXEditItemViewer.EditChangeHandler(Sender: TObject); +begin + HandleEditChange((Sender as TEdit)); +end; + +procedure TTBXEditItemViewer.HandleEditChange(Edit: TEdit); +begin + TTBXEditItem(Item).HandleEditChange(Edit); +end; + +procedure TTBXEditItemViewer.GetEditInfo(out EditInfo: TTBXEditInfo; const ItemInfo: TTBXItemInfo); +begin + FillChar(EditInfo, SizeOf(EditInfo), 0); + EditInfo.LeftBtnWidth := GetIndentBefore; + EditInfo.RightBtnWidth := GetIndentAfter; +end; + +function TTBXEditItemViewer.GetAccRole: Integer; +const + ROLE_SYSTEM_SPINBUTTON = $34; + ROLE_SYSTEM_COMBOBOX = $2E; +begin + Result := inherited GetAccRole; + if Self is TTBXSpinEditViewer then Result := ROLE_SYSTEM_SPINBUTTON + else if Self is TTBXDropDownItemViewer then Result := ROLE_SYSTEM_COMBOBOX; +end; + +procedure TTBXEditItemViewer.GetItemInfo(out ItemInfo: TTBXItemInfo; IsHoverItem, IsPushed, UseMenuColor: Boolean); +const + CToolbarStyle: array [Boolean] of Integer = (0, IO_TOOLBARSTYLE); + CDesigning: array [Boolean] of Integer = (0, IO_DESIGNING); +var + Item: TTBXEditItem; +begin + Item := TTBXEditItem(Self.Item); + + FillChar(ItemInfo, SizeOf(TTBXItemInfo), 0); + ItemInfo.ViewType := GetViewType(View); + ItemInfo.ItemOptions := CToolbarStyle[IsToolbarStyle] + or CDesigning[csDesigning in Item.ComponentState]; + ItemInfo.Enabled := Item.Enabled or View.Customizing; + ItemInfo.Pushed := IsPushed; + ItemInfo.Selected := Item.Checked; + if IsHoverItem then + begin + if not ItemInfo.Enabled and not View.MouseOverSelected then + ItemInfo.HoverKind := hkKeyboardHover + else + if ItemInfo.Enabled then ItemInfo.HoverKind := hkMouseHover; + end + else ItemInfo.HoverKind := hkNone; + if not IsToolbarStyle then ItemInfo.PopupMargin := GetPopupMargin(Self); +end; + +procedure TTBXEditItemViewer.GetEditRect(var R: TRect); +const + TB2K_EDIT_BORDER = 3; +var + W, B: Integer; +begin + if Item is TTBXEditItem then with CurrentTheme do + begin + R := BoundsRect; + if not IsToolbarStyle then + begin + W := MeasureEditCaption.CX; + if W > 0 then Inc(W, MenuLeftCaptionMargin + MenuRightCaptionMargin + MenuImageTextSpace); + Inc(R.Left, GetPopupMargin(Self) + MenuImageTextSpace + W); + Dec(R.Right, EditMenuRightIndent); + end; + + B := EditFrameWidth - TB2K_EDIT_BORDER; + InflateRect(R, -B - EditTextMarginHorz , -B - EditTextMarginVert); + Inc(R.Left, GetIndentBefore); + Dec(R.Right, GetIndentAfter); + end + else inherited; +end; + +function TTBXEditItemViewer.GetIndentAfter: Integer; +begin + Result := 0; +end; + +function TTBXEditItemViewer.GetIndentBefore: Integer; +var + ImgList: TCustomImageList; +begin + if ShowImage then + begin + ImgList := GetImageList; + if ImgList <> nil then Result := ImgList.Width + 2 + else Result := 0; + end + else Result := 0; +end; + +function TTBXEditItemViewer.HandleEditMessage(var Message: TMessage): Boolean; +const + CharKeys = [VK_SPACE, $30..$5A, VK_NUMPAD0..VK_DIVIDE, $BA..$F5]; +begin + if Message.Msg = WM_KEYDOWN then + begin + if Message.WParam in CharKeys then Inc(TTBXEditItem(Item).FAutoCompleteCounter) + end + else if Message.Msg = WM_KEYUP then + begin + if Message.WParam in CharKeys then Dec(TTBXEditItem(Item).FAutoCompleteCounter); + end; + Result := False; +end; + +procedure TTBXEditItemViewer.NewEditWndProc(var Message: TMessage); +begin + if Assigned(OldWndProc) and not HandleEditMessage(Message) then OldWndProc(Message); +end; + +procedure TTBXEditItemViewer.Paint(const Canvas: TCanvas; + const ClientAreaRect: TRect; IsHoverItem, IsPushed, UseDisabledShadow: Boolean); +const + FillColors: array [Boolean] of Integer = (COLOR_BTNFACE, COLOR_WINDOW); + TextColors: array [Boolean] of Integer = (COLOR_GRAYTEXT, COLOR_WINDOWTEXT); + Alignments: array [TAlignment] of Integer = (DT_LEFT, DT_RIGHT, DT_CENTER); +var + DC: HDC; + Item: TTBXEditItem; + S: string; + R, R2: TRect; + M, W: Integer; + ItemInfo: TTBXItemInfo; + EditInfo: TTBXEditInfo; + ImgList: TCustomImageList; + ImgIndex: Integer; + Fnt, OldFnt: HFont; + C, OldColor: TColor; +begin + DC := Canvas.Handle; + Item := TTBXEditItem(Self.Item); + GetItemInfo(ItemInfo, IsHoverItem, IsPushed, UseDisabledShadow); + GetEditInfo(EditInfo, ItemInfo); + R := ClientAreaRect; + + if not IsToolbarStyle then with CurrentTheme do + begin + S := Item.EditCaption; + + if Length(S) > 0 then + begin + { measure EditCaption } + Fnt := TTBXEditItem(Item).FontSettings.CreateTransformedFont(TTBViewAccess(View).GetFont.Handle, C); + OldFnt := SelectObject(DC, Fnt); + W := GetTextWidth(DC, S, True) + MenuImageTextSpace + MenuLeftCaptionMargin + MenuRightCaptionMargin; + SelectObject(DC, OldFnt); + end + else + begin + Fnt := 0; // to suppress compiler warning + W := 0; + end; + + M := GetPopupMargin(Self); + if not EditMenuFullSelect then R.Right := M + W + else Dec(R.Right, EditMenuRightIndent); + PaintMenuItemFrame(Canvas, R, ItemInfo); + Inc(R.Left, M + MenuImageTextSpace); + R.Right := ClientAreaRect.Right - EditMenuRightIndent; + + if Length(S) > 0 then + begin + Inc(R.Left, MenuLeftCaptionMargin); + C := ColorToRGB(GetItemTextColor(ItemInfo)); + OldFnt := SelectObject(DC, Fnt); + OldColor := SetTextColor(DC, C); + PaintCaption(Canvas, R, ItemInfo, S, DT_SINGLELINE or DT_LEFT or DT_VCENTER, False); + SetTextColor(DC, OldColor); + W := GetTextWidth(DC, S, True); + SelectObject(DC, OldFnt); + DeleteObject(Fnt); + Inc(R.Left, W + MenuRightCaptionMargin + MenuImageTextSpace); + end; + end; + + CurrentTheme.PaintEditFrame(Canvas, R, ItemInfo, EditInfo); + W := CurrentTheme.EditFrameWidth; + InflateRect(R, -W - CurrentTheme.EditTextMarginHorz, -W - CurrentTheme.EditTextMarginVert); + + if ShowImage then + begin + ImgList := GetImageList; + if ImgList <> nil then + begin + R2.Left := R.Left; + R2.Right := R.Left + ImgList.Width; + R2.Top := (R.Top + R.Bottom + 1 - ImgList.Height) div 2; + R2.Bottom := R2.Top + ImgList.Height; + ImgIndex := TTBXEditItem(Item).GetImageIndex; + if Item.Enabled then ImgList.Draw(Canvas, R.Left, R2.Top, ImgIndex) + else DrawTBXImage(Canvas, R2, ImgList, ImgIndex, ISF_DISABLED); + end; + end; + Inc(R.Left, EditInfo.LeftBtnWidth); + Dec(R.Right, EditInfo.RightBtnWidth + 1); + + if Item.Text <> '' then + begin + S := Item.Text; + if TTBXEditItem(Item).PasswordChar <> #0 then S := StringOfChar(TTBXEditItem(Item).PasswordChar, Length(S)); + Fnt := Item.EditorFontSettings.CreateTransformedFont(TTBViewAccess(View).GetFont.Handle, C); + OldFnt := SelectObject(DC, Fnt); + SetBkMode(DC, TRANSPARENT); + SetBkColor(DC, GetSysColor(FillColors[Item.Enabled])); + SetTextColor(DC, GetSysColor(TextColors[Item.Enabled])); + DrawText(DC, PChar(S), Length(S), R, DT_SINGLELINE or DT_NOPREFIX or Alignments[Item.Alignment]); + SelectObject(DC, OldFnt); + DeleteObject(Fnt); + end; + +{ if not IsToolbarStyle then + begin + R := ClientAreaRect; + Self.GetEditRect(R); + OffsetRect(R, -BoundsRect.Left, -BoundsRect.Top); + Canvas.FrameRect(R); + end; } +end; + +function TTBXEditItemViewer.GetEditControlClass: TEditClass; +begin + Result := TTBXEdit; +end; + +function TTBXEditItemViewer.ShowImage: Boolean; +begin + Result := TTBXEditItem(Item).ShowImage; +end; + +function TTBXEditItemViewer.IsToolbarSize: Boolean; +begin + Result := inherited IsToolbarSize; + Result := Result or ((GetViewType(View) and PVT_TOOLBOX) = PVT_TOOLBOX); +end; + +function TTBXEditItemViewer.IsToolbarStyle: Boolean; +begin + Result := inherited IsToolbarStyle; + Result := Result or ((GetViewType(View) and PVT_TOOLBOX) = PVT_TOOLBOX); +end; + +function TTBXEditItemViewer.MeasureEditCaption: TSize; +var + DC: HDC; + Fnt, OldFnt: HFont; + DummyColor: TColor; + TextMetric: TTextMetric; + S: string; +begin + Result.cx := 0; + Result.cy := 0; + if Item is TTBXEditItem then + begin + S := StripAccelChars(TTBXEditItem(Item).EditCaption); + if Length(S) > 0 then + begin + DummyColor := clWhite; + DC := GetDC(0); + Fnt := TTBXEditItem(Item).FontSettings.CreateTransformedFont(TTBViewAccess(View).GetFont.Handle, DummyColor); + OldFnt := SelectObject(DC, Fnt); + GetTextExtentPoint32(DC, PChar(S), Length(S), Result); + GetTextMetrics(DC, TextMetric); + Inc(Result.cy, TextMetric.tmExternalLeading); + SelectObject(DC, OldFnt); + DeleteObject(Fnt); + ReleaseDC(0, DC); + end; + end; +end; + +function TTBXEditItemViewer.MeasureTextHeight: Integer; +var + DC: HDC; + Fnt, OldFnt: HFont; + DummyColor: TColor; + TextMetric: TTextMetric; +begin + Result := 0; + if Item is TTBXEditItem then + begin + DummyColor := clWhite; + DC := GetDC(0); + Fnt := TTBXEditItem(Item).EditorFontSettings.CreateTransformedFont(TTBViewAccess(View).GetFont.Handle, DummyColor); + OldFnt := SelectObject(DC, Fnt); + Result := GetTextHeight(DC); + GetTextMetrics(DC, TextMetric); + Inc(Result, TextMetric.tmExternalLeading); + SelectObject(DC, OldFnt); + DeleteObject(Fnt); + ReleaseDC(0, DC); + end; +end; + +function TTBXEditItemViewer.DoExecute: Boolean; +begin + if Item is TTBXEditItem then + begin + TTBXEditItem(Item).FLastEditChange := ''; + Result := inherited DoExecute; + with TTBXEditItem(Item) do + begin + if FLastEditChange <> Text then DoChange(Text); + FLastEditChange := ''; + end; + end + else Result := inherited DoExecute; +end; + + +//============================================================================// + +{ TTBXCustomDropDownItem } + +constructor TTBXCustomDropDownItem.Create(AOwner: TComponent); +begin + inherited; + ItemStyle := ItemStyle + [tbisCombo, tbisSubmenu, tbisSubitemsEditable] - [tbisDontSelectFirst]; + FAlwaysSelectFirst := True; +end; + +function TTBXCustomDropDownItem.CreatePopup(const ParentView: TTBView; + const ParentViewer: TTBItemViewer; const PositionAsSubmenu, + SelectFirstItem, Customizing: Boolean; const APopupPoint: TPoint; + const Alignment: TTBPopupAlignment): TTBPopupWindow; +var + SelectFirst: Boolean; +begin + if AlwaysSelectFirst then SelectFirst := True + else SelectFirst := SelectFirstItem; + Result := inherited CreatePopup(ParentView, ParentViewer, PositionAsSubmenu, + SelectFirst, Customizing, APopupPoint, Alignment); +end; + +function TTBXCustomDropDownItem.GetItemViewerClass(AView: TTBView): TTBItemViewerClass; +begin + if not (tboUseEditWhenVertical in EditOptions) and (AView.Orientation = tbvoVertical) then + Result := TTBXItemViewer + else + Result := TTBXDropDownItemViewer; +end; + + +//----------------------------------------------------------------------------// + +{ TTBXDropDownItemViewer } + +procedure TTBXDropDownItemViewer.GetCursor(const Pt: TPoint; var ACursor: HCURSOR); +begin + if not TTBXCustomDropDownItem(Item).DropDownList then inherited; +end; + +procedure TTBXDropDownItemViewer.GetEditInfo(out EditInfo: TTBXEditInfo; const ItemInfo: TTBXItemInfo); +const + CDisabled: array [Boolean] of Integer = (EBDS_DISABLED, 0); + CHot: array [Boolean] of Integer = (0, EBDS_HOT); + CPressed: array [Boolean] of Integer = (0, EBDS_PRESSED); +begin + inherited GetEditInfo(EditInfo, ItemInfo); + EditInfo.RightBtnInfo.ButtonType := EBT_DROPDOWN; + EditInfo.RightBtnInfo.ButtonState := CDisabled[ItemInfo.Enabled] or + CHot[ItemInfo.HoverKind = hkMouseHover] or CPressed[ItemInfo.Pushed]; +end; + +function TTBXDropDownItemViewer.GetIndentAfter: Integer; +begin + if IsToolbarStyle then Result := CurrentTheme.EditBtnWidth + else Result := GetSystemMetrics(SM_CXMENUCHECK) + 2; +end; + +function TTBXDropDownItemViewer.HandleEditMessage(var Message: TMessage): Boolean; +begin + if Message.Msg = WM_KEYDOWN then + begin + if TWMKeyDown(Message).CharCode = VK_F4 then + begin + TTBViewAccess(View).OpenChildPopup(True); + Result := True; + Exit; + end; + end; + + Result := inherited HandleEditMessage(Message); +end; + +function TTBXDropDownItemViewer.IsPtInButtonPart(X, Y: Integer): Boolean; +begin + Result := not (tbisSubmenu in TTBXCustomDropDownItem(Item).ItemStyle); + if TTBXCustomDropDownItem(Item).DropDownList then Result := False + else if (tbisCombo in TTBXCustomDropDownItem(Item).ItemStyle) then + Result := X < (BoundsRect.Right - BoundsRect.Left) - GetIndentAfter; +end; + +procedure TTBXDropDownItemViewer.KeyDown(var Key: Word; Shift: TShiftState); +begin + if not TTBXCustomDropDownItem(Item).DropDownList then inherited; +end; + +//============================================================================// + +{ TTBXComboBoxItem } + +procedure TTBXComboBoxItem.AdjustImageIndex(const AText: string; + AIndex: Integer; var ImageIndex: Integer); +begin + if Assigned(FOnAdjustImageIndex) then FOnAdjustImageIndex(Self, AText, AIndex, ImageIndex); +end; + +procedure TTBXComboBoxItem.AdjustImageIndexHandler(Sender: TTBXCustomList; + AItemIndex: Integer; var ImageIndex: Integer); +begin + AdjustImageIndex(FList.Strings[AItemIndex], AItemIndex, ImageIndex); +end; + +constructor TTBXComboBoxItem.Create(AOwner: TComponent); +begin + inherited; + ItemStyle := ItemStyle - [tbisSubItemsEditable]; + FAutoComplete := True; + FList := GetStringListClass.Create(Self); + FList.OnChange := ListChangeHandler; + FList.OnClick := ListClickHandler; + FList.OnAdjustImageIndex := AdjustImageIndexHandler; + MinListWidth := 64; +end; + +function TTBXComboBoxItem.DoAutoComplete(var AText: string): Boolean; +var + I: Integer; + S, R: string; + TemplateL, MinL, L: Integer; +begin + Result := False; + if Length(AText) > 0 then + begin + { choose the shortest matching string from items } + TemplateL := Length(AText); + MinL := MaxInt; + SetLength(R, 0); + for I := 0 to FList.Strings.Count - 1 do + begin + S := FList.Strings[I]; + L := Length(S); + if (L >= TemplateL) and (L < MinL) and StartsText(AText, S) then + begin + R := S; + MinL := L; + if MinL = TemplateL then Break; + end; + end; + Result := Length(R) > 0; + if Result then AText := R; + end; +end; + +procedure TTBXComboBoxItem.DoListChange; +begin + { Update text in edit item. This will call OnChange automatically } + if (FList.ItemIndex >= 0) and (FList.ItemIndex < FList.Strings.Count) then + begin + IsChanging := True; + try + if Text <> FList.Strings[Flist.ItemIndex] then + begin + SetTextEx(FList.Strings[FList.ItemIndex], tcrList); + end; + finally + IsChanging := False; + end; + end; +end; + +procedure TTBXComboBoxItem.DoListClick; +begin + if Assigned(FOnItemClick) then FOnItemClick(Self); +end; + +procedure TTBXComboBoxItem.DoPopup(Sender: TTBCustomItem; FromLink: Boolean); +begin + inherited; + FList.ItemIndex := FList.Strings.IndexOf(Text); +end; + +function TTBXComboBoxItem.GetImageIndex: Integer; +begin + if not CacheValid then + begin + CachedImageIndex := ImageIndex; + if ItemIndex >= 0 then CachedImageIndex := ItemIndex; + AdjustImageIndex(Text, -1, CachedImageIndex); + CacheValid := True; + end; + Result := CachedImageIndex; +end; + +function TTBXComboBoxItem.GetItemIndex: Integer; +begin + Result := FList.ItemIndex; +end; + +function TTBXComboBoxItem.GetItemViewerClass(AView: TTBView): TTBItemViewerClass; +begin + if not (tboUseEditWhenVertical in EditOptions) and + (AView.Orientation = tbvoVertical) then + Result := TTBXItemViewer + else + Result := TTBXComboBoxItemViewer; +end; + +function TTBXComboBoxItem.GetMaxVisibleItems: Integer; +begin + Result := FList.MaxVisibleItems; +end; + +function TTBXComboBoxItem.GetMaxWidth: Integer; +begin + Result := FList.MaxWidth; +end; + +function TTBXComboBoxItem.GetMinWidth: Integer; +begin + Result := FList.MinWidth; +end; + +function TTBXComboBoxItem.GetOnClearItem: TTBXLPaintEvent; +begin + Result := FList.OnClearItem; +end; + +function TTBXComboBoxItem.GetOnDrawItem: TTBXLPaintEvent; +begin + Result := FList.OnDrawItem; +end; + +function TTBXComboBoxItem.GetOnMeasureHeight: TTBXLMeasureHeight; +begin + Result := FList.OnMeasureHeight; +end; + +function TTBXComboBoxItem.GetOnMeasureWidth: TTBXLMeasureWidth; +begin + Result := FList.OnMeasureWidth; +end; + +function TTBXComboBoxItem.GetShowListImages: Boolean; +begin + Result := FList.ShowImages; +end; + +function TTBXComboBoxItem.GetStringListClass: TTBXStringListClass; +begin + Result := TTBXStringList; +end; + +function TTBXComboBoxItem.GetStrings: TStrings; +begin + Result := FList.Strings; +end; + +procedure TTBXComboBoxItem.HandleEditChange(Edit: TEdit); +begin + CacheValid := False; + inherited; +end; + +procedure TTBXComboBoxItem.ListChangeHandler(Sender: TObject); +begin + CacheValid := False; + DoListChange; +end; + +procedure TTBXComboBoxItem.ListClickHandler(Sender: TObject); +begin + CacheValid := False; + DoListClick; +end; + +procedure TTBXComboBoxItem.Loaded; +begin + inherited; + if FList.Strings.IndexOf(Text) >= 0 then + begin + IsChanging := True; + try + FList.ItemIndex := FList.Strings.IndexOf(Text); + finally + IsChanging := False; + end; + end; + if not (csDesigning in ComponentState) then Add(FList); +end; + +procedure TTBXComboBoxItem.SetItemIndex(Value: Integer); +begin + FList.ItemIndex := Value; +end; + +procedure TTBXComboBoxItem.SetMaxVisibleItems(Value: Integer); +begin + FList.MaxVisibleItems := Value; +end; + +procedure TTBXComboBoxItem.SetMaxWidth(Value: Integer); +begin + FList.MaxWidth := Value; +end; + +procedure TTBXComboBoxItem.SetMinWidth(Value: Integer); +begin + FList.MinWidth := Value; +end; + +procedure TTBXComboBoxItem.SetOnClearItem(Value: TTBXLPaintEvent); +begin + FList.OnClearItem := Value; +end; + +procedure TTBXComboBoxItem.SetOnDrawItem(Value: TTBXLPaintEvent); +begin + FList.OnDrawItem := Value; +end; + +procedure TTBXComboBoxItem.SetOnMeasureHeight(Value: TTBXLMeasureHeight); +begin + FList.OnMeasureHeight := Value; +end; + +procedure TTBXComboBoxItem.SetOnMeasureWidth(Value: TTBXLMeasureWidth); +begin + FList.OnMeasureWidth := Value; +end; + +procedure TTBXComboBoxItem.SetShowListImages(Value: Boolean); +begin + FList.ShowImages := Value; +end; + +procedure TTBXComboBoxItem.SetStrings(Value: TStrings); +begin + FList.Strings := Value; +end; + + +//============================================================================// + +{ TTBXComboBoxItemViewer } + +function TTBXComboBoxItemViewer.HandleEditMessage(var Message: TMessage): Boolean; +begin + if (Message.Msg = WM_KEYDOWN) then with TTBXComboBoxItem(Item) do + begin + case Message.wParam of + VK_UP: + begin + ItemIndex := ItemIndex - 1; + EditControl.Text := Text; + EditControl.SelectAll; + Result := True; + end; + + VK_DOWN: + begin + ItemIndex := ItemIndex + 1; + EditControl.Text := Text; + EditControl.SelectAll; + Result := True; + end; + else + Result := inherited HandleEditMessage(Message); + end + end + else Result := inherited HandleEditMessage(Message); +end; + + +//============================================================================// + +{ TTBXLabelItem } + +constructor TTBXLabelItem.Create(AOwner: TComponent); +begin + inherited; + FFontSettings := TFontSettings.Create; + TFontSettingsAccess(FFontSettings).OnChange := FontSettingsChanged; + FShowAccelChar := True; + ItemStyle := ItemStyle - [tbisSelectable] + [tbisClicksTransparent, tbisStretch]; +end; + +destructor TTBXLabelItem.Destroy; +begin + FFontSettings.Free; + inherited; +end; + +procedure TTBXLabelItem.FontSettingsChanged(Sender: TObject); +begin + Change(True); +end; + +function TTBXLabelItem.GetItemViewerClass(AView: TTBView): TTBItemViewerClass; +begin + Result := TTBXLabelItemViewer; +end; + +procedure TTBXLabelItem.SetCaption(const Value: TCaption); +begin + FCaption := Value; + Change(True); +end; + +procedure TTBXLabelItem.SetFontSettings(Value: TFontSettings); +begin + FFontSettings := Value; +end; + +{procedure TTBXLabelItem.SetFontSize(Value: TTBXFontSize); +begin + FFontSize := Value; + Change(True); +end; } + +procedure TTBXLabelItem.SetMargin(Value: Integer); +begin + FMargin := Value; + Change(True); +end; + +procedure TTBXLabelItem.SetOrientation(Value: TTBXLabelOrientation); +begin + FOrientation := Value; + Change(True); +end; + +procedure TTBXLabelItem.SetShowAccelChar(Value: Boolean); +begin + FShowAccelChar := Value; + Change(True); +end; + +procedure TTBXLabelItem.UpdateCaption(const Value: TCaption); +begin + FCaption := Value; + Change(False); +end; + + +//============================================================================// + +{ TTBXLabelItemViewer } + +procedure TTBXLabelItemViewer.CalcSize(const Canvas: TCanvas; var AWidth, AHeight: Integer); +var + DC: HDC; + S: string; + TextMetrics: TTextMetric; + RotatedFont, SaveFont: HFont; +begin + Canvas.Font := TTBViewAccess(View).GetFont; + DoAdjustFont(Canvas.Font, 0); + S := GetCaptionText; + if Length(S) = 0 then S := '0'; + DC := Canvas.Handle; + if IsToolbarStyle then + begin + AWidth := TTBXLabelItem(Item).Margin; + AHeight := AWidth; + if Length(S) > 0 then + begin + if GetIsHoriz then + begin + GetTextMetrics(DC, TextMetrics); + Inc(AHeight, TextMetrics.tmHeight); + Inc(AWidth, GetTextWidth(DC, S, TTBXLabelItem(Item).ShowAccelChar)); + end + else + begin + RotatedFont := CreateRotatedFont(DC); + SaveFont := SelectObject(DC, RotatedFont); + GetTextMetrics(DC, TextMetrics); + Inc(AWidth, TextMetrics.tmHeight); + Inc(AHeight, GetTextWidth(DC, S, TTBXLabelItem(Item).ShowAccelChar)); + SelectObject(DC, SaveFont); + DeleteObject(RotatedFont); + end; + end; + end + else + begin + if Length(S) > 0 then + begin + GetTextMetrics(DC, TextMetrics); + AHeight := TextMetrics.tmHeight; + AWidth := GetTextWidth(DC, S, TTBXLabelItem(Item).ShowAccelChar); + end; + end; + + if AWidth < 6 then AWidth := 6; + if AHeight < 6 then AHeight := 6; + with TTBXLabelItem(Item) do + begin + Inc(AWidth, Margin shl 1 + 1); + Inc(AHeight, Margin shl 1 + 1); + end; +end; + +procedure TTBXLabelItemViewer.DoAdjustFont(AFont: TFont; StateFlags: Integer); +begin + if Item is TTBXLabelItem then + with TTBXLabelItem(Item) do + begin + FontSettings.Apply(AFont); + if Assigned(FOnAdjustFont) then FOnAdjustFont(Item, Self, AFont, StateFlags); + end; +end; + +function TTBXLabelItemViewer.GetCaptionText: string; +var + P: Integer; +begin + Result := TTBXLabelItem(Item).Caption; + P := Pos(#9, Result); + if P <> 0 then SetLength(Result, P - 1); +end; + +function TTBXLabelItemViewer.GetIsHoriz: Boolean; +begin + with TTBXLabelItem(Item) do + case Orientation of + tbxoHorizontal: Result := True; + tbxoVertical: Result := False; + else // tbxoAuto + Result := View.Orientation <> tbvoVertical; + end; +end; + +function TTBXLabelItemViewer.IsToolbarSize: Boolean; +begin + Result := inherited IsToolbarSize; + Result := Result or ((GetViewType(View) and PVT_TOOLBOX) = PVT_TOOLBOX); +end; + +function TTBXLabelItemViewer.IsToolbarStyle: Boolean; +begin + Result := inherited IsToolbarStyle; + Result := Result or ((GetViewType(View) and PVT_TOOLBOX) = PVT_TOOLBOX); +end; + +procedure TTBXLabelItemViewer.Paint(const Canvas: TCanvas; + const ClientAreaRect: TRect; IsHoverItem, IsPushed, UseDisabledShadow: Boolean); +const + CEnabledStates: array [Boolean] of Integer = (ISF_DISABLED, 0); + CDesigning: array [Boolean] of Integer = (0, IO_DESIGNING); + CPrefixes: array [Boolean] of Integer = (DT_NOPREFIX, 0); +var + Fmt: Cardinal; + ItemInfo: TTBXItemInfo; + R: TRect; +begin + FillChar(ItemInfo, SizeOf(ItemInfo), 0); + ItemInfo.ViewType := GetViewType(View); + ItemInfo.ItemOptions := IO_TOOLBARSTYLE or CDesigning[csDesigning in Item.ComponentState]; + ItemInfo.Enabled := Item.Enabled or View.Customizing; + ItemInfo.Pushed := False; + ItemInfo.Selected := False; + ItemInfo.ImageShown := False; + ItemInfo.ImageWidth := 0; + ItemInfo.ImageHeight := 0; + ItemInfo.HoverKind := hkNone; + ItemInfo.IsPopupParent := False; + ItemInfo.IsVertical := not GetIsHoriz; + + Canvas.Font := TTBViewAccess(View).GetFont; + Canvas.Font.Color := CurrentTheme.GetItemTextColor(ItemInfo); + DoAdjustFont(Canvas.Font, CEnabledStates[ItemInfo.Enabled]); + Canvas.Brush.Style := bsClear; + Fmt := DT_SINGLELINE or DT_CENTER or DT_VCENTER or CPrefixes[TTBXLabelItem(Item).ShowAccelChar]; + R := ClientAreaRect; + CurrentTheme.PaintCaption(Canvas, R, ItemInfo, GetCaptionText, Fmt, ItemInfo.IsVertical); + Canvas.Brush.Style := bsSolid; +end; + + +//============================================================================// + +{ TTBXColorItem } + +constructor TTBXColorItem.Create(AOwner: TComponent); +begin + inherited; + FColor := clWhite; +end; + +function TTBXColorItem.GetItemViewerClass(AView: TTBView): TTBItemViewerClass; +begin + Result := TTBXColorItemViewer; +end; + +procedure TTBXColorItem.SetColor(Value: TColor); +begin + if FColor <> Value then + begin + FColor := Value; + Change(False); + end; +end; + + +//============================================================================// + +{ TTBXColorItemViewer } + +procedure TTBXColorItemViewer.DrawItemImage(Canvas: TCanvas; ARect: TRect; ItemInfo: TTBXItemInfo); +begin + with ItemInfo, Canvas do if Enabled then + begin + if ((ItemOptions and IO_TOOLBARSTYLE) = 0) then InflateRect(ARect, -2, -2); + if TTBXColorItem(Item).Color <> clNone then + begin + Brush.Color := clBtnShadow; + FrameRect(ARect); + InflateRect(ARect, -1, -1); + Brush.Color := TTBXColorItem(Item).Color; + FillRect(ARect); + end; + end + else + begin + Inc(ARect.Right); + Inc(ARect.Bottom); + DrawEdge(Handle, ARect, BDR_SUNKENOUTER or BDR_RAISEDINNER, BF_RECT); + end; +end; + +procedure TTBXColorItemViewer.DoPaintCaption(Canvas: TCanvas; + const ClientAreaRect: TRect; var CaptionRect: TRect; + IsTextRotated: Boolean; var PaintDefault: Boolean); +begin + if (GetViewType(View) and PVT_TOOLBOX) = PVT_TOOLBOX then + begin + { Center Caption } + OffsetRect(CaptionRect, -CaptionRect.Left, 0); + OffsetRect(CaptionRect, (ClientAreaRect.Right - CaptionRect.Right) div 2, 0); + end; +end; + +function TTBXColorItemViewer.GetImageSize: TSize; +begin + if IsToolbarStyle then + begin + Result.CX := 12; + Result.CY := 12; + end + else + begin + Result.CX := 16; + Result.CY := 16; + end; +end; + +function TTBXColorItemViewer.GetImageShown: Boolean; +begin + Result := ((Item.DisplayMode in [nbdmDefault, nbdmImageAndText]) or + (IsToolbarStyle and (Item.DisplayMode = nbdmTextOnlyInMenus))); +end; + +constructor TTBXColorItemViewer.Create(AView: TTBView; AItem: TTBCustomItem; AGroupLevel: Integer); +begin + inherited; + Wide := False; +end; + +//============================================================================// + +{ TTBXMRUList } + +function TTBXMRUList.GetFirstKey:Integer; +begin + Result := FKeyShift; +end; + +function TTBXMRUList.GetItemClass: TTBCustomItemClass; +begin + Result := TTBXCustomItem; +end; + +procedure TTBXMRUList.SetItemCaptions; +var + I: Integer; +begin + inherited; + if Container is TTBXCustomItem then + for I := 0 to Items.Count - 1 do + TTBXCustomItem(Items[I]).FontSettings := TTBXCustomItem(Container).FontSettings; +end; + +procedure TTBXMRUList.SetKeyShift(Value: Integer); +begin + if Value < 0 then Value := 0; + FKeyShift := Value; + SetItemCaptions; +end; + + +//============================================================================// + +{ TTBXMRUListItem } + +constructor TTBXMRUListItem.Create(AOwner: TComponent); +begin + inherited; + ItemStyle := ItemStyle + [tbisEmbeddedGroup]; + Caption := STBMRUListItemDefCaption[1] + 'TBX ' + + Copy(STBMRUListItemDefCaption, 2, Length(STBMRUListItemDefCaption) - 1); +end; + +procedure TTBXMRUListItem.Notification(AComponent: TComponent; + Operation: TOperation); +begin + inherited; + if (AComponent = FMRUList) and (Operation = opRemove) then MRUList := nil; +end; + +procedure TTBXMRUListItem.SetMRUList(Value: TTBMRUList); +begin + if FMRUList <> Value then + begin + FMRUList := Value; + if Assigned(Value) then + begin + Value.FreeNotification(Self); + LinkSubitems := TTBMRUListAccess(Value).Container; + end + else LinkSubitems := nil; + end; +end; + +{ TTBXCustomSpinEditItem } + +function TTBXCustomSpinEditItem.CheckValue(const V: Extended): Extended; +begin + Result := V; + if FMaxValue <> FMinValue then + begin + if V < FMinValue then Result := FMinValue + else if V > FMaxValue then Result := FMaxValue; + end; +end; + +procedure TTBXCustomSpinEditItem.ClickDown; +var + OldValue, NewValue: Extended; +begin + OldValue := GetValue; + if Snap then + NewValue := Ceil(OldValue / Increment - 1 - Increment * 0.0001) * Increment + else + NewValue := OldValue - FIncrement; + DoStep(-1, OldValue, NewValue); + SetValueEx(NewValue, tcrSpinButton); +end; + +procedure TTBXCustomSpinEditItem.ClickUp; +var + OldValue, NewValue: Extended; +begin + OldValue := GetValue; + if Snap then + NewValue := Floor(OldValue / Increment + 1 + Increment * 0.0001) * Increment + else + NewValue := OldValue + FIncrement; + DoStep(+1, OldValue, NewValue); + SetValueEx(NewValue, tcrSpinButton); +end; + +constructor TTBXCustomSpinEditItem.Create(AOwner: TComponent); +begin + inherited; + FAlignment := taRightJustify; + FDecimal := 2; + FIncrement := 1; + FSnap := True; + Text := '0'; +end; + +function TTBXCustomSpinEditItem.DoAcceptText(var NewText: string): Boolean; +var + V: Extended; +begin + if ParseValue(NewText, V) then + begin + NewText := GetAsText(V); + Result := True; + end + else Result := False; +end; + +function TTBXCustomSpinEditItem.DoConvert(const APrefix, APostfix: string; var AValue: Extended): Boolean; +begin + Result := True; + if Assigned(FOnConvert) then FOnConvert(Self, APrefix, APostfix, AValue, Result); +end; + +procedure TTBXCustomSpinEditItem.DoStep(Step: Integer; const OldValue: Extended; var NewValue: Extended); +begin + if Assigned(FOnStep) then FOnStep(Self, Step, OldValue, NewValue); +end; + +procedure TTBXCustomSpinEditItem.DoTextChanged(Reason: Integer); +begin + if Reason = tcrEditControl then + SetValueEx(GetValue, tcrNumericProperty); +end; + +function TTBXCustomSpinEditItem.DoTextToValue(const AText: string; out AValue: Extended): Boolean; +begin + Result := False; + if Assigned(FOnTextToValue) then FOnTextToValue(Self, AText, AValue, Result); +end; + +procedure TTBXCustomSpinEditItem.DoValueChange(const V: Extended); +begin + if Assigned(FOnValueChange) then FOnValueChange(Self, V); +end; + +procedure TTBXCustomSpinEditItem.DoValueToText(const NewValue: Extended; var NewText: string); +begin + if Assigned(FOnValueToText) then FOnValueToText(Self, NewValue, NewText); +end; + +function TTBXCustomSpinEditItem.GetAsInteger: Integer; +begin + Result := Round(Value); +end; + +function TTBXCustomSpinEditItem.GetAsText(AValue: Extended): string; +begin + AValue := CheckValue(AValue); + if ValueType = evtFloat then Result := FloatToStrF(AValue, ffFixed, 15, FDecimal) + else if ValueType = evtHex then Result := IntToHex(Round(AValue), 1) + else Result := IntToStr(Round(AValue)); + + if Length(Prefix) > 0 then + begin + if SpaceAfterPrefix then Result := ' ' + Result; + Result := Prefix + Result; + end; + if Length(Postfix) > 0 then + begin + if SpaceBeforePostfix then Result := Result + ' '; + Result := Result + Postfix; + end; + DoValueToText(AValue, Result); +end; + +function TTBXCustomSpinEditItem.GetItemViewerClass(AView: TTBView): TTBItemViewerClass; +begin + if not (tboUseEditWhenVertical in EditOptions) and + (AView.Orientation = tbvoVertical) then + Result := TTBXItemViewer + else + Result := TTBXSpinEditViewer; +end; + +function TTBXCustomSpinEditItem.GetValue: Extended; +begin + if not ParseValue(Text, Result) then + Result := FLastGoodValue; +end; + +function TTBXCustomSpinEditItem.IsIncrementStored: Boolean; +begin + Result := FIncrement <> 1; +end; + +function TTBXCustomSpinEditItem.IsMaxValueStored: Boolean; +begin + Result := FMaxValue <> 0; +end; + +function TTBXCustomSpinEditItem.IsMinValueStored: Boolean; +begin + Result := FMinValue <> 0; +end; + +function TTBXCustomSpinEditItem.IsValueStored: Boolean; +begin + Result := GetValue <> 0; +end; + +function TTBXCustomSpinEditItem.ParseValue(const S: string; out V: Extended): Boolean; +const + CWhiteSpace = [' ', #9]; + CDigits = ['0'..'9']; + CHexDigits = CDigits + ['A'..'F']; + CInvalidUnitChars = [#0..#31, ' ', '*', '+', ',', '-', '.', '/', '0'..'9', '^']; + CInvalidHexUnitChars = CInvalidUnitChars + ['A'..'F']; +var + P: PChar; + Sign1: Integer; + Value1: Extended; + Value2: Extended; + Operator: Char; + PrefixString, PostfixString: string; + + procedure SkipWhiteSpace; + begin + while P^ in CWhiteSpace do Inc(P); + end; + + function GetInt: Integer; + begin + Result := 0; + while P^ in CDigits do + begin + Result := Result * 10 + (Integer(P^) - Integer('0')); + Inc(P); + end; + end; + + function GetInt2: Extended; + begin + Result := 0; + while P^ in CDigits do + begin + Result := Result * 10 + (Integer(P^) - Integer('0')); + Inc(P); + end; + end; + + function GetNumber(out PrefixString, PostfixString: string; out R: Extended): Boolean; + var + PStart: PChar; + Tmp: Integer; + ExponentSign, IR: Integer; + Count1, Count2: Integer; + E: Extended; + begin + R := 0; + Result := False; + + { Read prefix } + PStart := P; + if ValueType <> evtHex then while not (P^ in CInvalidUnitChars) do Inc(P) + else while not (P^ in CInvalidHexUnitChars) do Inc(P); + SetString(PrefixString, PStart, P - PStart); + SkipWhiteSpace; + + { Read value } + if ValueType in [evtFloat, evtInteger] then + begin + if (ValueType = evtInteger) and not (P^ in CDigits) then Exit; + + { get the integer part } + PStart := P; + R := GetInt2; + Count1 := P - PStart; + + if (ValueType = evtFloat) and (P^ = DecimalSeparator) then + begin + Inc(P); + PStart := P; + E := GetInt2; + R := R + E / IntPower(10, P - PStart); + Count2 := P - PStart; + end + else Count2 := 0; + + if (Count1 = 0) and (Count2 = 0) then Exit; // '.' (or ',') is not a number + + if (ValueType = evtFloat) and (P^ in ['e', 'E']) and (PChar(P + 1)^ in ['+', '-', '0'..'9']) then + begin + Inc(P); + ExponentSign := 1; + if P^ = '-' then + begin + ExponentSign := -1; + Inc(P); + end + else if P^ = '+' then Inc(P); + if not (P^ in CDigits) then Exit; + Tmp := GetInt; + if Tmp >= 5000 then Exit; + R := R * IntPower(10, Tmp * ExponentSign); + end; + end + else { evtHex } + begin + IR := 0; + if not (P^ in CHexDigits) then Exit; + while P^ in CHexDigits do + begin + IR := IR shl 4; + if P^ in CDigits then Inc(IR, Integer(P^) - Integer('0')) + else if P^ in ['a'..'f'] then Inc(IR, Integer(P^) - Integer('a') + 10) + else Inc(IR, Integer(P^) - Integer('A') + 10); + Inc(P); + end; + R := IR; + end; + SkipWhiteSpace; + + { Read postfix } + PStart := P; + if ValueType <> evtHex then while not (P^ in CInvalidUnitChars) do Inc(P) + else while not (P^ in CInvalidHexUnitChars) do Inc(P); + SetString(PostfixString, PStart, P - PStart); + SkipWhiteSpace; + + Result := True; + end; + +begin + V := 0; + + { Try text-to-value conversion for predefined "constants" } + Result := DoTextToValue(S, V); + if Result then Exit; + + { Parse the string for values and expressions } + if Length(S) = 0 then Exit; + P := PChar(S); + SkipWhiteSpace; + + { Read the sign } + Sign1 := 1; + if P^ = '-' then + begin + Sign1 := -1; + Inc(P); + SkipWhiteSpace; + end + else if P^ = '+' then + begin + Inc(P); + SkipWhiteSpace; + end; + + { Read value } + if not GetNumber(PrefixString, PostfixString, Value1) then Exit; + if not DoConvert(PrefixString, PostfixString, Value1) then Exit; + Value1 := Value1 * Sign1; + V := Value1; + + { Read operator } + if P^ in ['*', '+', '-', '/'] then + begin + Operator := P^; + Inc(P); + SkipWhiteSpace; + if not GetNumber(PrefixString, PostfixString, Value2) then Exit; + if not DoConvert(PrefixString, PostfixString, Value2) then Exit; + case Operator of + '*': V := V * Value2; + '+': V := V + Value2; + '-': V := V - Value2; + '/': if Value2 <> 0 then V := V / Value2 else Exit; + end; + end; + + if P^ = #0 then Result := True; +end; + +procedure TTBXCustomSpinEditItem.SetAsInteger(AValue: Integer); +begin + Value := AValue; +end; + +procedure TTBXCustomSpinEditItem.SetDecimal(NewDecimal: TDecimal); +begin + if NewDecimal <> FDecimal then + begin + FDecimal := NewDecimal; + SetValueEx(GetValue, tcrNumericProperty); + end; +end; + +procedure TTBXCustomSpinEditItem.SetIncrement(const NewIncrement: Extended); +begin + if NewIncrement <= 0 then + raise EPropertyError.Create('Increment should be a positive value'); + FIncrement := NewIncrement; +end; + +procedure TTBXCustomSpinEditItem.SetPostfix(const NewPostfix: string); +begin + if not ValidateUnits(NewPostfix) then + raise EPropertyError.Create('Invalid postfix'); + FPostfix := NewPostfix; + SetValueEx(GetValue, tcrNumericProperty); +end; + +procedure TTBXCustomSpinEditItem.SetPrefix(const NewPrefix: string); +begin + if not ValidateUnits(NewPrefix) then + raise EPropertyError.Create('Invalid prefix'); + FPrefix := NewPrefix; + SetValueEx(GetValue, tcrNumericProperty); +end; + +procedure TTBXCustomSpinEditItem.SetSpaceAfterPrefix(UseSpace: Boolean); +begin + FSpaceAfterPrefix := UseSpace; + SetValueEx(GetValue, tcrNumericProperty); +end; + +procedure TTBXCustomSpinEditItem.SetSpaceBeforePostfix(UseSpace: Boolean); +begin + FSpaceBeforePostfix := UseSpace; + SetValueEx(GetValue, tcrNumericProperty); +end; + +procedure TTBXCustomSpinEditItem.SetValue(NewValue: Extended); +begin + SetTextEx(GetAsText(NewValue), tcrNumericProperty); + if FLastGoodValue <> NewValue then + begin + FLastGoodValue := NewValue; + DoValueChange(NewValue); + end; +end; + +procedure TTBXCustomSpinEditItem.SetValueEx(NewValue: Extended; Reason: Integer); +begin + SetTextEx(GetAsText(NewValue), Reason); + if FLastGoodValue <> NewValue then + begin + FLastGoodValue := NewValue; + DoValueChange(NewValue); + end; +end; + +procedure TTBXCustomSpinEditItem.SetValueType(NewType: TSEValueType); +var + V: Extended; +begin + if NewType <> FValueType then + begin + V := GetValue; + FValueType := NewType; + SetValueEx(V, tcrNumericProperty); + if NewType in [evtInteger, evtHex] then FIncrement := Max(Round(FIncrement), 1); + end; +end; + +function TTBXCustomSpinEditItem.ValidateUnits(const S: string): Boolean; +const + InvalidChars = [#0..#31, ' ', '*', '+', ',', '-', '.', '/', '0'..'9', '^']; +var + I: Integer; +begin + Result := False; + if Length(S) > 0 then + for I := 1 to Length(S) do + if S[I] in InvalidChars then Exit; + Result := True; +end; + +{ TTBXSpinEditViewer } + +destructor TTBXSpinEditViewer.Destroy; +begin + FBtnTimer.Free; + inherited; +end; + +procedure TTBXSpinEditViewer.GetEditInfo(out EditInfo: TTBXEditInfo; const ItemInfo: TTBXItemInfo); +const + CDisabled: array [Boolean] of Integer = (EBSS_DISABLED, 0); + CHot: array [Boolean] of Integer = (0, EBSS_HOT); + CUpDnState: array [TSEBtnState] of Integer = (0, EBSS_UP, EBSS_DOWN); +begin + inherited GetEditInfo(EditInfo, ItemInfo); + EditInfo.RightBtnInfo.ButtonType := EBT_SPIN; + EditInfo.RightBtnInfo.ButtonState := CDisabled[ItemInfo.Enabled] or + CHot[ItemInfo.HoverKind = hkMouseHover] or CUpDnState[FBtnState]; +end; + +function TTBXSpinEditViewer.GetIndentAfter: Integer; +begin + if IsToolbarStyle then Result := CurrentTheme.EditBtnWidth + 2 + else Result := GetSystemMetrics(SM_CXMENUCHECK) + 2; +end; + +function TTBXSpinEditViewer.HandleEditMessage(var Message: TMessage): Boolean; +var + Item: TTBXCustomSpinEditItem; + + function Val: Extended; + begin + if not Item.ParseValue(EditControl.Text, Result) then Result := Item.FLastGoodValue; + end; + +begin + Item := TTBXCustomSpinEditItem(Self.Item); + if Message.Msg = WM_CHAR then + case TWMChar(Message).CharCode of + VK_TAB: + begin + Item.Value := Val; + EditControl.Text := Item.Text; + end; + VK_RETURN: + begin + Item.Value := Val; + EditControl.Text := Item.Text; + end; + VK_ESCAPE: + begin +// Item.Value := Item.GetValue; + end; + end + else if Message.Msg = WM_KEYDOWN then + case TWMKeyDown(Message).CharCode of + VK_UP: + begin + Item.ClickUp; + EditControl.Text := Item.Text; + EditControl.SelectAll; + Result := True; + Exit; + end; + VK_DOWN: + begin + Item.ClickDown; + EditControl.Text := Item.Text; + EditControl.SelectAll; + Result := True; + Exit; + end; + end; + + Result := inherited HandleEditMessage(Message); +end; + +procedure TTBXSpinEditViewer.InvalidateButtons; +var + R: TRect; +begin + with TTBXSpinEditItem(Item) do + if Show and not IsRectEmpty(BoundsRect) then + begin + R := BoundsRect; + R.Left := R.Right - GetIndentAfter; + InvalidateRect(View.Window.Handle, @R, False); + Include(State, tbisInvalidated); + end; +end; + +function TTBXSpinEditViewer.IsPtInButtonPart(X, Y: Integer): Boolean; +begin + Result := X <= (BoundsRect.Right - BoundsRect.Left) - GetIndentAfter; +end; + +procedure TTBXSpinEditViewer.LosingCapture; +begin + FBtnTimer.Free; + FBtnTimer := nil; + inherited; +end; + +procedure TTBXSpinEditViewer.MouseDown(Shift: TShiftState; X, Y: Integer; var MouseDownOnMenu: Boolean); +begin + if not Item.Enabled then Exit; + FBtnState := ebsNone; + if X >= BoundsRect.Right - BoundsRect.Left - GetIndentAfter then + begin + if Y < (BoundsRect.Bottom - BoundsRect.Top) div 2 then + begin + FBtnState := ebsUp; + TTBXSpinEditItem(Item).ClickUp; + end + else + begin + FBtnState := ebsDown; + TTBXSpinEditItem(Item).ClickDown; + end; + + if FBtnTimer = nil then + begin + FBtnTimer := TTimer.Create(nil); + FBtnTimer.OnTimer := TimerHandler; + end; + FBtnTimer.Interval := SE_FIRSTINTERVAL; + FBtnTimer.Enabled := True; + end; + + if FBtnState <> ebsNone then + begin + InvalidateButtons; + inherited; + View.SetCapture; + end + else inherited; +end; + +procedure TTBXSpinEditViewer.MouseUp(X, Y: Integer; MouseWasDownOnMenu: Boolean); +begin + if FBtnState <> ebsNone then + begin + FBtnState := ebsNone; + FBtnTimer.Free; + FBtnTimer := nil; + InvalidateButtons; + end; + inherited; +end; + +procedure TTBXSpinEditViewer.TimerHandler(Sender: TObject); +begin + FBtnTimer.Interval := SE_INTERVAL; + if FBtnState = ebsUp then TTBXSpinEditItem(Item).ClickUp + else if FBtnState = ebsDown then TTBXSpinEditItem(Item).ClickDown + else + begin + FBtnTimer.Free; + FBtnTimer := nil; + end; +end; + +end. diff --git a/official/2.1.6+2.1.beta1/TBX/TBXLists.pas b/official/2.1.6+2.1.beta1/TBX/TBXLists.pas new file mode 100644 index 0000000..7ff67c1 --- /dev/null +++ b/official/2.1.6+2.1.beta1/TBX/TBXLists.pas @@ -0,0 +1,1387 @@ +unit TBXLists; + +// TBX Package +// Copyright 2001-2004 Alex A. Denisov. All Rights Reserved +// See TBX.chm for license and installation instructions +// +// $Id: TBXLists.pas 7 2004-02-21 06:07:53Z $ + +interface + +{$I ..\..\Source\TB2Ver.inc} +{$I TBX.inc} + +uses + Windows, Messages, Classes, SysUtils, Controls, Forms, Graphics, TB2Item, TBX, + TBXThemes, TBXUxThemes, ImgList; + +type + { TTBXScrollBar } + + TSBIncrement = 1..1000; + TSBZone = (sbzEmpty, sbzPrev, sbzPagePrev, sbzHandle, sbzPageNext, sbzNext); + TSBAutoScrollEvent = procedure(Sender: TObject; var Direction, Interval: Integer) of object; + + TTBXScrollBar = class + private + FBounds: TRect; + FLeft: Integer; + FHandle: HWND; + FHeight: Integer; + FIncrement: TSBIncrement; + FKind: TScrollBarKind; + FPosition: Integer; + FRange: Integer; + FRight: Integer; + FTop: Integer; + FWidth: Integer; + FWindow: Integer; + FOnChange: TNotifyEvent; + FOnAutoScroll: TSBAutoScrollEvent; + FOnRedrawRequest: TNotifyEvent; + procedure SetBounds(const Value: TRect); + procedure SetKind(Value: TScrollBarKind); + procedure SetPosition(Value: Integer); + procedure SetRange(Value: Integer); + function GetHandle: HWND; + protected + AutoScrollDirection: Integer; + AutoScrolling: Boolean; + AutoScrollInterval: Integer; + Zones: array [TSBZone] of TRect; + MouseDownZone: TSBZone; + MouseDownPoint: TPoint; + MouseDownPosition: Integer; + LastMousePoint: TPoint; + PrevCapture: HWND; + UserChange: Boolean; + procedure AdjustPosition(var NewPosition: Integer); + procedure CreateWnd; + procedure DestroyWnd; + function GetZone(X, Y: Integer): TSBZone; + function GetEffectiveWindow: Integer; + function GetEnabled: Boolean; virtual; + procedure HandleZoneClick(AZone: TSBZone); + procedure MouseDown(Button: TMouseButton; X, Y: Integer); virtual; + procedure MouseMove(X, Y: Integer); virtual; + procedure MouseUp(Button: TMouseButton; X, Y: Integer); virtual; + procedure PaintButton(Canvas: TCanvas; Rect: TRect; Direction: Integer; Pushed, Enabled: Boolean); + procedure PaintHandle(Canvas: TCanvas; Rect: TRect; Pushed, Enabled: Boolean); + procedure PaintTrack(Canvas: TCanvas; Rect: TRect; IsNextZone, Pushed, Enabled: Boolean); + procedure PaintTo(Canvas: TCanvas); + procedure SBWndProc(var Message: TMessage); + procedure StartAutoScroll(Direction, Interval: Integer); + procedure StopAutoScroll; + procedure StartTimer(ID: Integer; Elapse: Integer); + procedure StopTimer(ID: Integer); + procedure TimerElapsed(ID: Integer; var NewElapse: Integer); virtual; + procedure UpdateZones; + property Handle: HWND read GetHandle; + public + constructor Create; + destructor Destroy; override; + procedure Redraw; virtual; + procedure UpdatePosition(NewPosition: Integer); + property Kind: TScrollBarKind read FKind write SetKind; + property Bounds: TRect read FBounds write SetBounds; + property Left: Integer read FLeft; + property Height: Integer read FHeight; + property Increment: TSBIncrement read FIncrement write FIncrement; + property Position: Integer read FPosition write SetPosition; + property Range: Integer read FRange write SetRange; + property Right: Integer read FRight; + property Top: Integer read FTop; + property Width: Integer read FWidth; + property Window: Integer read FWindow write FWindow; + property OnAutoScroll: TSBAutoScrollEvent read FOnAutoScroll write FOnAutoScroll; + property OnChange: TNotifyEvent read FOnChange write FOnChange; + property OnRedrawRequest: TNotifyEvent read FOnRedrawRequest write FOnRedrawRequest; + end; + + { TTBXCustomList } + TTBXCustomList = class; + + TTBXLMeasureHeight = procedure(Sender: TTBXCustomList; ACanvas: TCanvas; var AHeight: Integer) of object; + TTBXLMeasureWidth = procedure(Sender: TTBXCustomList; ACanvas: TCanvas; AIndex: Integer; var AWidth: Integer) of object; + TTBXLPaintEvent = procedure(Sender: TTBXCustomList; ACanvas: TCanvas; ARect: TRect; AIndex, AHoverIndex: Integer; var DrawDefault: Boolean) of object; + TTBXLAdjustImageIndex = procedure(Sender: TTBXCustomList; AItemIndex: Integer; var ImageIndex: Integer) of object; + + TTBXCustomListViewer = class; + + TTBXCustomList = class(TTBXCustomItem) + private + FViewers: TList; + FItemIndex: Integer; + FMinWidth: Integer; + FMaxWidth: Integer; + FMaxVisibleItems: Integer; + FShowImages: Boolean; + FOnChange: TNotifyEvent; + FOnClearItem: TTBXLPaintEvent; + FOnDrawItem: TTBXLPaintEvent; + FOnAdjustImageIndex: TTBXLAdjustImageIndex; + FOnMeasureHeight: TTBXLMeasureHeight; + FOnMeasureWidth: TTBXLMeasureWidth; + procedure SetItemIndex(Value: Integer); + protected + function DoClearItem(ACanvas: TCanvas; ARect: TRect; AIndex, AHoverIndex: Integer): Boolean; virtual; + function DoDrawItem(ACanvas: TCanvas; ARect: TRect; AIndex, AHoverIndex: Integer): Boolean; virtual; + procedure DoMeasureHeight(ACanvas: TCanvas; var AHeight: Integer); virtual; + procedure DoMeasureWidth(ACanvas: TCanvas; AIndex: Integer; var AWidth: Integer); virtual; + procedure DrawItem(ACanvas: TCanvas; AViewer: TTBXCustomListViewer; const ARect: TRect; AIndex, AHoverIndex: Integer); virtual; + function GetImageIndex(ItemIndex: Integer): Integer; virtual; + function GetItemViewerClass(AView: TTBView): TTBItemViewerClass; override; + function GetItemText(Index: Integer): string; virtual; abstract; + function GetCount: Integer; virtual; abstract; + procedure HandleChange; virtual; + procedure HandleHover(AIndex: Integer); virtual; + procedure Notification(AComponent: TComponent; Operation: TOperation); override; + public + constructor Create(AOwner: TComponent); override; + procedure MakeVisible(AIndex: Integer); + property ItemIndex: Integer read FItemIndex write SetItemIndex default -1; + property MaxVisibleItems: Integer read FMaxVisibleItems write FMaxVisibleItems default 8; + property MaxWidth: Integer read FMaxWidth write FMaxWidth default 0; + property MinWidth: Integer read FMinWidth write FMinWidth default 32; + property ShowImages: Boolean read FShowImages write FShowImages default False; + property OnAdjustImageIndex: TTBXLAdjustImageIndex read FOnAdjustImageIndex write FOnAdjustImageIndex; + property OnChange: TNotifyEvent read FOnChange write FOnChange; + property OnClearItem: TTBXLPaintEvent read FOnClearItem write FOnClearItem; + property OnDrawItem: TTBXLPaintEvent read FOnDrawItem write FOnDrawItem; + property OnMeasureHeight: TTBXLMeasureHeight read FOnMeasureHeight write FOnMeasureHeight; + property OnMeasureWidth: TTBXLMeasureWidth read FOnMeasureWidth write FOnMeasureWidth; + end; + + TTBXCustomListViewer = class(TTBXItemViewer) + private + FItemCount: Integer; + FItemHeight: Integer; + FHoverIndex: Integer; + FHeight: Integer; + FLastClientRect: TRect; + FWheelAccumulator: Integer; + FWidth: Integer; + FOffset: Integer; + FScrollBarWidth: Integer; + FScrollBar: TTBXScrollBar; + FVisibleItems: Integer; + procedure ListChangeHandler(NewIndex: Integer); + procedure SBAutoScrollHandler(Sender: TObject; var Direction, Interval: Integer); + procedure SBChangeHandler(Sender: TObject); + procedure SBRedrawHandler(Sender: TObject); + protected + MouseIsDown: Boolean; + MouseInScrollBar: Boolean; + IgnoreMouseUp: Boolean; + IsChanging: Boolean; + procedure AdjustAutoScrollHover(var AIndex: Integer; Direction: Integer); virtual; + procedure CalcSize(const Canvas: TCanvas; var AWidth, AHeight: Integer); override; + procedure DrawItems(const Canvas: TCanvas; const ClientAreaRect: TRect); + function GetItemIndexAt(X, Y: Integer): Integer; + function GetItemRect(Index: Integer): TRect; + function GetItemHeight(ACanvas: TCanvas): Integer; virtual; + function GetItemWidth(ACanvas: TCanvas; Index: Integer): Integer; virtual; + procedure HandleAutoScroll(var Direction, Interval: Integer); virtual; + procedure KeyDown(var Key: Word; Shift: TShiftState); override; + procedure MakeVisible(Index: Integer); + procedure MouseDown(Shift: TShiftState; X, Y: Integer; var MouseDownOnMenu: Boolean); override; + procedure MouseMove(X, Y: Integer); override; + procedure MouseUp(X, Y: Integer; MouseWasDownOnMenu: Boolean); override; + procedure MouseWheel(WheelDelta: Integer; X, Y: Integer); override; + procedure Paint(const Canvas: TCanvas; const ClientAreaRect: TRect; IsHoverItem, IsPushed, UseDisabledShadow: Boolean); override; + procedure UpdateItems; + property HoverIndex: Integer read FHoverIndex write FHoverIndex; + property Offset: Integer read FOffset; {vb+} + property VisibleItems: Integer read FVisibleItems; {vb+} + public + constructor Create(AView: TTBView; AItem: TTBCustomItem; AGroupLevel: Integer); override; + destructor Destroy; override; + end; + + { TTBXStringList } + + TTBXStringList = class(TTBXCustomList) + private + FStrings: TStrings; + procedure SetStrings(Value: TStrings); + protected + function GetItemText(Index: Integer): string; override; + function GetCount: Integer; override; + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + published + property ItemIndex; + property MaxVisibleItems; + property MaxWidth; + property MinWidth; + property Strings: TStrings read FStrings write SetStrings; + property OnAdjustImageIndex; + property OnChange; + property OnClearItem; + property OnClick; + property OnDrawItem; + property OnMeasureHeight; + property OnMeasureWidth; + end; + + TTBXStringListClass = class of TTBXStringList; + + { TTBXUndoList } + + TTBXUndoList = class(TTBXStringList) + protected + procedure DrawItem(ACanvas: TCanvas; AViewer: TTBXCustomListViewer; const ARect: TRect; AIndex, AHoverIndex: Integer); override; + function GetItemViewerClass(AView: TTBView): TTBItemViewerClass; override; + procedure HandleHover(AIndex: Integer); override; + end; + + TTBXUndoListViewer = class(TTBXCustomListViewer) + protected + procedure AdjustAutoScrollHover(var AIndex: Integer; Direction: Integer); override; + procedure HandleAutoScroll(var Direction, Interval: Integer); override; + end; + +implementation + +type TTBViewAccess = class(TTBView); + +const + SCROLL_TIMER = 1; + AUTO_SCROLL_TIMER = 2; + MIN_SB_HANDLE_SIZE = 8; + + CImageSpacing = 4; + +//----------------------------------------------------------------------------// + +{ TTBXScrollBar } + +procedure TTBXScrollBar.AdjustPosition(var NewPosition: Integer); +var + W: Integer; +begin + W := GetEffectiveWindow; + if NewPosition + W > Range then NewPosition := Range - W; + if NewPosition < 0 then NewPosition := 0; +end; + +constructor TTBXScrollBar.Create; +begin + FIncrement := 1; +end; + +procedure TTBXScrollBar.CreateWnd; +begin + if FHandle = 0 then FHandle := {$IFDEF JR_D6}Classes.{$ENDIF}AllocateHWnd(SBWndProc); +end; + +destructor TTBXScrollBar.Destroy; +begin + DestroyWnd; + inherited; +end; + +procedure TTBXScrollBar.DestroyWnd; +begin + if FHandle <> 0 then + begin + {$IFDEF JR_D6}Classes.{$ENDIF}DeallocateHWnd(FHandle); + FHandle := 0; + end; +end; + +function TTBXScrollBar.GetEffectiveWindow: Integer; +begin + if Window <= 0 then + begin + if Kind = sbVertical then Result := Height + else Result := Width; + end + else Result := Window; +end; + +function TTBXScrollBar.GetEnabled: Boolean; +begin + Result := Range > GetEffectiveWindow; +end; + +function TTBXScrollBar.GetHandle: HWND; +begin + if FHandle = 0 then CreateWnd; + Result := FHandle; +end; + +function TTBXScrollBar.GetZone(X, Y: Integer): TSBZone; +var + I: Integer; + Pt: TPoint; +begin + Pt.X := X; + Pt.Y := Y; + for I := Ord(sbzPrev) to Ord(sbzNext) do + begin + Result := TSBZone(I); + if PtInRect(Zones[Result], Pt) then Exit; + end; + Result := sbzEmpty; +end; + +procedure TTBXScrollBar.HandleZoneClick(AZone: TSBZone); +begin + UserChange := True; + case AZone of + sbzPrev: Position := Position - Increment; + sbzPagePrev: Position := Position - GetEffectiveWindow; + sbzPageNext: Position := Position + GetEffectiveWindow; + sbzNext: Position := Position + Increment; + end; + UserChange := False; +end; + +procedure TTBXScrollBar.MouseDown(Button: TMouseButton; X, Y: Integer); +begin + if Button = mbLeft then + begin + MouseDownZone := GetZone(X, Y); + MouseDownPoint := Point(X, Y); + MouseDownPosition := Position; + LastMousePoint := MouseDownPoint; + if MouseDownZone in [sbzPrev, sbzPagePrev, sbzPageNext, sbzNext] then + begin + HandleZoneClick(MouseDownZone); + StartTimer(SCROLL_TIMER, 500); + end; + Redraw; + end; +end; + +procedure TTBXScrollBar.MouseMove(X, Y: Integer); +var + Delta: Integer; + ClientSize, HandleSize: Integer; +begin + LastMousePoint := Point(X, Y); + if MouseDownZone = sbzHandle then + begin + if Kind = sbVertical then + begin + Delta := Y - MouseDownPoint.Y; + ClientSize := Zones[sbzPageNext].Bottom - Zones[sbzPagePrev].Top; + end + else + begin + Delta := X - MouseDownPoint.X; + ClientSize := Zones[sbzPageNext].Right - Zones[sbzPagePrev].Left; + end; + HandleSize := Round(ClientSize * Window / Range); + if HandleSize < MIN_SB_HANDLE_SIZE then + Delta := Round(Delta * (Range - Window) / (ClientSize - MIN_SB_HANDLE_SIZE)) + else + Delta := Round(Delta * Range / ClientSize); + + if MouseDownPosition + Delta <> Position then + begin + UserChange := True; + Position := MouseDownPosition + Delta; + UserChange := False; + end; + end; +end; + +procedure TTBXScrollBar.MouseUp(Button: TMouseButton; X, Y: Integer); +begin + StopTimer(SCROLL_TIMER); + if Button = mbLeft then + begin + MouseDownZone := sbzEmpty; + Redraw; + end; +end; + +procedure TTBXScrollBar.PaintButton(Canvas: TCanvas; Rect: TRect; + Direction: Integer; Pushed, Enabled: Boolean); +const + DirectionFlags: array [0..3] of Cardinal = (DFCS_SCROLLLEFT, DFCS_SCROLLUP, + DFCS_SCROLLRIGHT, DFCS_SCROLLDOWN); + EnabledFlags: array [Boolean] of Cardinal = (DFCS_INACTIVE, 0); + PushedFlags: array [Boolean] of Cardinal = (0, DFCS_PUSHED or DFCS_FLAT); + + DirectionXPFlags: array [0..3] of Cardinal = (ABS_LEFTNORMAL, ABS_UPNORMAL, + ABS_RIGHTNORMAL, ABS_DOWNNORMAL); +var + StateFlags: Cardinal; +begin + if USE_THEMES then + begin + StateFlags := DirectionXPFlags[Direction]; + if not Enabled then Inc(StateFlags, 3) + else if Pushed then Inc(StateFlags, 2); + DrawThemeBackground(SCROLLBAR_THEME, Canvas.Handle, SBP_ARROWBTN, StateFlags, Rect, nil); + end + else + begin + DrawFrameControl(Canvas.Handle, Rect, DFC_SCROLL, + DirectionFlags[Direction] or EnabledFlags[Enabled] or PushedFlags[Pushed]); + end; +end; + +procedure TTBXScrollBar.PaintHandle(Canvas: TCanvas; Rect: TRect; Pushed, Enabled: Boolean); +const + PartXPFlags: array [TScrollBarKind] of Cardinal = (SBP_THUMBBTNHORZ, SBP_THUMBBTNVERT); +var + StateFlags: Cardinal; +begin + if USE_THEMES then + begin + StateFlags := SCRBS_NORMAL; + if not Enabled then Inc(StateFlags, 3) + else if Pushed then Inc(StateFlags, 2); + DrawThemeBackground(SCROLLBAR_THEME, Canvas.Handle, PartXPFlags[Kind], StateFlags, Rect, nil); + end + else + begin + DrawEdge(Canvas.Handle, Rect, EDGE_RAISED, BF_RECT or BF_ADJUST); + Canvas.Brush.Color := clBtnFace; + Canvas.FillRect(Rect); + end; +end; + +procedure TTBXScrollBar.PaintTo(Canvas: TCanvas); +var + R: TRect; + E, IsVert: Boolean; + I: Integer; + Dummy: TPoint; +begin + UpdateZones; + IsVert := Kind = sbVertical; + E := GetEnabled; + + OffsetWindowOrgEx(Canvas.Handle, -Bounds.Left, -Bounds.Top, Dummy); + try + + if IsVert then I := 1 else I := 0; + PaintButton(Canvas, Zones[sbzPrev], I, MouseDownZone = sbzPrev, E); + PaintButton(Canvas, Zones[sbzNext], I + 2, MouseDownZone = sbzNext, E); + + if not IsRectEmpty(Zones[sbzEmpty]) then + begin + Canvas.Brush.Color := clScrollBar; + Canvas.Brush.Style := bsSolid; + Canvas.FillRect(Zones[sbzEmpty]); + end; + + if not IsRectEmpty(Zones[sbzPagePrev]) or not IsRectEmpty(Zones[sbzPageNext]) then + begin + R := Zones[sbzPagePrev]; + PaintTrack(Canvas, R, False, MouseDownZone = sbzPagePrev, E); + R := Zones[sbzPageNext]; + PaintTrack(Canvas, R, True, MouseDownZone = sbzPageNext, E); + end; + + if not IsRectEmpty(Zones[sbzHandle]) then + PaintHandle(Canvas, Zones[sbzHandle], MouseDownZone = sbzHandle, E); + + finally + OffsetWindowOrgEx(Canvas.Handle, Bounds.Left, Bounds.Top, Dummy); + end; +end; + +procedure TTBXScrollBar.PaintTrack(Canvas: TCanvas; Rect: TRect; + IsNextZone, Pushed, Enabled: Boolean); +const + PartXPFlags: array [Boolean, TScrollBarKind] of Cardinal = + ((SBP_LOWERTRACKHORZ, SBP_LOWERTRACKVERT), (SBP_UPPERTRACKHORZ, SBP_UPPERTRACKVERT)); +var + StateFlags: Cardinal; +begin + if USE_THEMES then + begin + StateFlags := SCRBS_NORMAL; + if not Enabled then Inc(StateFlags, 3) + else if Pushed then Inc(StateFlags, 2); + DrawThemeBackground(SCROLLBAR_THEME, Canvas.Handle, PartXPFlags[IsNextZone, Kind], + StateFlags, Rect, nil); + end + else + begin + if Pushed then Canvas.Brush.Color := cl3DDkShadow + else Canvas.Brush.Bitmap := AllocPatternBitmap(clBtnHighlight, clScrollBar); + Canvas.FillRect(Rect); + end; +end; + +procedure TTBXScrollBar.Redraw; +begin + if Assigned(FOnRedrawRequest) then FOnRedrawRequest(Self); +end; + +procedure TTBXScrollBar.SBWndProc(var Message: TMessage); +var + I: Integer; + + procedure DefaultHandler; + begin + with Message do + Result := DefWindowProc(FHandle, Msg, wParam, lParam); + end; + +begin + case Message.Msg of + + WM_TIMER: with TWMTimer(Message) do + begin + I := 0; + TimerElapsed(TimerID, I); + if I > 0 then StartTimer(TimerID, I) + else StopTimer(TimerID); + Result := 0; + end; + + else + DefaultHandler; + end; +end; + +procedure TTBXScrollBar.SetBounds(const Value: TRect); +begin + FBounds := Value; + with Value do + begin + FLeft := Left; + FTop := Top; + FWidth := Right - Left; + FHeight := Bottom - Top; + end; + UpdateZones; +end; + +procedure TTBXScrollBar.SetKind(Value: TScrollBarKind); +begin + FKind := Value; + UpdateZones; +end; + +procedure TTBXScrollBar.SetPosition(Value: Integer); +begin + AdjustPosition(Value); + if Value <> FPosition then + begin + FPosition := Value; + if UserChange then + begin + Redraw; + if Assigned(FOnChange) then FOnChange(Self); + end; + end; +end; + +procedure TTBXScrollBar.SetRange(Value: Integer); +begin + if Value < 0 then Value := 0; + if Value <> FRange then + begin + FRange := Value; + Redraw; + SetPosition(Position); + end; +end; + +procedure TTBXScrollBar.StartAutoScroll(Direction, Interval: Integer); +begin + if Direction <> 0 then + begin + AutoScrollDirection := Direction; + AutoScrollInterval := Interval; + if not AutoScrolling then + begin + StartTimer(AUTO_SCROLL_TIMER, Interval); + AutoScrolling := True; + end; + end; +end; + +procedure TTBXScrollBar.StartTimer(ID, Elapse: Integer); +begin + SetTimer(Handle, ID, Elapse, nil); +end; + +procedure TTBXScrollBar.StopAutoScroll; +begin + if AutoScrolling then + begin + AutoScrolling := False; + StopTimer(AUTO_SCROLL_TIMER); + end; +end; + +procedure TTBXScrollBar.StopTimer(ID: Integer); +begin + KillTimer(Handle, ID); +end; + +procedure TTBXScrollBar.TimerElapsed(ID: Integer; var NewElapse: Integer); +begin + case ID of + SCROLL_TIMER: + if MouseDownZone <> sbzEmpty then + if not (MouseDownZone in [sbzPagePrev, sbzPageNext]) or + (GetZone(LastMousePoint.X, LastMousePoint.Y) = MouseDownZone) then + begin + HandleZoneClick(MouseDownZone); + NewElapse := 100; + end; + AUTO_SCROLL_TIMER: if AutoScrolling then + begin + NewElapse := AutoScrollInterval; + UpdatePosition(Position + AutoScrollDirection); + if (Position = 0) or (Position + Window = Range) then NewElapse := 0; + if Assigned(FOnAutoScroll) then + FOnAutoScroll(Self, AutoScrollDirection, AutoScrollInterval); + AutoScrolling := NewElapse > 0; + end; + end; +end; + +procedure TTBXScrollBar.UpdatePosition(NewPosition: Integer); +begin + UserChange := True; + if NewPosition < 0 then NewPosition := 0; + if NewPosition > Range - Window then NewPosition := Range - Window; + Position := NewPosition; + UserChange := False; +end; + +procedure TTBXScrollBar.UpdateZones; +var + SzL, SzT: Integer; + ButtonSize: Integer; + Lo, Hi: Integer; + HandleSize, HandlePos: Integer; + Window: Integer; + IsVert: Boolean; + + procedure SetZone(var R: TRect; Lo, Hi: Integer); + begin + if IsVert then + begin + R.Left := 0; + R.Right := Width; + R.Top := Lo; + R.Bottom := Hi; + end + else + begin + R.Left := Lo; + R.Right := Hi; + R.Top := 0; + R.Bottom := Height; + end; + end; + +begin + IsVert := Kind = sbVertical; + Window := GetEffectiveWindow; + + if IsVert then + begin + SzL := Height; + SzT := Width; + end + else + begin + SzL := Width; + SzT := Height; + end; + + + { Buttons } + ButtonSize := SzT; + if ButtonSize * 2 >= SzL - 2 then ButtonSize := (SzL - 2) div 2; + SetZone(Zones[sbzPrev], 0, ButtonSize); + SetZone(Zones[sbzNext], SzL - ButtonSize, SzL); + + { Handle } + Lo := ButtonSize; + Hi := SzL - ButtonSize; + if GetEnabled and (Hi - Lo > MIN_SB_HANDLE_SIZE + 4) then + begin + HandleSize := Round((Hi - Lo) * Window / Range); + if HandleSize >= MIN_SB_HANDLE_SIZE then + HandlePos := Round((Hi - Lo) * Position / Range) + else + begin + HandleSize := MIN_SB_HANDLE_SIZE; + HandlePos := Round((Hi - Lo - MIN_SB_HANDLE_SIZE) * Position / (Range - Window)); + end; + Inc(HandlePos, Lo); + SetZone(Zones[sbzHandle], HandlePos, HandlePos + HandleSize); + SetZone(Zones[sbzPagePrev], Lo, HandlePos); + SetZone(Zones[sbzPageNext], HandlePos + HandleSize, Hi); + Zones[sbzEmpty].Right := -1; + end + else + begin + { Invalidate invisible zones } + Zones[sbzPagePrev].Right := -1; + Zones[sbzHandle].Right := -1; + Zones[sbzPageNext].Right := -1; + SetZone(Zones[sbzEmpty], Lo, Hi); + end; +end; + +//----------------------------------------------------------------------------// + +{ TTBXCustomList } + +constructor TTBXCustomList.Create(AOwner: TComponent); +begin + inherited; + FMinWidth := 32; + FMaxWidth := 0; + FMaxVisibleItems := 8; + FItemIndex := -1; +end; + +function TTBXCustomList.DoClearItem(ACanvas: TCanvas; ARect: TRect; AIndex, AHoverIndex: Integer): Boolean; +begin + Result := True; + if Assigned(FOnClearItem) then FOnClearItem(Self, ACanvas, ARect, AIndex, AHoverIndex, Result); +end; + +function TTBXCustomList.DoDrawItem(ACanvas: TCanvas; ARect: TRect; AIndex, AHoverIndex: Integer): Boolean; +begin + Result := True; + if Assigned(FOnDrawItem) then FOnDrawItem(Self, ACanvas, ARect, AIndex, AHoverIndex, Result); +end; + +procedure TTBXCustomList.DoMeasureHeight(ACanvas: TCanvas; var AHeight: Integer); +begin + if Assigned(FOnMeasureHeight) then FOnMeasureHeight(Self, ACanvas, AHeight); +end; + +procedure TTBXCustomList.DoMeasureWidth(ACanvas: TCanvas; AIndex: Integer; var AWidth: Integer); +begin + if Assigned(FOnMeasureWidth) then FOnMeasureWidth(Self, ACanvas, AIndex, AWidth); +end; + +procedure TTBXCustomList.DrawItem(ACanvas: TCanvas; AViewer: TTBXCustomListViewer; + const ARect: TRect; AIndex, AHoverIndex: Integer); +const + FillColors: array [Boolean] of TColor = (clWindow, clHighlight); + TextColors: array [Boolean] of TColor = (clWindowText, clHighlightText); +var + S: string; + R, R2: TRect; + ImgList: TCustomImageList; +begin + ACanvas.Brush.Color := FillColors[AIndex = AHoverIndex]; + if DoClearItem(ACanvas, ARect, AIndex, AHoverIndex) then ACanvas.FillRect(ARect); + + ACanvas.Font.Color := TextColors[AIndex = AHoverIndex]; + if DoDrawItem(ACanvas, ARect, AIndex, AHoverIndex) then + begin + R := ARect; + InflateRect(R, -4, 1); + ImgList := AViewer.GetImageList; + if ShowImages and (ImgList <> nil) then + begin + R2.Left := R.Left; + R2.Top := (R.Top + R.Bottom - ImgList.Height) div 2; + R2.Right := R2.Left + ImgList.Width; + R2.Bottom := R2.Top + ImgList.Height; + if Enabled then ImgList.Draw(ACanvas, R2.Left, R2.Top, GetImageIndex(AIndex)) + else DrawTBXImage(ACanvas, R2, ImgList, GetImageIndex(AIndex), ISF_DISABLED); + Inc(R.Left, ImgList.Width + CImageSpacing); + end; + + S := GetItemText(AIndex); + if Length(S) > 0 then + begin + ACanvas.Brush.Style := bsClear; + DrawText(ACanvas.Handle, PChar(S), Length(S), R, DT_SINGLELINE or DT_VCENTER or DT_NOPREFIX); + ACanvas.Brush.Style := bsSolid; + end; + end; +end; + +function TTBXCustomList.GetImageIndex(ItemIndex: Integer): Integer; +begin + Result := ItemIndex; + if Assigned(FOnAdjustImageIndex) then FOnAdjustImageIndex(Self, ItemIndex, Result); +end; + +function TTBXCustomList.GetItemViewerClass(AView: TTBView): TTBItemViewerClass; +begin + Result := TTBXCustomListViewer; +end; + +procedure TTBXCustomList.HandleChange; +begin + if Assigned(FOnChange) then FOnChange(Self); +end; + +procedure TTBXCustomList.HandleHover(AIndex: Integer); +begin +end; + +procedure TTBXCustomList.MakeVisible(AIndex: Integer); +var + I: Integer; +begin + if FViewers <> nil then + for I := 0 to FViewers.Count - 1 do + TTBXCustomListViewer(FViewers[I]).MakeVisible(AIndex); +end; + +procedure TTBXCustomList.Notification(AComponent: TComponent; Operation: TOperation); +begin + inherited Notification(AComponent, Operation); + if (Operation = opRemove) and (AComponent = Images) then Images := nil; +end; + +procedure TTBXCustomList.SetItemIndex(Value: Integer); +var + I: Integer; +begin + if Value < 0 then Value := -1; + FItemIndex := Value; + + { Update viewers } + if FViewers <> nil then + for I := 0 to FViewers.Count - 1 do + TTBXCustomListViewer(FViewers[I]).ListChangeHandler(Value); + + if Assigned(FOnChange) then FOnChange(Self); +end; + +//----------------------------------------------------------------------------// + +{ TTBXCustomListViewer } + +procedure TTBXCustomListViewer.AdjustAutoScrollHover(var AIndex: Integer; Direction: Integer); +begin + AIndex := -1; // turn off hover when autoscrolling +end; + +procedure TTBXCustomListViewer.CalcSize(const Canvas: TCanvas; var AWidth, AHeight: Integer); +var + Item: TTBXCustomList; + I, W: Integer; +begin + Item := TTBXCustomList(Self.Item); + Canvas.Font := TTBViewAccess(View).GetFont; + FItemCount := Item.GetCount; + FItemHeight := GetItemHeight(Canvas); + + FVisibleItems := FItemCount; + if FVisibleItems > Item.MaxVisibleItems then FVisibleItems := Item.MaxVisibleItems + else if FVisibleItems <= 0 then FVisibleItems := 1; + + AHeight := FVisibleItems * FItemHeight; + + AWidth := 0; + for I := 0 to FItemCount - 1 do + begin + W := GetItemWidth(Canvas, I); + if W > AWidth then AWidth := W; + end; + + if FItemCount > FVisibleItems then FScrollBarWidth := GetSystemMetrics(SM_CXVSCROLL) + else FScrollBarWidth := 0; + Inc(AWidth, FScrollBarWidth); + + if AWidth < Item.MinWidth then AWidth := Item.MinWidth; + if (Item.MaxWidth > Item.MinWidth) and (AWidth > Item.MaxWidth) then AWidth := Item.MaxWidth; +end; + +constructor TTBXCustomListViewer.Create(AView: TTBView; AItem: TTBCustomItem; AGroupLevel: Integer); +var + Index: Integer; +begin + inherited; + Index := TTBXCustomList(AItem).ItemIndex; + FItemCount := TTBXCustomList(AItem).GetCount; + if (Index >= 0) and (Index < FItemCount) then + with TTBXCustomList(AItem) do + begin + FVisibleItems := GetCount; + if FVisibleItems > MaxVisibleItems then FVisibleItems := MaxVisibleItems; + if Index < FOffset then FOffset := Index + else if Index >= FOffset + FVisibleItems then FOffset := Index - FVisibleItems + 1 + end; + FHoverIndex := Index; + if FHoverIndex > FItemCount then FHoverIndex := -1; + AddToList(TTBXCustomList(AItem).FViewers, Self); +end; + +destructor TTBXCustomListViewer.Destroy; +begin + RemoveFromList(TTBXCustomList(Item).FViewers, Self); + if FScrollBar <> nil then FScrollBar.Free; + inherited; +end; + +procedure TTBXCustomListViewer.DrawItems(const Canvas: TCanvas; const ClientAreaRect: TRect); +var + I: Integer; + R: TRect; +begin + R := ClientAreaRect; + R.Bottom := FItemHeight; + Dec(R.Right, FScrollBarWidth); + Canvas.Font := TTBViewAccess(View).GetFont; + + for I := FOffset to FItemCount - 1 do + begin + if RectVisible(Canvas.Handle, R) then + TTBXCustomList(Item).DrawItem(Canvas, Self, R, I, HoverIndex); + R.Top := R.Bottom; + Inc(R.Bottom, FItemHeight); + if R.Bottom > FHeight then Break; + end; + + if R.Top < ClientAreaRect.Bottom then + begin + R.Bottom := ClientAreaRect.Bottom; + Canvas.Brush.Color := clWindow; + Canvas.FillRect(R); + end; +end; + +function TTBXCustomListViewer.GetItemHeight(ACanvas: TCanvas): Integer; +var + ImgList: TCustomImageList; +begin + Result := ACanvas.TextHeight('Q') + 2; + with TTBXStringList(Item) do + begin + ImgList := GetImageList; + if ShowImages and (ImgList <> nil) and (Result < ImgList.Height + 2) then + Result := ImgList.Height + 2; + DoMeasureHeight(ACanvas, Result); + end; +end; + +function TTBXCustomListViewer.GetItemIndexAt(X, Y: Integer): Integer; +begin + if (X < 0) or (X > FWidth - FScrollBarWidth) then Result := -1 + else + begin + Result := (Y div FItemHeight) + FOffset; + if (Result < FOffset) or (Result >= FOffset + FVisibleItems) or (Result >= FItemCount) then + Result := - 1; + end; +end; + +function TTBXCustomListViewer.GetItemRect(Index: Integer): TRect; +begin + { Note this method works properly only after Draw is called } + Result := FLastClientRect; + Inc(Result.Top, (Index - FOffset) * FItemHeight); + Result.Bottom := Result.Top + FItemHeight; + Dec(Result.Right, FScrollBarWidth); +end; + +function TTBXCustomListViewer.GetItemWidth(ACanvas: TCanvas; Index: Integer): Integer; +var + S: string; + ImgList: TCustomImageList; +begin + with TTBXStringList(Item) do + begin + S := GetItemText(Index); + Result := ACanvas.TextWidth(S); + if ShowImages then + begin + ImgList := GetImageList; + if ImgList <> nil then + begin + Inc(Result, ImgList.Width); + if Length(S) > 0 then Inc(Result, CImageSpacing); + end; + end; + Inc(Result, 8); + DoMeasureWidth(ACanvas, Index, Result) + end; +end; + +procedure TTBXCustomListViewer.HandleAutoScroll(var Direction, Interval: Integer); +begin + // do nothing by default +end; + +procedure TTBXCustomListViewer.KeyDown(var Key: Word; Shift: TShiftState); +var + OldIndex, NewIndex: Integer; +begin + OldIndex := FHoverIndex; + case Key of + VK_UP: NewIndex := OldIndex - 1; + VK_DOWN: NewIndex := OldIndex + 1; + VK_PRIOR: NewIndex := OldIndex - FVisibleItems; + VK_NEXT: NewIndex := OldIndex + FVisibleItems; + VK_HOME: NewIndex := 0; + VK_END: NewIndex := FItemCount - 1; + VK_RETURN: + begin + TTBXCustomList(Item).ItemIndex := FHoverIndex; + Exit; + end; + else + Exit; + end; + Key := 0; + if NewIndex < 0 then NewIndex := 0; + if NewIndex >= FItemCount then NewIndex := FItemCount - 1; + TTBXCustomList(Item).ItemIndex := NewIndex; +end; + +procedure TTBXCustomListViewer.ListChangeHandler(NewIndex: Integer); +begin + if not IsChanging and (NewIndex <> HoverIndex) then + begin + IsChanging := True; + HoverIndex := NewIndex; + TTBXCustomList(Item).HandleHover(NewIndex); + MakeVisible(HoverIndex); + UpdateItems; + IsChanging := False; + end; +end; + +procedure TTBXCustomListViewer.MakeVisible(Index: Integer); +begin + if (Index >= 0) and (Index < FItemCount) then + begin + if Index < FOffset then FScrollBar.UpdatePosition(Index) + else if Index >= FOffset + FVisibleItems then FScrollBar.UpdatePosition(Index - FVisibleItems + 1); + end; +end; + +procedure TTBXCustomListViewer.MouseDown(Shift: TShiftState; X, Y: Integer; var MouseDownOnMenu: Boolean); +begin + if X > FWidth - FScrollBarWidth then + begin + Dec(X, FWidth - FScrollBarWidth); + MouseInScrollBar := True; + FScrollBar.MouseDown(mbLeft, X, Y); + MouseDownOnMenu := False; + end + else + begin + MouseIsDown := True; + MouseMove(X, Y); + end; + inherited; + View.SetCapture; +end; + +procedure TTBXCustomListViewer.MouseMove(X, Y: Integer); +var + NewHoverIndex, OldHoverIndex, IndexLo, IndexHi, I: Integer; + R: TRect; + Canvas: TCanvas; + DC: HDC; + V, Dir: Integer; +begin + if MouseInScrollBar then + begin + Dec(X, FWidth - FScrollBarWidth); + FScrollBar.MouseMove(X, Y); + Exit; + end; + + if not View.Capture and (GetKeyState(VK_LBUTTON) < 0) then + begin + View.SetCapture; + MouseIsDown := True; + end; + + NewHoverIndex := GetItemIndexAt(X, Y); + if FScrollBar <> nil then + begin + if MouseIsDown and ((Y < 0) or (Y >= FHeight)) then + begin + { Get AutoScroll Intervals } + V := Y; + if V >= FHeight then Dec(V, FHeight - 1); + V := Abs(V); + if Y < 0 then Dir := -1 else Dir := 1; + case V of + 0..9: V := 150; + 10..29: V := 100; + 30..50: begin V := 100; Dir := Dir * 2; end; + else + V := 100; + Dir := Dir * 4; + end; + + if ((Dir < 0) and (FOffset > 0)) or + ((Dir > 0) and (FOffset + FVisibleItems < FItemCount)) then + FScrollBar.StartAutoScroll(Dir, V) + else + FScrollBar.StopAutoScroll; + AdjustAutoScrollHover(NewHoverIndex, Dir); + end + else FScrollBar.StopAutoScroll; + end; + + if not MouseIsDown and (NewHoverIndex = -1) then Exit; + + if NewHoverIndex <> FHoverIndex then + begin + Canvas := TCanvas.Create; + DC := GetDC(View.Window.Handle); + OldHoverIndex := FHoverIndex; + FHoverIndex := NewHoverIndex; + try + SetWindowOrgEx(DC, -BoundsRect.Left, -BoundsRect.Top, nil); + Canvas.Handle := DC; + Canvas.Font := TTBViewAccess(View).GetFont; + + IndexLo := OldHoverIndex; + IndexHi := FHoverIndex; + if FHoverIndex < OldHoverIndex then + begin + IndexLo := FHoverIndex; + IndexHi := OldHoverIndex; + end; + for I := IndexLo to IndexHi do + begin + R := GetItemRect(I); + if (R.Top >= 0) and (R.Bottom <= FHeight) and RectVisible(DC, R) then + TTBXCustomList(Item).DrawItem(Canvas, Self, R, I, HoverIndex); + end; + finally + Canvas.Handle := 0; + Canvas.Free; + ReleaseDC(View.Window.Handle, DC); + end; + TTBXCustomList(Item).HandleHover(FHoverIndex); + end; +end; + +procedure TTBXCustomListViewer.MouseUp(X, Y: Integer; MouseWasDownOnMenu: Boolean); +var + DAD: TTBDoneActionData; +begin + if FScrollBar <> nil then FScrollBar.StopAutoScroll; + if MouseInScrollBar then + begin + inherited; + Dec(X, FWidth - FScrollBarWidth); + FScrollBar.MouseUp(mbLeft, X, Y); + DAD := TTBViewAccess(TTBViewAccess(View).GetRootView).DoneActionData; + DAD.DoneAction := tbdaNone; + TTBViewAccess(TTBViewAccess(View).GetRootView).DoneActionData := DAD; + MouseInScrollBar := False; + end + else if MouseIsDown then + begin + MouseIsDown := False; + TTBXCustomList(Item).ItemIndex := FHoverIndex; + inherited; + DAD := TTBViewAccess(TTBViewAccess(View).GetRootView).DoneActionData; + DAD.Sound := False; + TTBViewAccess(TTBViewAccess(View).GetRootView).DoneActionData := DAD; + end; +end; + +procedure TTBXCustomListViewer.MouseWheel(WheelDelta, X, Y: Integer); +var + IsNegative: Boolean; +begin + if FScrollBar <> nil then + begin + Inc(FWheelAccumulator, WheelDelta); + while Abs(FWheelAccumulator) >= WHEEL_DELTA do + begin + IsNegative := FWheelAccumulator < 0; + FWheelAccumulator := Abs(FWheelAccumulator) - WHEEL_DELTA; + if IsNegative then + begin + if FWheelAccumulator <> 0 then FWheelAccumulator := -FWheelAccumulator; + FScrollBar.UpdatePosition(FScrollBar.Position + 1) + end + else + FScrollBar.UpdatePosition(FScrollBar.Position - 1) + end; + end; +end; + +procedure TTBXCustomListViewer.Paint(const Canvas: TCanvas; + const ClientAreaRect: TRect; IsHoverItem, IsPushed, UseDisabledShadow: Boolean); +begin + { Cache some important info for later usage } + FLastClientRect := ClientAreaRect; + with ClientAreaRect do + begin + FWidth := Right - Left; + FHeight := Bottom - Top; + end; + + DrawItems(Canvas, ClientAreaRect); + + if FScrollBarWidth > 0 then + begin + if FScrollBar = nil then + begin + FScrollBar := TTBXScrollBar.Create; + FScrollBar.Kind := sbVertical; + FScrollBar.OnRedrawRequest := SBRedrawHandler; + FScrollBar.OnChange := SBChangeHandler; + FScrollBar.OnAutoScroll := SBAutoScrollHandler; + end; + FScrollBar.Bounds := Rect(ClientAreaRect.Right - FScrollBarWidth, + ClientAreaRect.Top, ClientAreaRect.Right, ClientAreaRect.Bottom); + FScrollBar.Range := FItemCount; + FScrollBar.Window := FVisibleItems; + FScrollBar.Position := FOffset; + FScrollBar.PaintTo(Canvas); + end; +end; + +procedure TTBXCustomListViewer.SBAutoScrollHandler(Sender: TObject; + var Direction, Interval: Integer); +begin + HandleAutoScroll(Direction, Interval); +end; + +procedure TTBXCustomListViewer.SBChangeHandler(Sender: TObject); +begin + FOffset := FScrollBar.Position; + UpdateItems; +end; + +procedure TTBXCustomListViewer.SBRedrawHandler(Sender: TObject); +var + DC: HDC; + Canvas: TCanvas; +begin + Canvas := TCanvas.Create; + DC := GetDC(View.Window.Handle); + try + SetWindowOrgEx(DC, -BoundsRect.Left, -BoundsRect.Top, nil); + Canvas.Handle := DC; + FScrollBar.PaintTo(Canvas); + finally + Canvas.Handle := 0; + Canvas.Free; + ReleaseDC(View.Window.Handle, DC); + end; +end; + +procedure TTBXCustomListViewer.UpdateItems; +var + DC: HDC; + Canvas: TCanvas; +begin + if Assigned(FScrollBar) then FOffset := FScrollBar.Position + else FOffset := 0; + Canvas := TCanvas.Create; + DC := GetDC(View.Window.Handle); + try + SetWindowOrgEx(DC, -BoundsRect.Left, -BoundsRect.Top, nil); + Canvas.Handle := DC; + DrawItems(Canvas, FLastClientRect); + finally + Canvas.Handle := 0; + Canvas.Free; + ReleaseDC(View.Window.Handle, DC); + end; +end; + + +//----------------------------------------------------------------------------// + +{ TTBXStringList } + +constructor TTBXStringList.Create(AOwner: TComponent); +begin + inherited; + FStrings := TStringList.Create; +end; + +destructor TTBXStringList.Destroy; +begin + FStrings.Free; + inherited; +end; + +function TTBXStringList.GetCount: Integer; +begin + Result := FStrings.Count; +end; + +function TTBXStringList.GetItemText(Index: Integer): string; +begin + Result := FStrings[Index]; +end; + +procedure TTBXStringList.SetStrings(Value: TStrings); +begin + FStrings.Assign(Value); +end; + + +//----------------------------------------------------------------------------// + +{ TTBXUndoList } + +procedure TTBXUndoList.DrawItem(ACanvas: TCanvas; AViewer: TTBXCustomListViewer; + const ARect: TRect; AIndex, AHoverIndex: Integer); +const + FillColors: array [Boolean] of TColor = (clWindow, clHighlight); + TextColors: array [Boolean] of TColor = (clWindowText, clHighlightText); +var + S: string; + R: TRect; +begin + ACanvas.Brush.Color := FillColors[AIndex <= AHoverIndex]; + ACanvas.FillRect(ARect); + S := Strings[AIndex]; + if Length(S) > 0 then + begin + R := ARect; + InflateRect(R, -4, 1); + ACanvas.Font.Color := TextColors[AIndex <= AHoverIndex]; + ACanvas.Brush.Style := bsClear; + DrawText(ACanvas.Handle, PChar(S), Length(S), R, DT_SINGLELINE or DT_VCENTER); + ACanvas.Brush.Style := bsSolid; + end; +end; + +function TTBXUndoList.GetItemViewerClass(AView: TTBView): TTBItemViewerClass; +begin + Result := TTBXUndoListViewer; +end; + +procedure TTBXUndoList.HandleHover(AIndex: Integer); +begin + ItemIndex := AIndex; +end; + + +//----------------------------------------------------------------------------// + +{ TTBXUndoListViewer } + +procedure TTBXUndoListViewer.AdjustAutoScrollHover(var AIndex: Integer; Direction: Integer); +begin + if Direction < 0 then AIndex := FOffset + else if Direction > 0 then AIndex := FOffset + FVisibleItems - 1; +end; + +procedure TTBXUndoListViewer.HandleAutoScroll(var Direction, Interval: Integer); +begin + inherited; + if Direction < 0 then HoverIndex := FOffset + else if Direction > 0 then HoverIndex := FOffset + FVisibleItems - 1 + else Exit; + TTBXCustomList(Item).HandleHover(HoverIndex); + UpdateItems; +end; + +end. diff --git a/official/2.1.6+2.1.beta1/TBX/TBXLists.pas.orig b/official/2.1.6+2.1.beta1/TBX/TBXLists.pas.orig new file mode 100644 index 0000000..7340fb4 --- /dev/null +++ b/official/2.1.6+2.1.beta1/TBX/TBXLists.pas.orig @@ -0,0 +1,1385 @@ +unit TBXLists; + +// TBX Package +// Copyright 2001-2004 Alex A. Denisov. All Rights Reserved +// See TBX.chm for license and installation instructions +// +// $Id: TBXLists.pas 7 2004-02-21 06:07:53Z $ + +interface + +{$I TB2Ver.inc} +{$I TBX.inc} + +uses + Windows, Messages, Classes, SysUtils, Controls, Forms, Graphics, TB2Item, TBX, + TBXThemes, TBXUxThemes, ImgList; + +type + { TTBXScrollBar } + + TSBIncrement = 1..1000; + TSBZone = (sbzEmpty, sbzPrev, sbzPagePrev, sbzHandle, sbzPageNext, sbzNext); + TSBAutoScrollEvent = procedure(Sender: TObject; var Direction, Interval: Integer) of object; + + TTBXScrollBar = class + private + FBounds: TRect; + FLeft: Integer; + FHandle: HWND; + FHeight: Integer; + FIncrement: TSBIncrement; + FKind: TScrollBarKind; + FPosition: Integer; + FRange: Integer; + FRight: Integer; + FTop: Integer; + FWidth: Integer; + FWindow: Integer; + FOnChange: TNotifyEvent; + FOnAutoScroll: TSBAutoScrollEvent; + FOnRedrawRequest: TNotifyEvent; + procedure SetBounds(const Value: TRect); + procedure SetKind(Value: TScrollBarKind); + procedure SetPosition(Value: Integer); + procedure SetRange(Value: Integer); + function GetHandle: HWND; + protected + AutoScrollDirection: Integer; + AutoScrolling: Boolean; + AutoScrollInterval: Integer; + Zones: array [TSBZone] of TRect; + MouseDownZone: TSBZone; + MouseDownPoint: TPoint; + MouseDownPosition: Integer; + LastMousePoint: TPoint; + PrevCapture: HWND; + UserChange: Boolean; + procedure AdjustPosition(var NewPosition: Integer); + procedure CreateWnd; + procedure DestroyWnd; + function GetZone(X, Y: Integer): TSBZone; + function GetEffectiveWindow: Integer; + function GetEnabled: Boolean; virtual; + procedure HandleZoneClick(AZone: TSBZone); + procedure MouseDown(Button: TMouseButton; X, Y: Integer); virtual; + procedure MouseMove(X, Y: Integer); virtual; + procedure MouseUp(Button: TMouseButton; X, Y: Integer); virtual; + procedure PaintButton(Canvas: TCanvas; Rect: TRect; Direction: Integer; Pushed, Enabled: Boolean); + procedure PaintHandle(Canvas: TCanvas; Rect: TRect; Pushed, Enabled: Boolean); + procedure PaintTrack(Canvas: TCanvas; Rect: TRect; IsNextZone, Pushed, Enabled: Boolean); + procedure PaintTo(Canvas: TCanvas); + procedure SBWndProc(var Message: TMessage); + procedure StartAutoScroll(Direction, Interval: Integer); + procedure StopAutoScroll; + procedure StartTimer(ID: Integer; Elapse: Integer); + procedure StopTimer(ID: Integer); + procedure TimerElapsed(ID: Integer; var NewElapse: Integer); virtual; + procedure UpdateZones; + property Handle: HWND read GetHandle; + public + constructor Create; + destructor Destroy; override; + procedure Redraw; virtual; + procedure UpdatePosition(NewPosition: Integer); + property Kind: TScrollBarKind read FKind write SetKind; + property Bounds: TRect read FBounds write SetBounds; + property Left: Integer read FLeft; + property Height: Integer read FHeight; + property Increment: TSBIncrement read FIncrement write FIncrement; + property Position: Integer read FPosition write SetPosition; + property Range: Integer read FRange write SetRange; + property Right: Integer read FRight; + property Top: Integer read FTop; + property Width: Integer read FWidth; + property Window: Integer read FWindow write FWindow; + property OnAutoScroll: TSBAutoScrollEvent read FOnAutoScroll write FOnAutoScroll; + property OnChange: TNotifyEvent read FOnChange write FOnChange; + property OnRedrawRequest: TNotifyEvent read FOnRedrawRequest write FOnRedrawRequest; + end; + + { TTBXCustomList } + TTBXCustomList = class; + + TTBXLMeasureHeight = procedure(Sender: TTBXCustomList; ACanvas: TCanvas; var AHeight: Integer) of object; + TTBXLMeasureWidth = procedure(Sender: TTBXCustomList; ACanvas: TCanvas; AIndex: Integer; var AWidth: Integer) of object; + TTBXLPaintEvent = procedure(Sender: TTBXCustomList; ACanvas: TCanvas; ARect: TRect; AIndex, AHoverIndex: Integer; var DrawDefault: Boolean) of object; + TTBXLAdjustImageIndex = procedure(Sender: TTBXCustomList; AItemIndex: Integer; var ImageIndex: Integer) of object; + + TTBXCustomListViewer = class; + + TTBXCustomList = class(TTBXCustomItem) + private + FViewers: TList; + FItemIndex: Integer; + FMinWidth: Integer; + FMaxWidth: Integer; + FMaxVisibleItems: Integer; + FShowImages: Boolean; + FOnChange: TNotifyEvent; + FOnClearItem: TTBXLPaintEvent; + FOnDrawItem: TTBXLPaintEvent; + FOnAdjustImageIndex: TTBXLAdjustImageIndex; + FOnMeasureHeight: TTBXLMeasureHeight; + FOnMeasureWidth: TTBXLMeasureWidth; + procedure SetItemIndex(Value: Integer); + protected + function DoClearItem(ACanvas: TCanvas; ARect: TRect; AIndex, AHoverIndex: Integer): Boolean; virtual; + function DoDrawItem(ACanvas: TCanvas; ARect: TRect; AIndex, AHoverIndex: Integer): Boolean; virtual; + procedure DoMeasureHeight(ACanvas: TCanvas; var AHeight: Integer); virtual; + procedure DoMeasureWidth(ACanvas: TCanvas; AIndex: Integer; var AWidth: Integer); virtual; + procedure DrawItem(ACanvas: TCanvas; AViewer: TTBXCustomListViewer; const ARect: TRect; AIndex, AHoverIndex: Integer); virtual; + function GetImageIndex(ItemIndex: Integer): Integer; virtual; + function GetItemViewerClass(AView: TTBView): TTBItemViewerClass; override; + function GetItemText(Index: Integer): string; virtual; abstract; + function GetCount: Integer; virtual; abstract; + procedure HandleChange; virtual; + procedure HandleHover(AIndex: Integer); virtual; + procedure Notification(AComponent: TComponent; Operation: TOperation); override; + public + constructor Create(AOwner: TComponent); override; + procedure MakeVisible(AIndex: Integer); + property ItemIndex: Integer read FItemIndex write SetItemIndex default -1; + property MaxVisibleItems: Integer read FMaxVisibleItems write FMaxVisibleItems default 8; + property MaxWidth: Integer read FMaxWidth write FMaxWidth default 0; + property MinWidth: Integer read FMinWidth write FMinWidth default 32; + property ShowImages: Boolean read FShowImages write FShowImages default False; + property OnAdjustImageIndex: TTBXLAdjustImageIndex read FOnAdjustImageIndex write FOnAdjustImageIndex; + property OnChange: TNotifyEvent read FOnChange write FOnChange; + property OnClearItem: TTBXLPaintEvent read FOnClearItem write FOnClearItem; + property OnDrawItem: TTBXLPaintEvent read FOnDrawItem write FOnDrawItem; + property OnMeasureHeight: TTBXLMeasureHeight read FOnMeasureHeight write FOnMeasureHeight; + property OnMeasureWidth: TTBXLMeasureWidth read FOnMeasureWidth write FOnMeasureWidth; + end; + + TTBXCustomListViewer = class(TTBXItemViewer) + private + FItemCount: Integer; + FItemHeight: Integer; + FHoverIndex: Integer; + FHeight: Integer; + FLastClientRect: TRect; + FWheelAccumulator: Integer; + FWidth: Integer; + FOffset: Integer; + FScrollBarWidth: Integer; + FScrollBar: TTBXScrollBar; + FVisibleItems: Integer; + procedure ListChangeHandler(NewIndex: Integer); + procedure SBAutoScrollHandler(Sender: TObject; var Direction, Interval: Integer); + procedure SBChangeHandler(Sender: TObject); + procedure SBRedrawHandler(Sender: TObject); + protected + MouseIsDown: Boolean; + MouseInScrollBar: Boolean; + IgnoreMouseUp: Boolean; + IsChanging: Boolean; + procedure AdjustAutoScrollHover(var AIndex: Integer; Direction: Integer); virtual; + procedure CalcSize(const Canvas: TCanvas; var AWidth, AHeight: Integer); override; + procedure DrawItems(const Canvas: TCanvas; const ClientAreaRect: TRect); + function GetItemIndexAt(X, Y: Integer): Integer; + function GetItemRect(Index: Integer): TRect; + function GetItemHeight(ACanvas: TCanvas): Integer; virtual; + function GetItemWidth(ACanvas: TCanvas; Index: Integer): Integer; virtual; + procedure HandleAutoScroll(var Direction, Interval: Integer); virtual; + procedure KeyDown(var Key: Word; Shift: TShiftState); override; + procedure MakeVisible(Index: Integer); + procedure MouseDown(Shift: TShiftState; X, Y: Integer; var MouseDownOnMenu: Boolean); override; + procedure MouseMove(X, Y: Integer); override; + procedure MouseUp(X, Y: Integer; MouseWasDownOnMenu: Boolean); override; + procedure MouseWheel(WheelDelta: Integer; X, Y: Integer); override; + procedure Paint(const Canvas: TCanvas; const ClientAreaRect: TRect; IsHoverItem, IsPushed, UseDisabledShadow: Boolean); override; + procedure UpdateItems; + property HoverIndex: Integer read FHoverIndex write FHoverIndex; + public + constructor Create(AView: TTBView; AItem: TTBCustomItem; AGroupLevel: Integer); override; + destructor Destroy; override; + end; + + { TTBXStringList } + + TTBXStringList = class(TTBXCustomList) + private + FStrings: TStrings; + procedure SetStrings(Value: TStrings); + protected + function GetItemText(Index: Integer): string; override; + function GetCount: Integer; override; + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + published + property ItemIndex; + property MaxVisibleItems; + property MaxWidth; + property MinWidth; + property Strings: TStrings read FStrings write SetStrings; + property OnAdjustImageIndex; + property OnChange; + property OnClearItem; + property OnClick; + property OnDrawItem; + property OnMeasureHeight; + property OnMeasureWidth; + end; + + TTBXStringListClass = class of TTBXStringList; + + { TTBXUndoList } + + TTBXUndoList = class(TTBXStringList) + protected + procedure DrawItem(ACanvas: TCanvas; AViewer: TTBXCustomListViewer; const ARect: TRect; AIndex, AHoverIndex: Integer); override; + function GetItemViewerClass(AView: TTBView): TTBItemViewerClass; override; + procedure HandleHover(AIndex: Integer); override; + end; + + TTBXUndoListViewer = class(TTBXCustomListViewer) + protected + procedure AdjustAutoScrollHover(var AIndex: Integer; Direction: Integer); override; + procedure HandleAutoScroll(var Direction, Interval: Integer); override; + end; + +implementation + +type TTBViewAccess = class(TTBView); + +const + SCROLL_TIMER = 1; + AUTO_SCROLL_TIMER = 2; + MIN_SB_HANDLE_SIZE = 8; + + CImageSpacing = 4; + +//----------------------------------------------------------------------------// + +{ TTBXScrollBar } + +procedure TTBXScrollBar.AdjustPosition(var NewPosition: Integer); +var + W: Integer; +begin + W := GetEffectiveWindow; + if NewPosition + W > Range then NewPosition := Range - W; + if NewPosition < 0 then NewPosition := 0; +end; + +constructor TTBXScrollBar.Create; +begin + FIncrement := 1; +end; + +procedure TTBXScrollBar.CreateWnd; +begin + if FHandle = 0 then FHandle := {$IFDEF JR_D6}Classes.{$ENDIF}AllocateHWnd(SBWndProc); +end; + +destructor TTBXScrollBar.Destroy; +begin + DestroyWnd; + inherited; +end; + +procedure TTBXScrollBar.DestroyWnd; +begin + if FHandle <> 0 then + begin + {$IFDEF JR_D6}Classes.{$ENDIF}DeallocateHWnd(FHandle); + FHandle := 0; + end; +end; + +function TTBXScrollBar.GetEffectiveWindow: Integer; +begin + if Window <= 0 then + begin + if Kind = sbVertical then Result := Height + else Result := Width; + end + else Result := Window; +end; + +function TTBXScrollBar.GetEnabled: Boolean; +begin + Result := Range > GetEffectiveWindow; +end; + +function TTBXScrollBar.GetHandle: HWND; +begin + if FHandle = 0 then CreateWnd; + Result := FHandle; +end; + +function TTBXScrollBar.GetZone(X, Y: Integer): TSBZone; +var + I: Integer; + Pt: TPoint; +begin + Pt.X := X; + Pt.Y := Y; + for I := Ord(sbzPrev) to Ord(sbzNext) do + begin + Result := TSBZone(I); + if PtInRect(Zones[Result], Pt) then Exit; + end; + Result := sbzEmpty; +end; + +procedure TTBXScrollBar.HandleZoneClick(AZone: TSBZone); +begin + UserChange := True; + case AZone of + sbzPrev: Position := Position - Increment; + sbzPagePrev: Position := Position - GetEffectiveWindow; + sbzPageNext: Position := Position + GetEffectiveWindow; + sbzNext: Position := Position + Increment; + end; + UserChange := False; +end; + +procedure TTBXScrollBar.MouseDown(Button: TMouseButton; X, Y: Integer); +begin + if Button = mbLeft then + begin + MouseDownZone := GetZone(X, Y); + MouseDownPoint := Point(X, Y); + MouseDownPosition := Position; + LastMousePoint := MouseDownPoint; + if MouseDownZone in [sbzPrev, sbzPagePrev, sbzPageNext, sbzNext] then + begin + HandleZoneClick(MouseDownZone); + StartTimer(SCROLL_TIMER, 500); + end; + Redraw; + end; +end; + +procedure TTBXScrollBar.MouseMove(X, Y: Integer); +var + Delta: Integer; + ClientSize, HandleSize: Integer; +begin + LastMousePoint := Point(X, Y); + if MouseDownZone = sbzHandle then + begin + if Kind = sbVertical then + begin + Delta := Y - MouseDownPoint.Y; + ClientSize := Zones[sbzPageNext].Bottom - Zones[sbzPagePrev].Top; + end + else + begin + Delta := X - MouseDownPoint.X; + ClientSize := Zones[sbzPageNext].Right - Zones[sbzPagePrev].Left; + end; + HandleSize := Round(ClientSize * Window / Range); + if HandleSize < MIN_SB_HANDLE_SIZE then + Delta := Round(Delta * (Range - Window) / (ClientSize - MIN_SB_HANDLE_SIZE)) + else + Delta := Round(Delta * Range / ClientSize); + + if MouseDownPosition + Delta <> Position then + begin + UserChange := True; + Position := MouseDownPosition + Delta; + UserChange := False; + end; + end; +end; + +procedure TTBXScrollBar.MouseUp(Button: TMouseButton; X, Y: Integer); +begin + StopTimer(SCROLL_TIMER); + if Button = mbLeft then + begin + MouseDownZone := sbzEmpty; + Redraw; + end; +end; + +procedure TTBXScrollBar.PaintButton(Canvas: TCanvas; Rect: TRect; + Direction: Integer; Pushed, Enabled: Boolean); +const + DirectionFlags: array [0..3] of Cardinal = (DFCS_SCROLLLEFT, DFCS_SCROLLUP, + DFCS_SCROLLRIGHT, DFCS_SCROLLDOWN); + EnabledFlags: array [Boolean] of Cardinal = (DFCS_INACTIVE, 0); + PushedFlags: array [Boolean] of Cardinal = (0, DFCS_PUSHED or DFCS_FLAT); + + DirectionXPFlags: array [0..3] of Cardinal = (ABS_LEFTNORMAL, ABS_UPNORMAL, + ABS_RIGHTNORMAL, ABS_DOWNNORMAL); +var + StateFlags: Cardinal; +begin + if USE_THEMES then + begin + StateFlags := DirectionXPFlags[Direction]; + if not Enabled then Inc(StateFlags, 3) + else if Pushed then Inc(StateFlags, 2); + DrawThemeBackground(SCROLLBAR_THEME, Canvas.Handle, SBP_ARROWBTN, StateFlags, Rect, nil); + end + else + begin + DrawFrameControl(Canvas.Handle, Rect, DFC_SCROLL, + DirectionFlags[Direction] or EnabledFlags[Enabled] or PushedFlags[Pushed]); + end; +end; + +procedure TTBXScrollBar.PaintHandle(Canvas: TCanvas; Rect: TRect; Pushed, Enabled: Boolean); +const + PartXPFlags: array [TScrollBarKind] of Cardinal = (SBP_THUMBBTNHORZ, SBP_THUMBBTNVERT); +var + StateFlags: Cardinal; +begin + if USE_THEMES then + begin + StateFlags := SCRBS_NORMAL; + if not Enabled then Inc(StateFlags, 3) + else if Pushed then Inc(StateFlags, 2); + DrawThemeBackground(SCROLLBAR_THEME, Canvas.Handle, PartXPFlags[Kind], StateFlags, Rect, nil); + end + else + begin + DrawEdge(Canvas.Handle, Rect, EDGE_RAISED, BF_RECT or BF_ADJUST); + Canvas.Brush.Color := clBtnFace; + Canvas.FillRect(Rect); + end; +end; + +procedure TTBXScrollBar.PaintTo(Canvas: TCanvas); +var + R: TRect; + E, IsVert: Boolean; + I: Integer; + Dummy: TPoint; +begin + UpdateZones; + IsVert := Kind = sbVertical; + E := GetEnabled; + + OffsetWindowOrgEx(Canvas.Handle, -Bounds.Left, -Bounds.Top, Dummy); + try + + if IsVert then I := 1 else I := 0; + PaintButton(Canvas, Zones[sbzPrev], I, MouseDownZone = sbzPrev, E); + PaintButton(Canvas, Zones[sbzNext], I + 2, MouseDownZone = sbzNext, E); + + if not IsRectEmpty(Zones[sbzEmpty]) then + begin + Canvas.Brush.Color := clScrollBar; + Canvas.Brush.Style := bsSolid; + Canvas.FillRect(Zones[sbzEmpty]); + end; + + if not IsRectEmpty(Zones[sbzPagePrev]) or not IsRectEmpty(Zones[sbzPageNext]) then + begin + R := Zones[sbzPagePrev]; + PaintTrack(Canvas, R, False, MouseDownZone = sbzPagePrev, E); + R := Zones[sbzPageNext]; + PaintTrack(Canvas, R, True, MouseDownZone = sbzPageNext, E); + end; + + if not IsRectEmpty(Zones[sbzHandle]) then + PaintHandle(Canvas, Zones[sbzHandle], MouseDownZone = sbzHandle, E); + + finally + OffsetWindowOrgEx(Canvas.Handle, Bounds.Left, Bounds.Top, Dummy); + end; +end; + +procedure TTBXScrollBar.PaintTrack(Canvas: TCanvas; Rect: TRect; + IsNextZone, Pushed, Enabled: Boolean); +const + PartXPFlags: array [Boolean, TScrollBarKind] of Cardinal = + ((SBP_LOWERTRACKHORZ, SBP_LOWERTRACKVERT), (SBP_UPPERTRACKHORZ, SBP_UPPERTRACKVERT)); +var + StateFlags: Cardinal; +begin + if USE_THEMES then + begin + StateFlags := SCRBS_NORMAL; + if not Enabled then Inc(StateFlags, 3) + else if Pushed then Inc(StateFlags, 2); + DrawThemeBackground(SCROLLBAR_THEME, Canvas.Handle, PartXPFlags[IsNextZone, Kind], + StateFlags, Rect, nil); + end + else + begin + if Pushed then Canvas.Brush.Color := cl3DDkShadow + else Canvas.Brush.Bitmap := AllocPatternBitmap(clBtnHighlight, clScrollBar); + Canvas.FillRect(Rect); + end; +end; + +procedure TTBXScrollBar.Redraw; +begin + if Assigned(FOnRedrawRequest) then FOnRedrawRequest(Self); +end; + +procedure TTBXScrollBar.SBWndProc(var Message: TMessage); +var + I: Integer; + + procedure DefaultHandler; + begin + with Message do + Result := DefWindowProc(FHandle, Msg, wParam, lParam); + end; + +begin + case Message.Msg of + + WM_TIMER: with TWMTimer(Message) do + begin + I := 0; + TimerElapsed(TimerID, I); + if I > 0 then StartTimer(TimerID, I) + else StopTimer(TimerID); + Result := 0; + end; + + else + DefaultHandler; + end; +end; + +procedure TTBXScrollBar.SetBounds(const Value: TRect); +begin + FBounds := Value; + with Value do + begin + FLeft := Left; + FTop := Top; + FWidth := Right - Left; + FHeight := Bottom - Top; + end; + UpdateZones; +end; + +procedure TTBXScrollBar.SetKind(Value: TScrollBarKind); +begin + FKind := Value; + UpdateZones; +end; + +procedure TTBXScrollBar.SetPosition(Value: Integer); +begin + AdjustPosition(Value); + if Value <> FPosition then + begin + FPosition := Value; + if UserChange then + begin + Redraw; + if Assigned(FOnChange) then FOnChange(Self); + end; + end; +end; + +procedure TTBXScrollBar.SetRange(Value: Integer); +begin + if Value < 0 then Value := 0; + if Value <> FRange then + begin + FRange := Value; + Redraw; + SetPosition(Position); + end; +end; + +procedure TTBXScrollBar.StartAutoScroll(Direction, Interval: Integer); +begin + if Direction <> 0 then + begin + AutoScrollDirection := Direction; + AutoScrollInterval := Interval; + if not AutoScrolling then + begin + StartTimer(AUTO_SCROLL_TIMER, Interval); + AutoScrolling := True; + end; + end; +end; + +procedure TTBXScrollBar.StartTimer(ID, Elapse: Integer); +begin + SetTimer(Handle, ID, Elapse, nil); +end; + +procedure TTBXScrollBar.StopAutoScroll; +begin + if AutoScrolling then + begin + AutoScrolling := False; + StopTimer(AUTO_SCROLL_TIMER); + end; +end; + +procedure TTBXScrollBar.StopTimer(ID: Integer); +begin + KillTimer(Handle, ID); +end; + +procedure TTBXScrollBar.TimerElapsed(ID: Integer; var NewElapse: Integer); +begin + case ID of + SCROLL_TIMER: + if MouseDownZone <> sbzEmpty then + if not (MouseDownZone in [sbzPagePrev, sbzPageNext]) or + (GetZone(LastMousePoint.X, LastMousePoint.Y) = MouseDownZone) then + begin + HandleZoneClick(MouseDownZone); + NewElapse := 100; + end; + AUTO_SCROLL_TIMER: if AutoScrolling then + begin + NewElapse := AutoScrollInterval; + UpdatePosition(Position + AutoScrollDirection); + if (Position = 0) or (Position + Window = Range) then NewElapse := 0; + if Assigned(FOnAutoScroll) then + FOnAutoScroll(Self, AutoScrollDirection, AutoScrollInterval); + AutoScrolling := NewElapse > 0; + end; + end; +end; + +procedure TTBXScrollBar.UpdatePosition(NewPosition: Integer); +begin + UserChange := True; + if NewPosition < 0 then NewPosition := 0; + if NewPosition > Range - Window then NewPosition := Range - Window; + Position := NewPosition; + UserChange := False; +end; + +procedure TTBXScrollBar.UpdateZones; +var + SzL, SzT: Integer; + ButtonSize: Integer; + Lo, Hi: Integer; + HandleSize, HandlePos: Integer; + Window: Integer; + IsVert: Boolean; + + procedure SetZone(var R: TRect; Lo, Hi: Integer); + begin + if IsVert then + begin + R.Left := 0; + R.Right := Width; + R.Top := Lo; + R.Bottom := Hi; + end + else + begin + R.Left := Lo; + R.Right := Hi; + R.Top := 0; + R.Bottom := Height; + end; + end; + +begin + IsVert := Kind = sbVertical; + Window := GetEffectiveWindow; + + if IsVert then + begin + SzL := Height; + SzT := Width; + end + else + begin + SzL := Width; + SzT := Height; + end; + + + { Buttons } + ButtonSize := SzT; + if ButtonSize * 2 >= SzL - 2 then ButtonSize := (SzL - 2) div 2; + SetZone(Zones[sbzPrev], 0, ButtonSize); + SetZone(Zones[sbzNext], SzL - ButtonSize, SzL); + + { Handle } + Lo := ButtonSize; + Hi := SzL - ButtonSize; + if GetEnabled and (Hi - Lo > MIN_SB_HANDLE_SIZE + 4) then + begin + HandleSize := Round((Hi - Lo) * Window / Range); + if HandleSize >= MIN_SB_HANDLE_SIZE then + HandlePos := Round((Hi - Lo) * Position / Range) + else + begin + HandleSize := MIN_SB_HANDLE_SIZE; + HandlePos := Round((Hi - Lo - MIN_SB_HANDLE_SIZE) * Position / (Range - Window)); + end; + Inc(HandlePos, Lo); + SetZone(Zones[sbzHandle], HandlePos, HandlePos + HandleSize); + SetZone(Zones[sbzPagePrev], Lo, HandlePos); + SetZone(Zones[sbzPageNext], HandlePos + HandleSize, Hi); + Zones[sbzEmpty].Right := -1; + end + else + begin + { Invalidate invisible zones } + Zones[sbzPagePrev].Right := -1; + Zones[sbzHandle].Right := -1; + Zones[sbzPageNext].Right := -1; + SetZone(Zones[sbzEmpty], Lo, Hi); + end; +end; + +//----------------------------------------------------------------------------// + +{ TTBXCustomList } + +constructor TTBXCustomList.Create(AOwner: TComponent); +begin + inherited; + FMinWidth := 32; + FMaxWidth := 0; + FMaxVisibleItems := 8; + FItemIndex := -1; +end; + +function TTBXCustomList.DoClearItem(ACanvas: TCanvas; ARect: TRect; AIndex, AHoverIndex: Integer): Boolean; +begin + Result := True; + if Assigned(FOnClearItem) then FOnClearItem(Self, ACanvas, ARect, AIndex, AHoverIndex, Result); +end; + +function TTBXCustomList.DoDrawItem(ACanvas: TCanvas; ARect: TRect; AIndex, AHoverIndex: Integer): Boolean; +begin + Result := True; + if Assigned(FOnDrawItem) then FOnDrawItem(Self, ACanvas, ARect, AIndex, AHoverIndex, Result); +end; + +procedure TTBXCustomList.DoMeasureHeight(ACanvas: TCanvas; var AHeight: Integer); +begin + if Assigned(FOnMeasureHeight) then FOnMeasureHeight(Self, ACanvas, AHeight); +end; + +procedure TTBXCustomList.DoMeasureWidth(ACanvas: TCanvas; AIndex: Integer; var AWidth: Integer); +begin + if Assigned(FOnMeasureWidth) then FOnMeasureWidth(Self, ACanvas, AIndex, AWidth); +end; + +procedure TTBXCustomList.DrawItem(ACanvas: TCanvas; AViewer: TTBXCustomListViewer; + const ARect: TRect; AIndex, AHoverIndex: Integer); +const + FillColors: array [Boolean] of TColor = (clWindow, clHighlight); + TextColors: array [Boolean] of TColor = (clWindowText, clHighlightText); +var + S: string; + R, R2: TRect; + ImgList: TCustomImageList; +begin + ACanvas.Brush.Color := FillColors[AIndex = AHoverIndex]; + if DoClearItem(ACanvas, ARect, AIndex, AHoverIndex) then ACanvas.FillRect(ARect); + + ACanvas.Font.Color := TextColors[AIndex = AHoverIndex]; + if DoDrawItem(ACanvas, ARect, AIndex, AHoverIndex) then + begin + R := ARect; + InflateRect(R, -4, 1); + ImgList := AViewer.GetImageList; + if ShowImages and (ImgList <> nil) then + begin + R2.Left := R.Left; + R2.Top := (R.Top + R.Bottom - ImgList.Height) div 2; + R2.Right := R2.Left + ImgList.Width; + R2.Bottom := R2.Top + ImgList.Height; + if Enabled then ImgList.Draw(ACanvas, R2.Left, R2.Top, GetImageIndex(AIndex)) + else DrawTBXImage(ACanvas, R2, ImgList, GetImageIndex(AIndex), ISF_DISABLED); + Inc(R.Left, ImgList.Width + CImageSpacing); + end; + + S := GetItemText(AIndex); + if Length(S) > 0 then + begin + ACanvas.Brush.Style := bsClear; + DrawText(ACanvas.Handle, PChar(S), Length(S), R, DT_SINGLELINE or DT_VCENTER or DT_NOPREFIX); + ACanvas.Brush.Style := bsSolid; + end; + end; +end; + +function TTBXCustomList.GetImageIndex(ItemIndex: Integer): Integer; +begin + Result := ItemIndex; + if Assigned(FOnAdjustImageIndex) then FOnAdjustImageIndex(Self, ItemIndex, Result); +end; + +function TTBXCustomList.GetItemViewerClass(AView: TTBView): TTBItemViewerClass; +begin + Result := TTBXCustomListViewer; +end; + +procedure TTBXCustomList.HandleChange; +begin + if Assigned(FOnChange) then FOnChange(Self); +end; + +procedure TTBXCustomList.HandleHover(AIndex: Integer); +begin +end; + +procedure TTBXCustomList.MakeVisible(AIndex: Integer); +var + I: Integer; +begin + if FViewers <> nil then + for I := 0 to FViewers.Count - 1 do + TTBXCustomListViewer(FViewers[I]).MakeVisible(AIndex); +end; + +procedure TTBXCustomList.Notification(AComponent: TComponent; Operation: TOperation); +begin + inherited Notification(AComponent, Operation); + if (Operation = opRemove) and (AComponent = Images) then Images := nil; +end; + +procedure TTBXCustomList.SetItemIndex(Value: Integer); +var + I: Integer; +begin + if Value < 0 then Value := -1; + FItemIndex := Value; + + { Update viewers } + if FViewers <> nil then + for I := 0 to FViewers.Count - 1 do + TTBXCustomListViewer(FViewers[I]).ListChangeHandler(Value); + + if Assigned(FOnChange) then FOnChange(Self); +end; + +//----------------------------------------------------------------------------// + +{ TTBXCustomListViewer } + +procedure TTBXCustomListViewer.AdjustAutoScrollHover(var AIndex: Integer; Direction: Integer); +begin + AIndex := -1; // turn off hover when autoscrolling +end; + +procedure TTBXCustomListViewer.CalcSize(const Canvas: TCanvas; var AWidth, AHeight: Integer); +var + Item: TTBXCustomList; + I, W: Integer; +begin + Item := TTBXCustomList(Self.Item); + Canvas.Font := TTBViewAccess(View).GetFont; + FItemCount := Item.GetCount; + FItemHeight := GetItemHeight(Canvas); + + FVisibleItems := FItemCount; + if FVisibleItems > Item.MaxVisibleItems then FVisibleItems := Item.MaxVisibleItems + else if FVisibleItems <= 0 then FVisibleItems := 1; + + AHeight := FVisibleItems * FItemHeight; + + AWidth := 0; + for I := 0 to FItemCount - 1 do + begin + W := GetItemWidth(Canvas, I); + if W > AWidth then AWidth := W; + end; + + if FItemCount > FVisibleItems then FScrollBarWidth := GetSystemMetrics(SM_CXVSCROLL) + else FScrollBarWidth := 0; + Inc(AWidth, FScrollBarWidth); + + if AWidth < Item.MinWidth then AWidth := Item.MinWidth; + if (Item.MaxWidth > Item.MinWidth) and (AWidth > Item.MaxWidth) then AWidth := Item.MaxWidth; +end; + +constructor TTBXCustomListViewer.Create(AView: TTBView; AItem: TTBCustomItem; AGroupLevel: Integer); +var + Index: Integer; +begin + inherited; + Index := TTBXCustomList(AItem).ItemIndex; + FItemCount := TTBXCustomList(AItem).GetCount; + if (Index >= 0) and (Index < FItemCount) then + with TTBXCustomList(AItem) do + begin + FVisibleItems := GetCount; + if FVisibleItems > MaxVisibleItems then FVisibleItems := MaxVisibleItems; + if Index < FOffset then FOffset := Index + else if Index >= FOffset + FVisibleItems then FOffset := Index - FVisibleItems + 1 + end; + FHoverIndex := Index; + if FHoverIndex > FItemCount then FHoverIndex := -1; + AddToList(TTBXCustomList(AItem).FViewers, Self); +end; + +destructor TTBXCustomListViewer.Destroy; +begin + RemoveFromList(TTBXCustomList(Item).FViewers, Self); + if FScrollBar <> nil then FScrollBar.Free; + inherited; +end; + +procedure TTBXCustomListViewer.DrawItems(const Canvas: TCanvas; const ClientAreaRect: TRect); +var + I: Integer; + R: TRect; +begin + R := ClientAreaRect; + R.Bottom := FItemHeight; + Dec(R.Right, FScrollBarWidth); + Canvas.Font := TTBViewAccess(View).GetFont; + + for I := FOffset to FItemCount - 1 do + begin + if RectVisible(Canvas.Handle, R) then + TTBXCustomList(Item).DrawItem(Canvas, Self, R, I, HoverIndex); + R.Top := R.Bottom; + Inc(R.Bottom, FItemHeight); + if R.Bottom > FHeight then Break; + end; + + if R.Top < ClientAreaRect.Bottom then + begin + R.Bottom := ClientAreaRect.Bottom; + Canvas.Brush.Color := clWindow; + Canvas.FillRect(R); + end; +end; + +function TTBXCustomListViewer.GetItemHeight(ACanvas: TCanvas): Integer; +var + ImgList: TCustomImageList; +begin + Result := ACanvas.TextHeight('Q') + 2; + with TTBXStringList(Item) do + begin + ImgList := GetImageList; + if ShowImages and (ImgList <> nil) and (Result < ImgList.Height + 2) then + Result := ImgList.Height + 2; + DoMeasureHeight(ACanvas, Result); + end; +end; + +function TTBXCustomListViewer.GetItemIndexAt(X, Y: Integer): Integer; +begin + if (X < 0) or (X > FWidth - FScrollBarWidth) then Result := -1 + else + begin + Result := (Y div FItemHeight) + FOffset; + if (Result < FOffset) or (Result >= FOffset + FVisibleItems) or (Result >= FItemCount) then + Result := - 1; + end; +end; + +function TTBXCustomListViewer.GetItemRect(Index: Integer): TRect; +begin + { Note this method works properly only after Draw is called } + Result := FLastClientRect; + Inc(Result.Top, (Index - FOffset) * FItemHeight); + Result.Bottom := Result.Top + FItemHeight; + Dec(Result.Right, FScrollBarWidth); +end; + +function TTBXCustomListViewer.GetItemWidth(ACanvas: TCanvas; Index: Integer): Integer; +var + S: string; + ImgList: TCustomImageList; +begin + with TTBXStringList(Item) do + begin + S := GetItemText(Index); + Result := ACanvas.TextWidth(S); + if ShowImages then + begin + ImgList := GetImageList; + if ImgList <> nil then + begin + Inc(Result, ImgList.Width); + if Length(S) > 0 then Inc(Result, CImageSpacing); + end; + end; + Inc(Result, 8); + DoMeasureWidth(ACanvas, Index, Result) + end; +end; + +procedure TTBXCustomListViewer.HandleAutoScroll(var Direction, Interval: Integer); +begin + // do nothing by default +end; + +procedure TTBXCustomListViewer.KeyDown(var Key: Word; Shift: TShiftState); +var + OldIndex, NewIndex: Integer; +begin + OldIndex := FHoverIndex; + case Key of + VK_UP: NewIndex := OldIndex - 1; + VK_DOWN: NewIndex := OldIndex + 1; + VK_PRIOR: NewIndex := OldIndex - FVisibleItems; + VK_NEXT: NewIndex := OldIndex + FVisibleItems; + VK_HOME: NewIndex := 0; + VK_END: NewIndex := FItemCount - 1; + VK_RETURN: + begin + TTBXCustomList(Item).ItemIndex := FHoverIndex; + Exit; + end; + else + Exit; + end; + Key := 0; + if NewIndex < 0 then NewIndex := 0; + if NewIndex >= FItemCount then NewIndex := FItemCount - 1; + TTBXCustomList(Item).ItemIndex := NewIndex; +end; + +procedure TTBXCustomListViewer.ListChangeHandler(NewIndex: Integer); +begin + if not IsChanging and (NewIndex <> HoverIndex) then + begin + IsChanging := True; + HoverIndex := NewIndex; + TTBXCustomList(Item).HandleHover(NewIndex); + MakeVisible(HoverIndex); + UpdateItems; + IsChanging := False; + end; +end; + +procedure TTBXCustomListViewer.MakeVisible(Index: Integer); +begin + if (Index >= 0) and (Index < FItemCount) then + begin + if Index < FOffset then FScrollBar.UpdatePosition(Index) + else if Index >= FOffset + FVisibleItems then FScrollBar.UpdatePosition(Index - FVisibleItems + 1); + end; +end; + +procedure TTBXCustomListViewer.MouseDown(Shift: TShiftState; X, Y: Integer; var MouseDownOnMenu: Boolean); +begin + if X > FWidth - FScrollBarWidth then + begin + Dec(X, FWidth - FScrollBarWidth); + MouseInScrollBar := True; + FScrollBar.MouseDown(mbLeft, X, Y); + MouseDownOnMenu := False; + end + else + begin + MouseIsDown := True; + MouseMove(X, Y); + end; + inherited; + View.SetCapture; +end; + +procedure TTBXCustomListViewer.MouseMove(X, Y: Integer); +var + NewHoverIndex, OldHoverIndex, IndexLo, IndexHi, I: Integer; + R: TRect; + Canvas: TCanvas; + DC: HDC; + V, Dir: Integer; +begin + if MouseInScrollBar then + begin + Dec(X, FWidth - FScrollBarWidth); + FScrollBar.MouseMove(X, Y); + Exit; + end; + + if not View.Capture and (GetKeyState(VK_LBUTTON) < 0) then + begin + View.SetCapture; + MouseIsDown := True; + end; + + NewHoverIndex := GetItemIndexAt(X, Y); + if FScrollBar <> nil then + begin + if MouseIsDown and ((Y < 0) or (Y >= FHeight)) then + begin + { Get AutoScroll Intervals } + V := Y; + if V >= FHeight then Dec(V, FHeight - 1); + V := Abs(V); + if Y < 0 then Dir := -1 else Dir := 1; + case V of + 0..9: V := 150; + 10..29: V := 100; + 30..50: begin V := 100; Dir := Dir * 2; end; + else + V := 100; + Dir := Dir * 4; + end; + + if ((Dir < 0) and (FOffset > 0)) or + ((Dir > 0) and (FOffset + FVisibleItems < FItemCount)) then + FScrollBar.StartAutoScroll(Dir, V) + else + FScrollBar.StopAutoScroll; + AdjustAutoScrollHover(NewHoverIndex, Dir); + end + else FScrollBar.StopAutoScroll; + end; + + if not MouseIsDown and (NewHoverIndex = -1) then Exit; + + if NewHoverIndex <> FHoverIndex then + begin + Canvas := TCanvas.Create; + DC := GetDC(View.Window.Handle); + OldHoverIndex := FHoverIndex; + FHoverIndex := NewHoverIndex; + try + SetWindowOrgEx(DC, -BoundsRect.Left, -BoundsRect.Top, nil); + Canvas.Handle := DC; + Canvas.Font := TTBViewAccess(View).GetFont; + + IndexLo := OldHoverIndex; + IndexHi := FHoverIndex; + if FHoverIndex < OldHoverIndex then + begin + IndexLo := FHoverIndex; + IndexHi := OldHoverIndex; + end; + for I := IndexLo to IndexHi do + begin + R := GetItemRect(I); + if (R.Top >= 0) and (R.Bottom <= FHeight) and RectVisible(DC, R) then + TTBXCustomList(Item).DrawItem(Canvas, Self, R, I, HoverIndex); + end; + finally + Canvas.Handle := 0; + Canvas.Free; + ReleaseDC(View.Window.Handle, DC); + end; + TTBXCustomList(Item).HandleHover(FHoverIndex); + end; +end; + +procedure TTBXCustomListViewer.MouseUp(X, Y: Integer; MouseWasDownOnMenu: Boolean); +var + DAD: TTBDoneActionData; +begin + if FScrollBar <> nil then FScrollBar.StopAutoScroll; + if MouseInScrollBar then + begin + inherited; + Dec(X, FWidth - FScrollBarWidth); + FScrollBar.MouseUp(mbLeft, X, Y); + DAD := TTBViewAccess(TTBViewAccess(View).GetRootView).DoneActionData; + DAD.DoneAction := tbdaNone; + TTBViewAccess(TTBViewAccess(View).GetRootView).DoneActionData := DAD; + MouseInScrollBar := False; + end + else if MouseIsDown then + begin + MouseIsDown := False; + TTBXCustomList(Item).ItemIndex := FHoverIndex; + inherited; + DAD := TTBViewAccess(TTBViewAccess(View).GetRootView).DoneActionData; + DAD.Sound := False; + TTBViewAccess(TTBViewAccess(View).GetRootView).DoneActionData := DAD; + end; +end; + +procedure TTBXCustomListViewer.MouseWheel(WheelDelta, X, Y: Integer); +var + IsNegative: Boolean; +begin + if FScrollBar <> nil then + begin + Inc(FWheelAccumulator, WheelDelta); + while Abs(FWheelAccumulator) >= WHEEL_DELTA do + begin + IsNegative := FWheelAccumulator < 0; + FWheelAccumulator := Abs(FWheelAccumulator) - WHEEL_DELTA; + if IsNegative then + begin + if FWheelAccumulator <> 0 then FWheelAccumulator := -FWheelAccumulator; + FScrollBar.UpdatePosition(FScrollBar.Position + 1) + end + else + FScrollBar.UpdatePosition(FScrollBar.Position - 1) + end; + end; +end; + +procedure TTBXCustomListViewer.Paint(const Canvas: TCanvas; + const ClientAreaRect: TRect; IsHoverItem, IsPushed, UseDisabledShadow: Boolean); +begin + { Cache some important info for later usage } + FLastClientRect := ClientAreaRect; + with ClientAreaRect do + begin + FWidth := Right - Left; + FHeight := Bottom - Top; + end; + + DrawItems(Canvas, ClientAreaRect); + + if FScrollBarWidth > 0 then + begin + if FScrollBar = nil then + begin + FScrollBar := TTBXScrollBar.Create; + FScrollBar.Kind := sbVertical; + FScrollBar.OnRedrawRequest := SBRedrawHandler; + FScrollBar.OnChange := SBChangeHandler; + FScrollBar.OnAutoScroll := SBAutoScrollHandler; + end; + FScrollBar.Bounds := Rect(ClientAreaRect.Right - FScrollBarWidth, + ClientAreaRect.Top, ClientAreaRect.Right, ClientAreaRect.Bottom); + FScrollBar.Range := FItemCount; + FScrollBar.Window := FVisibleItems; + FScrollBar.Position := FOffset; + FScrollBar.PaintTo(Canvas); + end; +end; + +procedure TTBXCustomListViewer.SBAutoScrollHandler(Sender: TObject; + var Direction, Interval: Integer); +begin + HandleAutoScroll(Direction, Interval); +end; + +procedure TTBXCustomListViewer.SBChangeHandler(Sender: TObject); +begin + FOffset := FScrollBar.Position; + UpdateItems; +end; + +procedure TTBXCustomListViewer.SBRedrawHandler(Sender: TObject); +var + DC: HDC; + Canvas: TCanvas; +begin + Canvas := TCanvas.Create; + DC := GetDC(View.Window.Handle); + try + SetWindowOrgEx(DC, -BoundsRect.Left, -BoundsRect.Top, nil); + Canvas.Handle := DC; + FScrollBar.PaintTo(Canvas); + finally + Canvas.Handle := 0; + Canvas.Free; + ReleaseDC(View.Window.Handle, DC); + end; +end; + +procedure TTBXCustomListViewer.UpdateItems; +var + DC: HDC; + Canvas: TCanvas; +begin + if Assigned(FScrollBar) then FOffset := FScrollBar.Position + else FOffset := 0; + Canvas := TCanvas.Create; + DC := GetDC(View.Window.Handle); + try + SetWindowOrgEx(DC, -BoundsRect.Left, -BoundsRect.Top, nil); + Canvas.Handle := DC; + DrawItems(Canvas, FLastClientRect); + finally + Canvas.Handle := 0; + Canvas.Free; + ReleaseDC(View.Window.Handle, DC); + end; +end; + + +//----------------------------------------------------------------------------// + +{ TTBXStringList } + +constructor TTBXStringList.Create(AOwner: TComponent); +begin + inherited; + FStrings := TStringList.Create; +end; + +destructor TTBXStringList.Destroy; +begin + FStrings.Free; + inherited; +end; + +function TTBXStringList.GetCount: Integer; +begin + Result := FStrings.Count; +end; + +function TTBXStringList.GetItemText(Index: Integer): string; +begin + Result := FStrings[Index]; +end; + +procedure TTBXStringList.SetStrings(Value: TStrings); +begin + FStrings.Assign(Value); +end; + + +//----------------------------------------------------------------------------// + +{ TTBXUndoList } + +procedure TTBXUndoList.DrawItem(ACanvas: TCanvas; AViewer: TTBXCustomListViewer; + const ARect: TRect; AIndex, AHoverIndex: Integer); +const + FillColors: array [Boolean] of TColor = (clWindow, clHighlight); + TextColors: array [Boolean] of TColor = (clWindowText, clHighlightText); +var + S: string; + R: TRect; +begin + ACanvas.Brush.Color := FillColors[AIndex <= AHoverIndex]; + ACanvas.FillRect(ARect); + S := Strings[AIndex]; + if Length(S) > 0 then + begin + R := ARect; + InflateRect(R, -4, 1); + ACanvas.Font.Color := TextColors[AIndex <= AHoverIndex]; + ACanvas.Brush.Style := bsClear; + DrawText(ACanvas.Handle, PChar(S), Length(S), R, DT_SINGLELINE or DT_VCENTER); + ACanvas.Brush.Style := bsSolid; + end; +end; + +function TTBXUndoList.GetItemViewerClass(AView: TTBView): TTBItemViewerClass; +begin + Result := TTBXUndoListViewer; +end; + +procedure TTBXUndoList.HandleHover(AIndex: Integer); +begin + ItemIndex := AIndex; +end; + + +//----------------------------------------------------------------------------// + +{ TTBXUndoListViewer } + +procedure TTBXUndoListViewer.AdjustAutoScrollHover(var AIndex: Integer; Direction: Integer); +begin + if Direction < 0 then AIndex := FOffset + else if Direction > 0 then AIndex := FOffset + FVisibleItems - 1; +end; + +procedure TTBXUndoListViewer.HandleAutoScroll(var Direction, Interval: Integer); +begin + inherited; + if Direction < 0 then HoverIndex := FOffset + else if Direction > 0 then HoverIndex := FOffset + FVisibleItems - 1 + else Exit; + TTBXCustomList(Item).HandleHover(HoverIndex); + UpdateItems; +end; + +end. diff --git a/official/2.1.6+2.1.beta1/TBX/TBXMDI.pas b/official/2.1.6+2.1.beta1/TBX/TBXMDI.pas new file mode 100644 index 0000000..0c7922e --- /dev/null +++ b/official/2.1.6+2.1.beta1/TBX/TBXMDI.pas @@ -0,0 +1,728 @@ +unit TBXMDI; + + +// TBX Package +// Copyright 2001-2004 Alex A. Denisov. All Rights Reserved +// See TBX.chm for license and installation instructions +// +// Parts of the code are converted from original Toolbar2000 sources. +// Original Copyright: +// Copyright (C) 1998-2004 by Jordan Russell. All rights reserved. +// +// $Id: TBXMDI.pas 7 2004-02-21 06:07:53Z $ + + +interface + +{$I ..\..\Source\TB2Ver.inc} +{$I TBX.inc} + +uses + Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, + Menus, TB2Item, TB2Toolbar, TBX; + +type + TTBXMDIButtonsItem = class; + TTBXMDISystemMenuItem = class; + TTBXMDIWindowItem = class; + + TTBXMDIHandler = class(TComponent) + private + FButtonsItem: TTBXMDIButtonsItem; + FSystemMenuItem: TTBXMDISystemMenuItem; + FToolbar: TTBCustomToolbar; + FStretchButtons: Boolean; + procedure SetToolbar(Value: TTBCustomToolbar); + procedure SetStretchButtons(Value: Boolean); + protected + procedure Notification(AComponent: TComponent; Operation: TOperation); override; + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + published + property Toolbar: TTBCustomToolbar read FToolbar write SetToolbar; + property StretchButtons: Boolean read FStretchButtons write SetStretchButtons default False; + end; + + TTBXMDIWindowItem = class(TTBXCustomItem) + private + FForm: TForm; + FWindowMenu: TMenuItem; + FOnUpdate: TNotifyEvent; + procedure ItemClick(Sender: TObject); + procedure SetForm(AForm: TForm); + protected + procedure EnabledChanged; override; + procedure GetChildren(Proc: TGetChildProc; Root: TComponent); override; + procedure Notification(AComponent: TComponent; Operation: TOperation); override; + public + constructor Create(AOwner: TComponent); override; + procedure InitiateAction; override; + published + property Enabled; + property FontSettings; + property OnUpdate: TNotifyEvent read FOnUpdate write FOnUpdate; + end; + + TTBXMDISystemMenuItem = class(TTBXCustomItem) + private + FImageList: TImageList; + procedure CommandClick(Sender: TObject); + protected + function GetItemViewerClass(AView: TTBView): TTBItemViewerClass; override; + public + constructor Create(AOwner: TComponent); override; + procedure Click; override; + end; + + TTBXMDISystemMenuItemViewer = class(TTBItemViewer) + protected + procedure CalcSize(const Canvas: TCanvas; var AWidth, AHeight: Integer); override; + procedure Paint(const Canvas: TCanvas; const ClientAreaRect: TRect; + IsSelected, IsPushed, UseDisabledShadow: Boolean); override; + end; + + TTBXMDIButtonType = (tbmbMinimize, tbmbRestore, tbmbClose); + + TTBXMDIButtonItem = class(TTBCustomItem) + private + FButtonType: TTBXMDIButtonType; + protected + function GetItemViewerClass(AView: TTBView): TTBItemViewerClass; override; + public + constructor Create(AOwner: TComponent); override; + end; + + TTBXMDIButtonItemViewer = class(TTBItemViewer) + protected + procedure CalcSize(const Canvas: TCanvas; var AWidth, AHeight: Integer); override; + procedure Paint(const Canvas: TCanvas; const ClientAreaRect: TRect; + IsSelected, IsPushed, UseDisabledShadow: Boolean); override; + end; + + TTBXMDISepItem = class(TTBSeparatorItem) + protected + function GetItemViewerClass(AView: TTBView): TTBItemViewerClass; override; + end; + + TTBXMDISepItemViewer = class(TTBSeparatorItemViewer) + protected + procedure CalcSize (const Canvas: TCanvas; var AWidth, AHeight: Integer); override; + end; + + TTBXMDIButtonsItem = class(TTBCustomItem) + private + FMinimizeItem: TTBXMDIButtonItem; + FRestoreItem: TTBXMDIButtonItem; + FCloseItem: TTBXMDIButtonItem; + FSep1, FSep2: TTBXMDISepItem; + procedure InvalidateSystemMenuItem; + procedure ItemClick(Sender: TObject); + procedure UpdateState(W: HWND; Maximized: Boolean); + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + end; + +implementation + +{$R TBX_MDI.res} + +uses + TBXThemes, TB2Common, TB2Consts, CommCtrl; + +type + TTBViewAccess = class(TTBView); + TTBCustomToolbarAccess = class(TTBCustomToolbar); + + +//----------------------------------------------------------------------------// + +{ TTBXMDIHandler } + +constructor TTBXMDIHandler.Create (AOwner: TComponent); +begin + inherited; + FSystemMenuItem := TTBXMDISystemMenuItem.Create(Self); + FButtonsItem := TTBXMDIButtonsItem.Create(Self); +end; + +destructor TTBXMDIHandler.Destroy; +begin + Toolbar := nil; + inherited; +end; + +procedure TTBXMDIHandler.Notification(AComponent: TComponent; Operation: TOperation); +begin + inherited; + if (AComponent = FToolbar) and (Operation = opRemove) then Toolbar := nil; +end; + +procedure TTBXMDIHandler.SetStretchButtons(Value: Boolean); +begin + if Value <> FStretchButtons then + begin + FStretchButtons := Value; + with FButtonsItem do + if FStretchButtons then + begin + FMinimizeItem.ItemStyle := FMinimizeItem.ItemStyle + [tbisStretch]; + FRestoreItem.ItemStyle := FRestoreItem.ItemStyle + [tbisStretch]; + FCloseItem.ItemStyle := FCloseItem.ItemStyle + [tbisStretch]; + end + else + begin + FMinimizeItem.ItemStyle := FMinimizeItem.ItemStyle - [tbisStretch]; + FRestoreItem.ItemStyle := FRestoreItem.ItemStyle - [tbisStretch]; + FCloseItem.ItemStyle := FCloseItem.ItemStyle - [tbisStretch]; + end; + end; +end; + +procedure TTBXMDIHandler.SetToolbar(Value: TTBCustomToolbar); +var + Rebuild: Boolean; +begin + if FToolbar <> Value then + begin + if Assigned(FToolbar) then with TTBCustomToolbarAccess(FToolbar) do + begin + Rebuild := False; + if FMDIButtonsItem = FButtonsItem then + begin + FMDIButtonsItem := nil; + Rebuild := True; + end; + if FMDISystemMenuItem = FSystemMenuItem then + begin + FMDISystemMenuItem := nil; + Rebuild := True; + end; + if Rebuild and Assigned(View) then View.RecreateAllViewers; + end; + FToolbar := Value; + if Assigned(Value) then with TTBCustomToolbarAccess(Value) do + begin + FreeNotification(Self); + FMDIButtonsItem := FButtonsItem; + FMDISystemMenuItem := FSystemMenuItem; + View.RecreateAllViewers; + end; + end; +end; + + +//----------------------------------------------------------------------------// + +{ TTBXMDISystemMenuItem } + +constructor TTBXMDISystemMenuItem.Create(AOwner: TComponent); +begin + inherited; + ItemStyle := ItemStyle + [tbisSubMenu, tbisDontSelectFirst] - + [tbisRedrawOnSelChange, tbisRedrawOnMouseOverChange]; + Caption := '&-'; + + FImageList := TImageList.Create(Self); + FImageList.Handle := ImageList_LoadBitmap(HInstance, 'TBXSYSMENUIMAGES', + 16, 0, $C0C0C0); + SubMenuImages := FImageList; +end; + +function TTBXMDISystemMenuItem.GetItemViewerClass(AView: TTBView): TTBItemViewerClass; +begin + Result := TTBXMDISystemMenuItemViewer; +end; + +procedure TTBXMDISystemMenuItem.Click; +var + I: Integer; + Form: TForm; + M: HMENU; + State, ID: UINT; + Item: TTBCustomItem; + Buf: array[0..1023] of Char; +begin + inherited; + Clear; + if Application.MainForm = nil then Exit; + Form := Application.MainForm.ActiveMDIChild; + if Form = nil then Exit; + M := GetSystemMenu(Form.Handle, False); + for I := 0 to GetMenuItemCount(M) - 1 do + begin + State := GetMenuState(M, I, MF_BYPOSITION); + if State and MF_SEPARATOR <> 0 then Add(TTBXSeparatorItem.Create(Self)) + else + begin + Item := TTBXCustomItem.Create(Self); + if State and MF_GRAYED <> 0 then Item.Enabled := False; + if GetMenuString(M, I, Buf, SizeOf(Buf), MF_BYPOSITION) = 0 then Buf[0] := #0; + Item.Caption := Buf; + ID := GetMenuItemID(M, I); + Item.Tag := ID; + case ID and $FFF0 of + SC_RESTORE: Item.ImageIndex := 3; + SC_MINIMIZE: Item.ImageIndex := 2; + SC_MAXIMIZE: Item.ImageIndex := 1; + SC_CLOSE: begin + Item.ImageIndex := 0; + Item.Options := Item.Options + [tboDefault]; + end; + end; + Item.OnClick := CommandClick; + Add(Item); + end; + end; +end; + +procedure TTBXMDISystemMenuItem.CommandClick (Sender: TObject); +var + Form: TForm; +begin + if Assigned(Application.MainForm) then + begin + Form := Application.MainForm.ActiveMDIChild; + if Assigned(Form) then + SendMessage(Form.Handle, WM_SYSCOMMAND, TTBXCustomItem(Sender).Tag, GetMessagePos); + end; +end; + + +//----------------------------------------------------------------------------// + +{ TTBXMDISystemMenuItemViewer } + +procedure TTBXMDISystemMenuItemViewer.CalcSize(const Canvas: TCanvas; + var AWidth, AHeight: Integer); +begin + AWidth := GetSystemMetrics(SM_CXSMICON) + 2; + AHeight := GetSystemMetrics(SM_CYSMICON) + 2; +end; + +procedure TTBXMDISystemMenuItemViewer.Paint(const Canvas: TCanvas; + const ClientAreaRect: TRect; IsSelected, IsPushed, UseDisabledShadow: Boolean); + + function GetIconHandle: HICON; + var + Form: TForm; + begin + Result := 0; + if Assigned(Application.MainForm) then + begin + Form := Application.MainForm.ActiveMDIChild; + if Assigned(Form) then Result := Form.Icon.Handle; + end; + if Result = 0 then Result := Application.Icon.Handle; + if Result = 0 then Result := LoadIcon(0, IDI_APPLICATION); + end; + +var + R: TRect; + IconHandle, TempIcon: HICON; +begin + R := ClientAreaRect; + InflateRect(R, -1, -1); + IconHandle := GetIconHandle; + TempIcon := CopyImage(IconHandle, IMAGE_ICON, R.Right - R.Left, + R.Bottom - R.Top, LR_COPYFROMRESOURCE); + if TempIcon <> 0 then + begin + DrawIconEx(Canvas.Handle, R.Left, R.Top, TempIcon, 0, 0, 0, 0, DI_NORMAL); + DestroyIcon(TempIcon); + end; +end; + + +//----------------------------------------------------------------------------// + +{ TTBXMDIButtonItem } + +constructor TTBXMDIButtonItem.Create (AOwner: TComponent); +begin + inherited; + ItemStyle := ItemStyle - [tbisSelectable] + [tbisRightAlign]; +end; + +function TTBXMDIButtonItem.GetItemViewerClass (AView: TTBView): TTBItemViewerClass; +begin + Result := TTBXMDIButtonItemViewer; +end; + + +//----------------------------------------------------------------------------// + +{ TTBXMDIButtonItemViewer } + +procedure TTBXMDIButtonItemViewer.CalcSize (const Canvas: TCanvas; + var AWidth, AHeight: Integer); +begin + if NewStyleControls then + begin + AWidth := GetSystemMetrics(SM_CXMENUSIZE) - CurrentTheme.MenuMDIDW; + if AWidth < 0 then AWidth := 0; + AHeight := GetSystemMetrics(SM_CYMENUSIZE) - CurrentTheme.MenuMDIDH; + if AHeight < 0 then AHeight := 0; + end + else + begin + AWidth := 16; + AHeight := 14; + end; +end; + +procedure TTBXMDIButtonItemViewer.Paint(const Canvas: TCanvas; + const ClientAreaRect: TRect; IsSelected, IsPushed, UseDisabledShadow: Boolean); +const + ButtonTypeFlags: array [TTBXMDIButtonType] of UINT = (DFCS_CAPTIONMIN, + DFCS_CAPTIONRESTORE, DFCS_CAPTIONCLOSE); + CDesigning: array [Boolean] of Integer = (0, IO_DESIGNING); +var + ItemInfo: TTBXItemInfo; +begin + FillChar(ItemInfo, SizeOf(ItemInfo), 0); + ItemInfo.ViewType := TVT_NORMALTOOLBAR; //GetViewType(View); + ItemInfo.ItemOptions := IO_TOOLBARSTYLE or CDesigning[csDesigning in Item.ComponentState]; + ItemInfo.Enabled := Item.Enabled{ or View.Customizing}; + ItemInfo.Pushed := IsPushed; + ItemInfo.Selected := False; + ItemInfo.ImageShown := False; + ItemInfo.ImageWidth := 0; + ItemInfo.ImageHeight := 0; + if IsSelected then + begin + if not ItemInfo.Enabled and not TTBViewAccess(View).MouseOverSelected then ItemInfo.HoverKind := hkKeyboardHover + else if ItemInfo.Enabled then ItemInfo.HoverKind := hkMouseHover; + end + else ItemInfo.HoverKind := hkNone; + ItemInfo.IsVertical := View.Orientation = tbvoVertical; + + CurrentTheme.PaintMDIButton(Canvas, ClientAreaRect, ItemInfo, + ButtonTypeFlags[TTBXMDIButtonItem(Item).FButtonType]); +end; + + +//----------------------------------------------------------------------------// + +{ TTBXMDISepItem } + +function TTBXMDISepItem.GetItemViewerClass(AView: TTBView): TTBItemViewerClass; +begin + Result := TTBXMDISepItemViewer; +end; + + +//----------------------------------------------------------------------------// + +{ TTBXMDISepItemViewer } + +procedure TTBXMDISepItemViewer.CalcSize(const Canvas: TCanvas; var AWidth, AHeight: Integer); +begin + if View.Orientation <> tbvoVertical then + begin + AWidth := 2; + AHeight := 6; + end + else + begin + AWidth := 6; + AHeight := 2; + end; +end; + + +//----------------------------------------------------------------------------// + +{ TTBXMDIButtonsItem } + +var + CBTHookHandle: HHOOK; + MDIButtonsItems: TList; + +function WindowIsMDIChild(W: HWND): Boolean; +var + I: Integer; + MainForm, ChildForm: TForm; +begin + MainForm := Application.MainForm; + if Assigned(MainForm) then + for I := 0 to MainForm.MDIChildCount-1 do + begin + ChildForm := MainForm.MDIChildren[I]; + if ChildForm.HandleAllocated and (ChildForm.Handle = W) then + begin + Result := True; + Exit; + end; + end; + Result := False; +end; + +function CBTHook(Code: Integer; WParam: WPARAM; LParam: LPARAM): LRESULT; stdcall; +var + Maximizing: Boolean; + WindowPlacement: TWindowPlacement; + I: Integer; +begin + case Code of + HCBT_SETFOCUS: + if WindowIsMDIChild(HWND(WParam)) and Assigned(MDIButtonsItems) then + for I := 0 to MDIButtonsItems.Count-1 do + TTBXMDIButtonsItem(MDIButtonsItems[I]).InvalidateSystemMenuItem; + HCBT_MINMAX: + if WindowIsMDIChild(HWND(WParam)) and Assigned(MDIButtonsItems) and + (LParam in [SW_SHOWNORMAL, SW_SHOWMAXIMIZED, SW_MINIMIZE, SW_RESTORE]) then + begin + Maximizing := (LParam = SW_MAXIMIZE); + if (LParam = SW_RESTORE) and not IsZoomed(HWND(WParam)) then + begin + WindowPlacement.length := SizeOf(WindowPlacement); + GetWindowPlacement (HWND(WParam), @WindowPlacement); + Maximizing := (WindowPlacement.flags and WPF_RESTORETOMAXIMIZED <> 0); + end; + for I := 0 to MDIButtonsItems.Count-1 do + TTBXMDIButtonsItem(MDIButtonsItems[I]).UpdateState(HWND(WParam), Maximizing); + end; + HCBT_DESTROYWND: + if WindowIsMDIChild(HWND(WParam)) and Assigned(MDIButtonsItems) then + begin + for I := 0 to MDIButtonsItems.Count-1 do + TTBXMDIButtonsItem(MDIButtonsItems[I]).UpdateState(HWND(WParam), False); + end; + end; + Result := CallNextHookEx(CBTHookHandle, Code, WParam, LParam); +end; + +constructor TTBXMDIButtonsItem.Create(AOwner: TComponent); + + function CreateItem(const AType: TTBXMDIButtonType): TTBXMDIButtonItem; + begin + Result := TTBXMDIButtonItem.Create(Self); + Result.FButtonType := AType; + Result.OnClick := ItemClick; + end; + +begin + inherited; + ItemStyle := ItemStyle + [tbisEmbeddedGroup]; + FMinimizeItem := CreateItem(tbmbMinimize); + FRestoreItem := CreateItem(tbmbRestore); + FCloseItem := CreateItem(tbmbClose); + FSep1 := TTBXMDISepItem.Create(Self); + FSep1.Blank := True; + FSep1.ItemStyle := FSep1.ItemStyle + [tbisRightAlign, tbisNoLineBreak]; + FSep2 := TTBXMDISepItem.Create(Self); + FSep2.Blank := True; + FSep2.ItemStyle := FSep2.ItemStyle + [tbisRightAlign, tbisNoLineBreak]; + Add(FSep1); + Add(FMinimizeItem); + Add(FRestoreItem); + Add(FSep2); + Add(FCloseItem); + UpdateState(0, False); + AddToList(MDIButtonsItems, Self); + if CBTHookHandle = 0 then CBTHookHandle := SetWindowsHookEx(WH_CBT, CBTHook, 0, GetCurrentThreadId); +end; + +destructor TTBXMDIButtonsItem.Destroy; +begin + RemoveFromList(MDIButtonsItems, Self); + if (MDIButtonsItems = nil) and (CBTHookHandle <> 0) then + begin + UnhookWindowsHookEx(CBTHookHandle); + CBTHookHandle := 0; + end; + inherited; +end; + +procedure TTBXMDIButtonsItem.UpdateState(W: HWND; Maximized: Boolean); +var + HasMaxChild, VisibilityChanged: Boolean; + + procedure UpdateVisibleEnabled(const Item: TTBCustomItem; const AEnabled: Boolean); + begin + if (Item.Visible <> HasMaxChild) or (Item.Enabled <> AEnabled) then + begin + Item.Visible := HasMaxChild; + Item.Enabled := AEnabled; + VisibilityChanged := True; + end; + end; + +var + MainForm, ActiveMDIChild, ChildForm: TForm; + I: Integer; +begin + HasMaxChild := False; + MainForm := Application.MainForm; + ActiveMDIChild := nil; + if Assigned(MainForm) then + begin + for I := 0 to MainForm.MDIChildCount-1 do + begin + ChildForm := MainForm.MDIChildren[I]; + if ChildForm.HandleAllocated and + (((ChildForm.Handle = W) and Maximized) or + ((ChildForm.Handle <> W) and IsZoomed(ChildForm.Handle))) then + begin + HasMaxChild := True; + Break; + end; + end; + ActiveMDIChild := MainForm.ActiveMDIChild; + end; + + VisibilityChanged := False; + UpdateVisibleEnabled(TTBXMDIHandler(Owner).FSystemMenuItem, True); + UpdateVisibleEnabled(FSep1, True); + UpdateVisibleEnabled(FMinimizeItem, (ActiveMDIChild = nil) or + (GetWindowLong(ActiveMDIChild.Handle, GWL_STYLE) and WS_MINIMIZEBOX <> 0)); + UpdateVisibleEnabled(FRestoreItem, True); + UpdateVisibleEnabled(FSep2, True); + UpdateVisibleEnabled(FCloseItem, True); + + if VisibilityChanged and Assigned((Owner as TTBXMDIHandler).FToolbar) then + begin + TTBXMDIHandler(Owner).FToolbar.View.InvalidatePositions; + TTBXMDIHandler(Owner).FToolbar.View.TryValidatePositions; + end; +end; + +procedure TTBXMDIButtonsItem.ItemClick (Sender: TObject); +var + MainForm, ChildForm: TForm; + Cmd: WPARAM; +begin + MainForm := Application.MainForm; + if Assigned(MainForm) then begin + ChildForm := MainForm.ActiveMDIChild; + if Assigned(ChildForm) then begin + { Send WM_SYSCOMMAND messages so that we get sounds } + if Sender = FRestoreItem then + Cmd := SC_RESTORE + else if Sender = FCloseItem then + Cmd := SC_CLOSE + else + Cmd := SC_MINIMIZE; + SendMessage(ChildForm.Handle, WM_SYSCOMMAND, Cmd, GetMessagePos); + end; + end; +end; + +procedure TTBXMDIButtonsItem.InvalidateSystemMenuItem; +var + View: TTBView; +begin + if Assigned((Owner as TTBXMDIHandler).FToolbar) then + begin + View := TTBXMDIHandler(Owner).FToolbar.View; + View.Invalidate (View.Find(TTBXMDIHandler(Owner).FSystemMenuItem)); + end; +end; + + +//----------------------------------------------------------------------------// + +{ TTBXMDIWindowItem } + +constructor TTBXMDIWindowItem.Create(AOwner: TComponent); +var + Form: TForm; +begin + inherited; + ItemStyle := ItemStyle + [tbisEmbeddedGroup]; + Caption := STBMDIWindowItemDefCaption; + FWindowMenu := TMenuItem.Create(Self); + + if not(csDesigning in ComponentState) then + begin + { Need to set WindowMenu before MDI children are created. Otherwise the + list incorrectly shows the first 9 child windows, even if window 10+ is + active. } + Form := Application.MainForm; + if (Form = nil) and (Screen.FormCount > 0) then Form := Screen.Forms[0]; + SetForm (Form); + end; +end; + +procedure TTBXMDIWindowItem.GetChildren (Proc: TGetChildProc; Root: TComponent); +begin +end; + +procedure TTBXMDIWindowItem.Notification (AComponent: TComponent; Operation: TOperation); +begin + inherited; + if (Operation = opRemove) and (AComponent = FForm) then SetForm (nil); +end; + +procedure TTBXMDIWindowItem.SetForm (AForm: TForm); +begin + if FForm <> AForm then + begin + if Assigned(FForm) and (FForm.WindowMenu = FWindowMenu) then FForm.WindowMenu := nil; + FForm := AForm; + if Assigned(FForm) then FForm.FreeNotification (Self); + end; + if Assigned(FForm) then FForm.WindowMenu := FWindowMenu; +end; + +procedure TTBXMDIWindowItem.EnabledChanged; +var + I: Integer; +begin + inherited; + for I := 0 to Count-1 do Items[I].Enabled := Enabled; +end; + +procedure TTBXMDIWindowItem.InitiateAction; +var + MainForm: TForm; + I: Integer; + M: HMENU; + Item: TTBXCustomItem; + ItemCount: Integer; + Buf: array[0..1023] of Char; +begin + inherited; + if csDesigning in ComponentState then Exit; + MainForm := Application.MainForm; + if Assigned(MainForm) then SetForm(MainForm); + if FForm = nil then Exit; + if FForm.ClientHandle <> 0 then + { This is needed, otherwise windows selected on the More Windows dialog + don't move back into the list } + SendMessage (FForm.ClientHandle, WM_MDIREFRESHMENU, 0, 0); + M := FWindowMenu.Handle; + ItemCount := GetMenuItemCount(M) - 1; + if ItemCount < 0 then ItemCount := 0; + while Count < ItemCount do + begin + Item := TTBXCustomItem.Create(Self); + Item.Enabled := Enabled; + Item.OnClick := ItemClick; + Item.FontSettings := FontSettings; + Add(Item); + end; + while Count > ItemCount do Items[Count - 1].Free; + for I := 0 to ItemCount - 1 do + begin + Item := TTBXCustomItem(Items[I]); + Item.Tag := GetMenuItemID(M, I + 1); + if GetMenuString(M, I + 1, Buf, SizeOf(Buf), MF_BYPOSITION) = 0 then Buf[0] := #0; + Item.Caption := Buf; + Item.Checked := GetMenuState(M, I + 1, MF_BYPOSITION) and MF_CHECKED <> 0; + Item.FontSettings := FontSettings; + end; + if Assigned(FOnUpdate) then FOnUpdate(Self); +end; + +procedure TTBXMDIWindowItem.ItemClick (Sender: TObject); +var + Form: TForm; +begin + Form := Application.MainForm; + if Assigned(Form) then PostMessage(Form.Handle, WM_COMMAND, TTBXCustomItem(Sender).Tag, 0); +end; + +end. diff --git a/official/2.1.6+2.1.beta1/TBX/TBXOffice2003Theme.pas b/official/2.1.6+2.1.beta1/TBX/TBXOffice2003Theme.pas new file mode 100644 index 0000000..47d2420 --- /dev/null +++ b/official/2.1.6+2.1.beta1/TBX/TBXOffice2003Theme.pas @@ -0,0 +1,2040 @@ +unit TBXOffice2003Theme; + +// TBX Package +// Copyright 2001-2004 Alex A. Denisov. All Rights Reserved +// See TBX.chm for license and installation instructions +// +// Office2003 theme +// Copyright (c) Yury Plashenkov (Sep. 2005) +// +// Version for TBX version 2.1 + +interface + +{$I ..\..\Source\TB2Ver.inc} +{$I TBX.inc} + +// PngComponents is a set of components that allows you to include in your +// application semitransparent PNG images +// I advise you to get it from http://www.thany.org/ +// After installing, use TPngImageList (from PngComponents package) instead of +// "classic" TImageList + +// Comment next string if you use Toolbar2000 version different from 2.1.6 +{$DEFINE TB2K_VER216} + +// Uncomment next string if you want to see highlighted icons +//{$DEFINE HIGHLIGHTTOOLBARICONS} + +// Uncomment next string to turn on gradient captions on dockpanels +//{$DEFINE DOCKPANELGRADIENTCAPTION} + +uses + Windows, Messages, Graphics, Classes, TBXThemes, ImgList, TBXUxThemes; + +type + TItemPart = (ipBody, ipText, ipFrame); + TBtnItemState = (bisNormal, bisDisabled, bisSelected, bisPressed, bisHot, + bisDisabledHot, bisSelectedHot, bisPopupParent); + TMenuItemState = (misNormal, misDisabled, misHot, misDisabledHot); + TWinFramePart = (wfpBorder, wfpCaption, wfpCaptionText); + + TOffice2003Scheme = (osBlue, osMetallic, osGreen, osUnknown); + + TTBXOffice2003Theme = class(TTBXTheme) + private + FOnSetupColorCache: TNotifyEvent; + procedure TBXSysCommand(var Message: TMessage); message TBX_SYSCOMMAND; + protected + DockColor: TColor; + + ToolbarColor1: TColor; + ToolbarColor2: TColor; + ToolbarFrameColor1: TColor; + ToolbarFrameColor2: TColor; + SeparatorColor1: TColor; + SeparatorColor2: TColor; + DragHandleColor1: TColor; + DragHandleColor2: TColor; + + EmbeddedColor: TColor; + EmbeddedFrameColor: TColor; + EmbeddedDisabledColor: TColor; + + PopupColor: TColor; + PopupFrameColor: TColor; + + DockPanelColor: TColor; + WinFrameColors: array[TWinFramePart] of TColor; + MenuItemColors: array[TMenuItemState, TItemPart] of TColor; + BtnItemColors: array[TBtnItemState, ipText..ipFrame] of TColor; + BtnBodyColors: array[TBtnItemState, Boolean] of TColor; + + StatusPanelFrameColor: TColor; + FMDIAreaColor: TColor; + + procedure SetupColorCache; virtual; + protected + function GetPartColor(const ItemInfo: TTBXItemInfo; ItemPart: TItemPart): TColor; + function GetBtnColor(const ItemInfo: TTBXItemInfo; ItemPart: TItemPart; GradColor2: Boolean = False): TColor; + public + constructor Create(const AName: string); override; + destructor Destroy; override; + + function GetBooleanMetrics(Index: Integer): Boolean; override; + function GetIntegerMetrics(Index: Integer): Integer; override; + procedure GetMargins(MarginID: Integer; out Margins: TTBXMargins); override; + function GetImageOffset(Canvas: TCanvas; const ItemInfo: TTBXItemInfo; ImageList: TCustomImageList): TPoint; override; + function GetItemColor(const ItemInfo: TTBXItemInfo): TColor; override; + function GetItemTextColor(const ItemInfo: TTBXItemInfo): TColor; override; + function GetItemImageBackground(const ItemInfo: TTBXItemInfo): TColor; override; + function GetPopupShadowType: Integer; override; + procedure GetViewBorder(ViewType: Integer; out Border: TPoint); override; + function GetViewColor(AViewType: Integer): TColor; override; + procedure GetViewMargins(ViewType: Integer; out Margins: TTBXMargins); override; + + procedure PaintBackgnd(Canvas: TCanvas; const ADockRect, ARect, AClipRect: TRect; AColor: TColor; Transparent: Boolean; AViewType: Integer); override; + procedure PaintButton(Canvas: TCanvas; const ARect: TRect; const ItemInfo: TTBXItemInfo); override; + procedure PaintCaption(Canvas: TCanvas; const ARect: TRect; const ItemInfo: TTBXItemInfo; const ACaption: string; AFormat: Cardinal; Rotated: Boolean); override; + procedure PaintCheckMark(Canvas: TCanvas; ARect: TRect; const ItemInfo: TTBXItemInfo); override; + procedure PaintChevron(Canvas: TCanvas; ARect: TRect; const ItemInfo: TTBXItemInfo); override; + procedure PaintDock(Canvas: TCanvas; const ClientRect, DockRect: TRect; DockPosition: Integer); override; + procedure PaintDockPanelNCArea(Canvas: TCanvas; R: TRect; const DockPanelInfo: TTBXDockPanelInfo); override; + procedure PaintDropDownArrow(Canvas: TCanvas; const ARect: TRect; const ItemInfo: TTBXItemInfo); override; + procedure PaintEditButton(Canvas: TCanvas; const ARect: TRect; var ItemInfo: TTBXItemInfo; ButtonInfo: TTBXEditBtnInfo); override; + procedure PaintEditFrame(Canvas: TCanvas; const ARect: TRect; var ItemInfo: TTBXItemInfo; const EditInfo: TTBXEditInfo); override; + procedure PaintFloatingBorder(Canvas: TCanvas; const ARect: TRect; const WindowInfo: TTBXWindowInfo); override; + procedure PaintFrame(Canvas: TCanvas; const ARect: TRect; const ItemInfo: TTBXItemInfo); override; + procedure PaintImage(Canvas: TCanvas; ARect: TRect; const ItemInfo: TTBXItemInfo; ImageList: TCustomImageList; ImageIndex: Integer); override; + procedure PaintMDIButton(Canvas: TCanvas; ARect: TRect; const ItemInfo: TTBXItemInfo; ButtonKind: Cardinal); override; + procedure PaintMenuItem(Canvas: TCanvas; const ARect: TRect; var ItemInfo: TTBXItemInfo); override; + procedure PaintMenuItemFrame(Canvas: TCanvas; const ARect: TRect; const ItemInfo: TTBXItemInfo); override; + procedure PaintPageScrollButton(Canvas: TCanvas; const ARect: TRect; ButtonType: Integer; Hot: Boolean); override; + procedure PaintPopupNCArea(Canvas: TCanvas; R: TRect; const PopupInfo: TTBXPopupInfo); override; + procedure PaintSeparator(Canvas: TCanvas; ARect: TRect; ItemInfo: TTBXItemInfo; Horizontal, LineSeparator: Boolean); override; + procedure PaintToolbarNCArea(Canvas: TCanvas; R: TRect; const ToolbarInfo: TTBXToolbarInfo); override; + procedure PaintFrameControl(Canvas: TCanvas; R: TRect; Kind, State: Integer; Params: Pointer); override; + procedure PaintStatusBar(Canvas: TCanvas; R: TRect; Part: Integer); override; + + property MDIAreaColor: TColor read FMDIAreaColor; + + property OnSetupColorCache: TNotifyEvent read FOnSetupColorCache write FOnSetupColorCache; + end; + +function GetOffice2003Scheme: TOffice2003Scheme; +procedure PaintGradient(DC: HDC; const ARect: TRect; Color1, Color2: TColor); +procedure PaintIrregularGradient(DC: HDC; const ARect: TRect; Color1, Color2: TColor; Horz: Boolean); +function GetMDIWorkspaceColor: TColor; + +implementation + +uses TBXUtils, TB2Common, TB2Item, Controls, CommCtrl, Forms, SysUtils; + +function GetOffice2003Scheme: TOffice2003Scheme; +const + MaxChars = 1024; +var + pszThemeFileName, pszColorBuff, pszSizeBuf: PWideChar; + S: string; +begin + Result := osUnknown; + if USE_THEMES then + begin + GetMem(pszThemeFileName, 2 * MaxChars); + GetMem(pszColorBuff, 2 * MaxChars); + GetMem(pszSizeBuf, 2 * MaxChars); + try + if not Failed(GetCurrentThemeName(pszThemeFileName, MaxChars, pszColorBuff, MaxChars, pszSizeBuf, MaxChars)) then + if UpperCase(ExtractFileName(pszThemeFileName)) = 'LUNA.MSSTYLES' then + begin + S := UpperCase(pszColorBuff); + if S = 'NORMALCOLOR' then + Result := osBlue + else if S = 'METALLIC' then + Result := osMetallic + else if S = 'HOMESTEAD' then + Result := osGreen; + end; + finally + FreeMem(pszSizeBuf); + FreeMem(pszColorBuff); + FreeMem(pszThemeFileName); + end; + end; +end; + +procedure PaintGradient(DC: HDC; const ARect: TRect; Color1, Color2: TColor); +var + r1, g1, b1, r2, g2, b2: Byte; + I, Size: Integer; + hbr: HBRUSH; + lprc: TRect; +begin + Color1 := ColorToRGB(Color1); + Color2 := ColorToRGB(Color2); + if Color1 = Color2 then + FillRectEx(DC, ARect, Color1) + else + begin + Size := ARect.Bottom - ARect.Top; + if Size <= 0 then Exit; + + r1 := GetRValue(Color1); + g1 := GetGValue(Color1); + b1 := GetBValue(Color1); + r2 := GetRValue(Color2); + g2 := GetGValue(Color2); + b2 := GetBValue(Color2); + + lprc := ARect; + lprc.Bottom := lprc.Top + 1; + + Dec(Size); + for I := 0 to Size do + begin + hbr := CreateSolidBrush(RGB((r2 - r1) * I div Size + r1, (g2 - g1) * I div Size + g1, (b2 - b1) * I div Size + b1)); + FillRect(DC, lprc, hbr); + DeleteObject(hbr); + OffsetRect(lprc, 0, 1); + end; + end; +end; + +var + IrregularGradientValue: Integer; + +procedure PaintIrregularGradient(DC: HDC; const ARect: TRect; Color1, Color2: TColor; Horz: Boolean); +var + r1, g1, b1, r2, g2, b2: Integer; + rm1, gm1, bm1, rm2, gm2, bm2: Integer; + lprc: TRect; + I, Size, Middle: Integer; + hbr: HBRUSH; +begin + Color1 := ColorToRGB(Color1); + Color2 := ColorToRGB(Color2); + if Color1 = Color2 then + FillRectEx(DC, ARect, Color1) + else + begin + if IsRectEmpty(ARect) then Exit; + + r1 := GetRValue(Color1); + g1 := GetGValue(Color1); + b1 := GetBValue(Color1); + r2 := GetRValue(Color2); + g2 := GetGValue(Color2); + b2 := GetBValue(Color2); + + lprc := ARect; + + if Horz then + begin + Size := ARect.Right - ARect.Left; + lprc.Right := lprc.Left + 1; + end + else + begin + Size := ARect.Bottom - ARect.Top; + lprc.Bottom := lprc.Top + 1; + end; + + Middle := Size div 2; + + rm1 := (r2 - r1) * IrregularGradientValue div 40 + r1; + gm1 := (g2 - g1) * IrregularGradientValue div 40 + g1; + bm1 := (b2 - b1) * IrregularGradientValue div 40 + b1; + rm2 := (rm1 - r1) * Size div Middle + r1; + gm2 := (gm1 - g1) * Size div Middle + g1; + bm2 := (bm1 - b1) * Size div Middle + b1; + + Dec(Size); + for I := 0 to Middle - 1 do + begin + hbr := CreateSolidBrush(RGB((rm2 - r1) * I div Size + r1, (gm2 - g1) * I div Size + g1, (bm2 - b1) * I div Size + b1)); + FillRect(DC, lprc, hbr); + DeleteObject(hbr); + OffsetRect(lprc, Ord(Horz), Ord(not Horz)); + end; + + hbr := CreateSolidBrush(RGB(rm1, gm1, bm1)); + FillRect(DC, lprc, hbr); + DeleteObject(hbr); + OffsetRect(lprc, Ord(Horz), Ord(not Horz)); + + rm1 := rm1 * 2 - r2; + gm1 := gm1 * 2 - g2; + bm1 := bm1 * 2 - b2; + + for I := Middle + 1 to Size do + begin + hbr := CreateSolidBrush(RGB((r2 - rm1) * I div Size + rm1, (g2 - gm1) * I div Size + gm1, (b2 - bm1) * I div Size + bm1)); + FillRect(DC, lprc, hbr); + DeleteObject(hbr); + OffsetRect(lprc, Ord(Horz), Ord(not Horz)); + end; + end; +end; + +function GetMDIWorkspaceColor: TColor; +const + MDIColors: array[TOffice2003Scheme] of TColor = ($AE9990, $B39A9B, $7BA097, clBtnShadow); +begin + Result := MDIColors[GetOffice2003Scheme]; +end; + +var + StockImgList: TImageList; + CounterLock: Integer; + +procedure InitializeStock; +begin + StockImgList := TImageList.Create(nil); + StockImgList.Handle := ImageList_LoadBitmap(HInstance, 'TBXGLYPHS', 16, 0, clWhite); +end; + +procedure FinalizeStock; +begin + StockImgList.Free; +end; + +{ TTBXOffice2003Theme } + +function TTBXOffice2003Theme.GetBooleanMetrics(Index: Integer): Boolean; +begin + case Index of + TMB_OFFICEXPPOPUPALIGNMENT: Result := True; + TMB_EDITMENUFULLSELECT: Result := True; + TMB_EDITHEIGHTEVEN: Result := False; + TMB_SOLIDTOOLBARNCAREA: Result := False; + TMB_SOLIDTOOLBARCLIENTAREA: Result := True; + TMB_PAINTDOCKBACKGROUND: Result := True; + else + Result := False; + end; +end; + +function TTBXOffice2003Theme.GetIntegerMetrics(Index: Integer): Integer; +begin + case Index of + TMI_SPLITBTN_ARROWWIDTH: Result := 12; + + TMI_DROPDOWN_ARROWWIDTH: Result := 8; + TMI_DROPDOWN_ARROWMARGIN: Result := 3; + + TMI_MENU_IMGTEXTSPACE: Result := 5; + TMI_MENU_LCAPTIONMARGIN: Result := 3; + TMI_MENU_RCAPTIONMARGIN: Result := 3; + TMI_MENU_SEPARATORSIZE: Result := 3; + TMI_MENU_MDI_DW: Result := 2; + TMI_MENU_MDI_DH: Result := 2; + + TMI_TLBR_SEPARATORSIZE: Result := 6; + + TMI_EDIT_FRAMEWIDTH: Result := 1; + TMI_EDIT_TEXTMARGINHORZ: Result := 2; + TMI_EDIT_TEXTMARGINVERT: Result := 2; + TMI_EDIT_BTNWIDTH: Result := 14; + TMI_EDIT_MENURIGHTINDENT: Result := 1; + else + Result := -1; + end; +end; + +function TTBXOffice2003Theme.GetViewColor(AViewType: Integer): TColor; +begin + Result := DockColor; + if (AViewType and VT_TOOLBAR) = VT_TOOLBAR then + begin + if (AViewType and TVT_MENUBAR) = TVT_MENUBAR then Result := DockColor + else Result := ToolbarColor1; + end + else if (AViewType and VT_POPUP) = VT_POPUP then + begin + if (AViewType and PVT_LISTBOX) = PVT_LISTBOX then Result := clWindow + else Result := PopupColor; + end + else if (AViewType and VT_DOCKPANEL) = VT_DOCKPANEL then Result := DockPanelColor; +end; + +function TTBXOffice2003Theme.GetBtnColor(const ItemInfo: TTBXItemInfo; ItemPart: TItemPart; GradColor2: Boolean = False): TColor; +const + BFlags1: array [Boolean] of TBtnItemState = (bisDisabled, bisDisabledHot); + BFlags2: array [Boolean] of TBtnItemState = (bisSelected, bisSelectedHot); + BFlags3: array [Boolean] of TBtnItemState = (bisNormal, bisHot); +var + B: TBtnItemState; + Embedded: Boolean; +begin + with ItemInfo do + begin + Embedded := (ViewType and VT_TOOLBAR = VT_TOOLBAR) and (ViewType and TVT_EMBEDDED = TVT_EMBEDDED); + if not Enabled then B := BFlags1[HoverKind = hkKeyboardHover] + else if ItemInfo.IsPopupParent then B := bisPopupParent + else if Pushed then B := bisPressed + else if Selected then B := BFlags2[HoverKind <> hkNone] + else B := BFlags3[HoverKind <> hkNone]; + if ItemPart = ipBody then + Result := BtnBodyColors[B, GradColor2] + else + Result := BtnItemColors[B, ItemPart]; + if Embedded and (Result = clNone) then + begin + if ItemPart = ipBody then Result := EmbeddedColor; + if (ItemPart = ipFrame) and not Selected then Result := EmbeddedFrameColor; + end; + end; +end; + +function TTBXOffice2003Theme.GetPartColor(const ItemInfo: TTBXItemInfo; ItemPart: TItemPart): TColor; +const + MFlags1: array [Boolean] of TMenuItemState = (misDisabled, misDisabledHot); + MFlags2: array [Boolean] of TMenuItemState = (misNormal, misHot); + BFlags1: array [Boolean] of TBtnItemState = (bisDisabled, bisDisabledHot); + BFlags2: array [Boolean] of TBtnItemState = (bisSelected, bisSelectedHot); + BFlags3: array [Boolean] of TBtnItemState = (bisNormal, bisHot); +var + IsMenuItem, Embedded: Boolean; + M: TMenuItemState; + B: TBtnItemState; +begin + with ItemInfo do + begin + IsMenuItem := ((ViewType and PVT_POPUPMENU) = PVT_POPUPMENU) and + ((ItemOptions and IO_TOOLBARSTYLE) = 0); + Embedded := ((ViewType and VT_TOOLBAR) = VT_TOOLBAR) and + ((ViewType and TVT_EMBEDDED) = TVT_EMBEDDED); + if IsMenuItem then + begin + if not Enabled then M := MFlags1[HoverKind = hkKeyboardHover] + else M := MFlags2[HoverKind <> hkNone]; + Result := MenuItemColors[M, ItemPart]; + end + else + begin + if not Enabled then B := BFlags1[HoverKind = hkKeyboardHover] + else if ItemInfo.IsPopupParent then B := bisPopupParent + else if Pushed then B := bisPressed + else if Selected then B := BFlags2[HoverKind <> hkNone] + else B := BFlags3[HoverKind <> hkNone]; + if ItemPart = ipBody then + Result := BtnBodyColors[B, False] + else + Result := BtnItemColors[B, ItemPart]; + if Embedded and (Result = clNone) then + begin + if ItemPart = ipBody then Result := EmbeddedColor; + if ItemPart = ipFrame then Result := EmbeddedFrameColor; + end; + end; + end; +end; + +function TTBXOffice2003Theme.GetItemColor(const ItemInfo: TTBXItemInfo): TColor; +begin + Result := GetPartColor(ItemInfo, ipBody); + if Result = clNone then Result := GetViewColor(ItemInfo.ViewType); +end; + +function TTBXOffice2003Theme.GetItemTextColor(const ItemInfo: TTBXItemInfo): TColor; +begin + Result := GetPartColor(ItemInfo, ipText); +end; + +function TTBXOffice2003Theme.GetItemImageBackground(const ItemInfo: TTBXItemInfo): TColor; +begin + Result := GetBtnColor(ItemInfo, ipBody); + if Result = clNone then Result := GetViewColor(ItemInfo.ViewType); +end; + +procedure TTBXOffice2003Theme.GetViewBorder(ViewType: Integer; out Border: TPoint); +const + XMetrics: array [Boolean] of Integer = (SM_CXDLGFRAME, SM_CXFRAME); + YMetrics: array [Boolean] of Integer = (SM_CYDLGFRAME, SM_CYFRAME); +var + Resizable: Boolean; + + procedure SetBorder(X, Y: Integer); + begin + Border.X := X; + Border.Y := Y; + end; + +begin + if (ViewType and VT_TOOLBAR) = VT_TOOLBAR then + begin + if (ViewType and TVT_FLOATING) = TVT_FLOATING then + begin + Resizable := (ViewType and TVT_RESIZABLE) = TVT_RESIZABLE; + Border.X := GetSystemMetrics(XMetrics[Resizable]) - 1; + Border.Y := GetSystemMetrics(YMetrics[Resizable]) - 1; + end + else SetBorder(2, 2); + end + else if (ViewType and VT_POPUP) = VT_POPUP then + begin + if (ViewType and PVT_POPUPMENU) = PVT_POPUPMENU then Border.X := 1 + else Border.X := 2; + Border.Y := 2; + end + else if (ViewType and VT_DOCKPANEL) = VT_DOCKPANEL then + begin + if (ViewType and DPVT_FLOATING) = DPVT_FLOATING then + begin + Resizable := (ViewType and DPVT_RESIZABLE) = DPVT_RESIZABLE; + Border.X := GetSystemMetrics(XMetrics[Resizable]) - 1; + Border.Y := GetSystemMetrics(YMetrics[Resizable]) - 1; + end + else SetBorder(2, 2); + end + else SetBorder(0, 0); +end; + +procedure TTBXOffice2003Theme.GetMargins(MarginID: Integer; out Margins: TTBXMargins); +begin + with Margins do + case MarginID of + MID_TOOLBARITEM: + begin + LeftWidth := 2; RightWidth := 2; + TopHeight := 2; BottomHeight := 2; + end; + MID_MENUITEM: + begin + LeftWidth := 1; RightWidth := 1; + TopHeight := 3; BottomHeight := 3; + end; + MID_STATUSPANE: + begin + LeftWidth := 1; RightWidth := 3; + TopHeight := 1; BottomHeight := 1; + end; + else + LeftWidth := 0; + RightWidth := 0; + TopHeight := 0; + BottomHeight := 0; + end; +end; + +procedure TTBXOffice2003Theme.PaintBackgnd(Canvas: TCanvas; const ADockRect, ARect, AClipRect: TRect; + AColor: TColor; Transparent: Boolean; AViewType: Integer); +var + DC: HDC; + R: TRect; + Horz: Boolean; +begin + DC := Canvas.Handle; + if not Transparent then + begin + IntersectRect(R, ARect, AClipRect); + if ((AViewType and TVT_NORMALTOOLBAR = TVT_NORMALTOOLBAR) or (AViewType and TVT_TOOLWINDOW = TVT_TOOLWINDOW)) and not (AViewType and TVT_EMBEDDED = TVT_EMBEDDED) then + begin + if IsRectEmpty(ADockRect) then + Horz := (ARect.Right > ARect.Bottom) + else + Horz := Abs(R.Right - R.Left) > Abs(R.Bottom - R.Top); + PaintIrregularGradient(Canvas.Handle, R, ToolbarColor1, ToolbarColor2, not Horz); + end + else + FillRectEx(DC, R, AColor); + end; +end; + +procedure TTBXOffice2003Theme.PaintCaption(Canvas: TCanvas; + const ARect: TRect; const ItemInfo: TTBXItemInfo; const ACaption: string; + AFormat: Cardinal; Rotated: Boolean); +var + R: TRect; +begin + with ItemInfo, Canvas do + begin + R := ARect; + Brush.Style := bsClear; + if Font.Color = clNone then Font.Color := GetPartColor(ItemInfo, ipText); + if not Rotated then Windows.DrawText(Handle, PChar(ACaption), Length(ACaption), R, AFormat) + else DrawRotatedText(Handle, ACaption, R, AFormat); + Brush.Style := bsSolid; + end; +end; + +procedure TTBXOffice2003Theme.PaintCheckMark(Canvas: TCanvas; ARect: TRect; const ItemInfo: TTBXItemInfo); +var + DC: HDC; + X, Y: Integer; + C: TColor; +begin + DC := Canvas.Handle; + X := (ARect.Left + ARect.Right) div 2 - 2; + Y := (ARect.Top + ARect.Bottom) div 2 + 1; + C := GetBtnColor(ItemInfo, ipText); + if ItemInfo.ItemOptions and IO_RADIO > 0 then + begin + RoundRectEx(DC, X - 1, Y - 4, X + 5, Y + 2, 2, 2, MixColors(C, ToolbarColor1, 200), clNone); + RoundRectEx(DC, X - 1, Y - 4, X + 5, Y + 2, 6, 6, C, C); + end + else + PolylineEx(DC, [Point(X - 2, Y - 2), Point(X, Y), Point(X + 4, Y - 4), + Point(X + 4, Y - 3), Point(X, Y + 1), Point(X - 2, Y - 1), Point(X - 2, Y - 2)], C); +end; + +procedure TTBXOffice2003Theme.PaintChevron(Canvas: TCanvas; ARect: TRect; const ItemInfo: TTBXItemInfo); +const + Pattern: array[Boolean, 0..15] of Byte = ( + ($CC, 0, $66, 0, $33, 0, $66, 0, $CC, 0, 0, 0, 0, 0, 0, 0), + ($88, 0, $D8, 0, $70, 0, $20, 0, $88, 0, $D8, 0, $70, 0, $20, 0)); +var + R2: TRect; + W, H: Integer; +begin + R2 := ARect; + PaintButton(Canvas, ARect, ItemInfo); + if not ItemInfo.IsVertical then + begin + Inc(R2.Top, 4); + R2.Bottom := R2.Top + 5; + W := 8; + H := 5; + end + else + begin + R2.Left := R2.Right - 9; + R2.Right := R2.Left + 5; + W := 5; + H := 8; + end; + DrawGlyph(Canvas.Handle, R2, W, H, Pattern[ItemInfo.IsVertical][0], GetPartColor(ItemInfo, ipText)); +end; + +procedure TTBXOffice2003Theme.PaintEditButton(Canvas: TCanvas; const ARect: TRect; + var ItemInfo: TTBXItemInfo; ButtonInfo: TTBXEditBtnInfo); +var + DC: HDC; + BtnDisabled, BtnHot, BtnPressed, Embedded: Boolean; + R, BR: TRect; + X, Y: Integer; + SaveItemInfoPushed: Boolean; + C: TColor; +begin + DC := Canvas.Handle; + R := ARect; + Embedded := ((ItemInfo.ViewType and VT_TOOLBAR) = VT_TOOLBAR) and + ((ItemInfo.ViewType and TVT_EMBEDDED) = TVT_EMBEDDED); + + InflateRect(R, 1, 1); + Inc(R.Left); + with Canvas do + if ButtonInfo.ButtonType = EBT_DROPDOWN then + begin + BtnDisabled := (ButtonInfo.ButtonState and EBDS_DISABLED) <> 0; + BtnHot := (ButtonInfo.ButtonState and EBDS_HOT) <> 0; + BtnPressed := (ButtonInfo.ButtonState and EBDS_PRESSED) <> 0; + if not BtnDisabled then + begin + if BtnPressed or BtnHot or Embedded then PaintButton(Canvas, R, ItemInfo) + else if (ItemInfo.ViewType and VT_TOOLBAR) = VT_TOOLBAR then + begin + R := ARect; + if not Embedded then + begin + FrameRectEx(DC, R, clWindow, False); + C := clWindow; + end + else C := GetBtnColor(ItemInfo, ipFrame); + DrawLineEx(DC, R.Left - 1, R.Top, R.Left - 1, R.Bottom, C); + end; + end; + PaintDropDownArrow(Canvas, R, ItemInfo); + end + else if ButtonInfo.ButtonType = EBT_SPIN then + begin + BtnDisabled := (ButtonInfo.ButtonState and EBSS_DISABLED) <> 0; + BtnHot := (ButtonInfo.ButtonState and EBSS_HOT) <> 0; + + { Upper button } + BR := R; + BR.Bottom := (R.Top + R.Bottom + 1) div 2; + BtnPressed := (ButtonInfo.ButtonState and EBSS_UP) <> 0; + SaveItemInfoPushed := ItemInfo.Pushed; + ItemInfo.Pushed := BtnPressed; + if not BtnDisabled then + begin + if BtnPressed or BtnHot or Embedded then PaintButton(Canvas, BR, ItemInfo) + else if (ItemInfo.ViewType and VT_TOOLBAR) = VT_TOOLBAR then + begin + BR.Left := ARect.Left; BR.Top := ARect.Top; BR.Right := ARect.Right; + if not Embedded then + begin + FrameRectEx(DC, BR, clWindow, False); + C := clWindow; + end + else C := GetBtnColor(ItemInfo, ipFrame); + DrawLineEx(DC, BR.Left - 1, BR.Top, BR.Left - 1, BR.Bottom, C); + end; + end; + X := (BR.Left + BR.Right) div 2; + Y := (BR.Top + BR.Bottom - 1) div 2; + Pen.Color := GetPartColor(ItemInfo, ipText); + Brush.Color := Pen.Color; + Polygon([Point(X - 2, Y + 1), Point(X + 2, Y + 1), Point(X, Y - 1)]); + + { Lower button } + BR := R; + BR.Top := (R.Top + R.Bottom) div 2; + BtnPressed := (ButtonInfo.ButtonState and EBSS_DOWN) <> 0; + ItemInfo.Pushed := BtnPressed; + if not BtnDisabled then + begin + if BtnPressed or BtnHot or Embedded then PaintButton(Canvas, BR, ItemInfo) + else if (ItemInfo.ViewType and VT_TOOLBAR) = VT_TOOLBAR then + begin + BR.Left := ARect.Left; BR.Bottom := ARect.Bottom; BR.Right := ARect.Right; + if not Embedded then + begin + FrameRectEx(DC, BR, clWindow, False); + C := clWindow; + end + else C := GetBtnColor(ItemInfo, ipFrame); + DrawLineEx(DC, BR.Left - 1, BR.Top, BR.Left - 1, BR.Bottom, C); + end; + end; + X := (BR.Left + BR.Right) div 2; + Y := (BR.Top + BR.Bottom) div 2; + C := GetPartColor(ItemInfo, ipText); + PolygonEx(DC, [Point(X - 2, Y - 1), Point(X + 2, Y - 1), Point(X, Y + 1)], C, C); + + ItemInfo.Pushed := SaveItemInfoPushed; + end; +end; + +procedure TTBXOffice2003Theme.PaintEditFrame(Canvas: TCanvas; + const ARect: TRect; var ItemInfo: TTBXItemInfo; const EditInfo: TTBXEditInfo); +var + DC: HDC; + R: TRect; + W: Integer; + Embedded: Boolean; +begin + DC := Canvas.Handle; + R := ARect; + PaintFrame(Canvas, R, ItemInfo); + W := EditFrameWidth; + InflateRect(R, -W, -W); + Embedded := ((ItemInfo.ViewType and VT_TOOLBAR) = VT_TOOLBAR) and + ((ItemInfo.ViewType and TVT_EMBEDDED) = TVT_EMBEDDED); + if not (ItemInfo.Enabled or Embedded) then + FrameRectEx(DC, R, BtnItemColors[bisDisabled, ipText], False); + + with EditInfo do if RightBtnWidth > 0 then Dec(R.Right, RightBtnWidth - 2); + + if ItemInfo.Enabled then + begin + if ((ItemInfo.ViewType and VT_TOOLBAR) <> VT_TOOLBAR) and (GetPartColor(ItemInfo, ipFrame) = clNone) then + FrameRectEx(DC, R, ToolbarColor2, False) + else + FrameRectEx(DC, R, clWindow, False); + + InflateRect(R, -1, -1); + FillRectEx(DC, R, clWindow); + if ((ItemInfo.ViewType and VT_TOOLBAR) <> VT_TOOLBAR) and (GetPartColor(ItemInfo, ipFrame) = clNone) then + begin + R := ARect; + InflateRect(R, -1, -1); + FrameRectEx(DC, R, ToolbarColor2, False); + end; + end + else InflateRect(R, -1, -1); + + with EditInfo do if LeftBtnWidth > 0 then Inc(R.Left, LeftBtnWidth - 2); + + if EditInfo.RightBtnWidth > 0 then + begin + R := ARect; + InflateRect(R, -W, -W); + R.Left := R.Right - EditInfo.RightBtnWidth; + PaintEditButton(Canvas, R, ItemInfo, EditInfo.RightBtnInfo); + end; +end; + +procedure TTBXOffice2003Theme.PaintDropDownArrow(Canvas: TCanvas; + const ARect: TRect; const ItemInfo: TTBXItemInfo); +var + X, Y: Integer; +begin + with ARect, Canvas do + begin + X := (Left + Right) div 2; + Y := (Top + Bottom) div 2 - 1; + Pen.Color := GetPartColor(ItemInfo, ipText); + Brush.Color := Pen.Color; + if ItemInfo.IsVertical then Polygon([Point(X, Y + 2), Point(X, Y - 2), Point(X - 2, Y)]) + else Polygon([Point(X - 2, Y), Point(X + 2, Y), Point(X, Y + 2)]); + end; +end; + +procedure TTBXOffice2003Theme.PaintButton(Canvas: TCanvas; const ARect: TRect; const ItemInfo: TTBXItemInfo); +var + DC: HDC; + R: TRect; + tmpColor1, tmpColor2: TColor; +begin + DC := Canvas.Handle; + with ItemInfo do + begin + R := ARect; + if ((ItemOptions and IO_DESIGNING) <> 0) and not Selected then + begin + if ComboPart = cpSplitRight then Dec(R.Left); + FrameRectEx(DC, R, clNavy, False); + end + else + begin + FrameRectEx(DC, R, GetBtnColor(ItemInfo, ipFrame), True); + if (ComboPart = cpSplitLeft) and IsPopupParent then Inc(R.Right); + if ComboPart = cpSplitRight then Dec(R.Left); + + tmpColor1 := GetBtnColor(ItemInfo, ipBody); + tmpColor2 := GetBtnColor(ItemInfo, ipBody, True); + + if (ItemInfo.ViewType and VT_POPUP = VT_POPUP) or (ItemInfo.ViewType and VT_TOOLBAR = VT_TOOLBAR) and (ItemInfo.ViewType and TVT_EMBEDDED = TVT_EMBEDDED) then + FillRectEx(DC, R, tmpColor1) + else if (tmpColor1 <> clNone) and (tmpColor2 <> clNone) then + PaintGradient(DC, R, tmpColor1, tmpColor2); + end; + if ComboPart = cpSplitRight then PaintDropDownArrow(Canvas, R, ItemInfo); + end; +end; + +procedure TTBXOffice2003Theme.PaintFloatingBorder(Canvas: TCanvas; const ARect: TRect; + const WindowInfo: TTBXWindowInfo); + + function GetBtnItemState(BtnState: Integer): TBtnItemState; + begin + if not WindowInfo.Active then Result := bisDisabled + else if (BtnState and CDBS_PRESSED) <> 0 then Result := bisPressed + else if (BtnState and CDBS_HOT) <> 0 then Result := bisHot + else Result := bisNormal; + end; + +var + BtnItemState: TBtnItemState; + SaveIndex, X, Y: Integer; + Sz: TPoint; + R: TRect; + BodyColor, CaptionColor, CaptionText: TColor; + IsDockPanel: Boolean; +begin + with Canvas do + begin + IsDockPanel := (WindowInfo.ViewType and VT_DOCKPANEL) = VT_DOCKPANEL; + BodyColor := Brush.Color; + + if (WRP_BORDER and WindowInfo.RedrawPart) <> 0 then + begin + R := ARect; + + if not IsDockPanel then Brush.Color := WinFrameColors[wfpBorder] + else Brush.Color := WinFrameColors[wfpBorder]; + + SaveIndex := SaveDC(Canvas.Handle); + Sz := WindowInfo.FloatingBorderSize; + with R, Sz do ExcludeClipRect(Canvas.Handle, Left + X, Top + Y, Right - X, Bottom - Y); + FillRect(R); + RestoreDC(Canvas.Handle, SaveIndex); + InflateRect(R, -Sz.X, -Sz.Y); + Pen.Color := BodyColor; + with R do + if not IsDockPanel then + Canvas.Polyline([ + Point(Left, Top - 1), Point(Right - 1, Top - 1), + Point(Right, Top), Point(Right, Bottom - 1), + Point(Right - 1, Bottom), + Point(Left, Bottom), Point(Left - 1, Bottom - 1), + Point(Left - 1, Top), Point(Left, Top - 1) + ]) + else + Canvas.Polyline([ + Point(Left, Top - 1), Point(Right - 1, Top - 1), + Point(Right, Top), Point(Right, Bottom), + Point(Left - 1, Bottom), + Point(Left - 1, Top), Point(Left, Top - 1) + ]); + end; + + if not WindowInfo.ShowCaption then Exit; + + if (WindowInfo.ViewType and VT_TOOLBAR) = VT_TOOLBAR then + begin + CaptionColor := WinFrameColors[wfpCaption]; + CaptionText := WinFrameColors[wfpCaptionText]; + end + else + begin + CaptionColor := WinFrameColors[wfpCaption]; + CaptionText := WinFrameColors[wfpCaptionText]; + end; + + { Caption } + if (WRP_CAPTION and WindowInfo.RedrawPart) <> 0 then + begin + R := Rect(0, 0, WindowInfo.ClientWidth, GetSystemMetrics(SM_CYSMCAPTION) - 1); + with WindowInfo.FloatingBorderSize do OffsetRect(R, X, Y); + DrawLineEx(Canvas.Handle, R.Left, R.Bottom, R.Right, R.Bottom, BodyColor); + + if ((CDBS_VISIBLE and WindowInfo.CloseButtonState) <> 0) and + ((WRP_CLOSEBTN and WindowInfo.RedrawPart) <> 0) then + Dec(R.Right, GetSystemMetrics(SM_CYSMCAPTION) - 1); + + Brush.Color := CaptionColor; + FillRect(R); + InflateRect(R, -2, 0); + Font.Assign(SmCaptionFont); + Font.Color := CaptionText; + DrawText(Canvas.Handle, WindowInfo.Caption, -1, R, + DT_SINGLELINE or DT_VCENTER or DT_END_ELLIPSIS or DT_NOPREFIX); + end; + + { Close button } + if (CDBS_VISIBLE and WindowInfo.CloseButtonState) <> 0 then + begin + R := Rect(0, 0, WindowInfo.ClientWidth, GetSystemMetrics(SM_CYSMCAPTION) - 1); + with WindowInfo.FloatingBorderSize do OffsetRect(R, X, Y); + R.Left := R.Right - (R.Bottom - R.Top); + DrawLineEx(Canvas.Handle, R.Left - 1, R.Bottom, R.Right, R.Bottom, BodyColor); + Brush.Color := CaptionColor; + FillRect(R); + with R do + begin + X := (Left + Right - StockImgList.Width + 1) div 2; + Y := (Top + Bottom - StockImgList.Height) div 2; + end; + BtnItemState := GetBtnItemState(WindowInfo.CloseButtonState); + FrameRectEx(Canvas.Handle, R, BtnItemColors[BtnItemState, ipFrame], True); + if FillRectEx(Canvas.Handle, R, BtnBodyColors[BtnItemState, False]) then + DrawGlyph(Canvas.Handle, X, Y, StockImgList, 0, BtnItemColors[BtnItemState, ipText]) + else + DrawGlyph(Canvas.Handle, X, Y, StockImgList, 0, CaptionText); + end; + end; +end; + +procedure TTBXOffice2003Theme.PaintFrame(Canvas: TCanvas; const ARect: TRect; + const ItemInfo: TTBXItemInfo); +var + DC: HDC; + R: TRect; +begin + DC := Canvas.Handle; + R := ARect; + FrameRectEx(DC, R, GetPartColor(ItemInfo, ipFrame), True); + FillRectEx(DC, R, GetPartColor(ItemInfo, ipBody)); +end; + +function TTBXOffice2003Theme.GetImageOffset(Canvas: TCanvas; + const ItemInfo: TTBXItemInfo; ImageList: TCustomImageList): TPoint; +begin + Result.X := 0; + Result.Y := 0; +end; + +procedure TTBXOffice2003Theme.PaintImage(Canvas: TCanvas; ARect: TRect; + const ItemInfo: TTBXItemInfo; ImageList: TCustomImageList; ImageIndex: Integer); +var + HiContrast: Boolean; +begin + with ItemInfo do + begin + if ImageList is TTBCustomImageList then + begin + TTBCustomImageList(ImageList).DrawState(Canvas, ARect.Left, ARect.Top, + ImageIndex, Enabled, (HoverKind <> hkNone), Selected); + Exit; + end; + + HiContrast := ColorIntensity(GetItemImageBackground(ItemInfo)) < 80; + if not Enabled then + begin + if not HiContrast then + DrawTBXIconShadow(Canvas, ARect, ImageList, ImageIndex, 0) + else + DrawTBXIconFlatShadow(Canvas, ARect, ImageList, ImageIndex, SeparatorColor1); + end + else {$IFDEF HIGHLIGHTTOOLBARICONS}if Selected or Pushed or (HoverKind <> hkNone) or HiContrast or TBXHiContrast or TBXLoColor then{$ENDIF} + DrawTBXIcon(Canvas, ARect, ImageList, ImageIndex, HiContrast) + {$IFDEF HIGHLIGHTTOOLBARICONS} + else + HighlightTBXIcon(Canvas, ARect, ImageList, ImageIndex, clWindow, 178){$ENDIF}; + end; +end; + +procedure TTBXOffice2003Theme.PaintMDIButton(Canvas: TCanvas; ARect: TRect; + const ItemInfo: TTBXItemInfo; ButtonKind: Cardinal); +var + Index: Integer; +begin + PaintButton(Canvas, ARect, ItemInfo); + Dec(ARect.Bottom); + case ButtonKind of + DFCS_CAPTIONMIN: Index := 2; + DFCS_CAPTIONRESTORE: Index := 3; + DFCS_CAPTIONCLOSE: Index := 0; + else + Exit; + end; + DrawGlyph(Canvas.Handle, ARect, StockImgList, Index, GetPartColor(ItemInfo, ipText)); +end; + +procedure TTBXOffice2003Theme.PaintMenuItemFrame(Canvas: TCanvas; + const ARect: TRect; const ItemInfo: TTBXItemInfo); +var + R: TRect; +begin + R := ARect; + if (ItemInfo.ViewType and PVT_TOOLBOX) <> PVT_TOOLBOX then with Canvas do + begin + R.Right := R.Left + ItemInfo.PopupMargin + 2; + PaintIrregularGradient(Handle, R, ToolbarColor1, ToolbarColor2, True); + Inc(R.Left); + R.Right := ARect.Right - 1; + end; + PaintFrame(Canvas, R, ItemInfo); +end; + +procedure TTBXOffice2003Theme.PaintMenuItem(Canvas: TCanvas; const ARect: TRect; var ItemInfo: TTBXItemInfo); +var + DC: HDC; + R: TRect; + X, Y: Integer; + ArrowWidth: Integer; + C, ClrText: TColor; +begin + DC := Canvas.Handle; + with ItemInfo do + begin + ArrowWidth := GetSystemMetrics(SM_CXMENUCHECK); + PaintMenuItemFrame(Canvas, ARect, ItemInfo); + ClrText := GetPartColor(ItemInfo, ipText); + R := ARect; + + if (ItemOptions and IO_COMBO) <> 0 then + begin + X := R.Right - ArrowWidth - 1; + if not ItemInfo.Enabled then C := ClrText + else if HoverKind = hkMouseHover then C := GetPartColor(ItemInfo, ipFrame) + else C := PopupFrameColor; + DrawLineEx(DC, X, R.Top + 1, X, R.Bottom - 1, C); + end; + + if (ItemOptions and IO_SUBMENUITEM) <> 0 then + begin + Y := ARect.Bottom div 2; + X := ARect.Right - ArrowWidth * 2 div 3 - 1; + PolygonEx(DC, [Point(X, Y - 3), Point(X, Y + 3), Point(X + 3, Y)], ClrText, ClrText); + end; + + if Selected and Enabled then + begin + R := ARect; + R.Left := ARect.Left + 1; + R.Right := R.Left + ItemInfo.PopupMargin; + InflateRect(R, -1, -1); + FrameRectEx(DC, R, GetBtnColor(ItemInfo, ipFrame), True); + FillRectEx(DC, R, GetBtnColor(ItemInfo, ipBody)); + end; + end; +end; + +procedure TTBXOffice2003Theme.PaintPopupNCArea(Canvas: TCanvas; R: TRect; const PopupInfo: TTBXPopupInfo); +var + PR: TRect; +begin + with Canvas do + begin + Brush.Color := PopupFrameColor; + FrameRect(R); + InflateRect(R, -1, -1); + Brush.Color := PopupColor; + FillRect(R); + + if not IsRectEmpty(PopupInfo.ParentRect) then + begin + PR := PopupInfo.ParentRect; + if not IsRectEmpty(PR) then with PR do + begin + Pen.Color := PopupColor; + if Bottom = R.Top then + begin + if Left <= R.Left then Left := R.Left - 1; + if Right >= R.Right then Right := R.Right + 1; + MoveTo(Left + 1, Bottom - 1); LineTo(Right - 1, Bottom - 1); + end + else if Top = R.Bottom then + begin + if Left <= R.Left then Left := R.Left - 1; + if Right >= R.Right then Right := R.Right + 1; + MoveTo(Left + 1, Top); LineTo(Right - 1, Top); + end; + if Right = R.Left then + begin + if Top <= R.Top then Top := R.Top - 1; + if Bottom >= R.Bottom then Bottom := R.Bottom + 1; + MoveTo(Right - 1, Top + 1); LineTo(Right - 1, Bottom - 1); + end + else if Left = R.Right then + begin + if Top <= R.Top then Top := R.Top - 1; + if Bottom >= R.Bottom then Bottom := R.Bottom + 1; + MoveTo(Left, Top + 1); LineTo(Left, Bottom - 1); + end; + end; + end; + end; +end; + +procedure TTBXOffice2003Theme.PaintSeparator(Canvas: TCanvas; ARect: TRect; + ItemInfo: TTBXItemInfo; Horizontal, LineSeparator: Boolean); +var + DC: HDC; + IsToolbox: Boolean; + R: TRect; + NewWidth: Integer; +begin + { Note: for blank separators, Enabled = False } + DC := Canvas.Handle; + with ItemInfo, ARect do + begin + if Horizontal then + begin + IsToolbox := (ViewType and PVT_TOOLBOX) = PVT_TOOLBOX; + if ((ItemOptions and IO_TOOLBARSTYLE) = 0) and not IsToolBox then + begin + R := ARect; + R.Right := ItemInfo.PopupMargin + 2; + PaintIrregularGradient(DC, R, ToolbarColor1, ToolbarColor2, True); + Inc(Left, ItemInfo.PopupMargin + 9); + Top := (Top + Bottom) div 2; + if Enabled then DrawLineEx(DC, Left, Top, Right, Top, SeparatorColor1); + end + else + begin + Top := (Top + Bottom) div 2; + Right := Right + 1; + NewWidth := Round(0.6 * (Right - Left)); + Left := (Right - Left - NewWidth) div 2; + Right := Left + NewWidth; + if Enabled then + begin + DrawLineEx(DC, Left, Top, Right, Top, SeparatorColor1); + OffsetRect(ARect, 1, 1); + DrawLineEx(DC, Left, Top, Right, Top, SeparatorColor2); + end; + end; + end + else if Enabled then + begin + Left := (Left + Right) div 2; + Bottom := Bottom + 1; + NewWidth := Round(0.6 * (Bottom - Top)); + Top := (Bottom - Top - NewWidth) div 2; + Bottom := Top + NewWidth; + DrawLineEx(DC, Left, Top, Left, Bottom, SeparatorColor1); + OffsetRect(ARect, 1, 1); + DrawLineEx(DC, Left, Top, Left, Bottom, SeparatorColor2); + end; + end; +end; + +procedure DrawButtonBitmap(DC: HDC; R: TRect; Color: TColor); +const +{$IFNDEF SMALL_CLOSE_BUTTON} + Pattern: array [0..15] of Byte = + ($C3, 0, $66, 0, $3C, 0, $18, 0, $3C, 0, $66, 0, $C3, 0, 0, 0); +{$ELSE} + Pattern: array [0..15] of Byte = + (0, 0, $63, 0, $36, 0, $1C, 0, $1C, 0, $36, 0, $63, 0, 0, 0); +{$ENDIF} +begin + DrawGlyph(DC, R, 8, 7, Pattern[0], Color); +end; + +procedure TTBXOffice2003Theme.PaintToolbarNCArea(Canvas: TCanvas; R: TRect; const ToolbarInfo: TTBXToolbarInfo); +const + DragHandleOffsets: array [Boolean, DHS_DOUBLE..DHS_SINGLE] of Integer = ((2, 0, 1), (5, 0, 5)); + + function GetBtnItemState(BtnState: Integer): TBtnItemState; + begin + if (BtnState and CDBS_PRESSED) <> 0 then Result := bisPressed + else if (BtnState and CDBS_HOT) <> 0 then Result := bisHot + else Result := bisNormal; + end; + + procedure DrawHandleElement(const P: TPoint); + begin + Canvas.Brush.Color := DragHandleColor2; + Canvas.FillRect(Rect(P.X + 1, P.Y + 1, P.X + 3, P.Y + 3)); + Canvas.Brush.Color := DragHandleColor1; + Canvas.FillRect(Rect(P.X, P.Y, P.X + 2, P.Y + 2)); + end; + +var + DC: HDC; + Sz: Integer; + R2: TRect; + I: Integer; + BtnVisible, Horz: Boolean; + BtnItemState: TBtnItemState; + IsMenuBar: Boolean; +begin + DC := Canvas.Handle; + Horz := not ToolbarInfo.IsVertical; + with Canvas do + begin + IsMenuBar := ToolbarInfo.ViewType and TVT_MENUBAR = TVT_MENUBAR; + if (ToolbarInfo.BorderStyle = bsSingle) and not IsMenuBar then + begin + I := ColorIntensity(clBtnFace); + if not (TBXLoColor or not (I in [50..254])) then + begin + InflateRect(R, -1, -1); + Pen.Style := psSolid; + with R do + begin + if Horz then + begin + {left} + PaintIrregularGradient(Handle, Rect(Left, Top + 1, Left + 1, Bottom - 1), ToolbarColor1, ToolbarColor2, False); + + {right} + PaintIrregularGradient(Handle, Rect(Right - 1, Top + 1, Right, Bottom - 1), ToolbarColor1, ToolbarColor2, False); + PaintIrregularGradient(Handle, Rect(Right, Top + 1, Right + 1, Bottom - 1), ToolbarColor2, ToolbarFrameColor1, False); + + {top} + Pen.Color := ToolbarColor1; + Polyline([Point(Left + 2, Top), Point(Right - 1, Top)]); + + {bottom} + Pen.Color := ToolbarColor2; + Polyline([Point(Left + 1, Bottom - 1), Point(Right - 1, Bottom - 1)]); + Pen.Color := ToolbarFrameColor1; + Polyline([Point(Left + 2, Bottom), Point(Right - 1, Bottom)]); + + {pixels} + SetPixelV(Handle, Left + 1, Top, ToolbarFrameColor2); + SetPixelV(Handle, Left, Top + 1, ToolbarFrameColor2); + SetPixelV(Handle, Right - 1, Top, ToolbarFrameColor2); + SetPixelV(Handle, Right, Top + 1, ToolbarFrameColor2); + SetPixelV(Handle, Right - 1, Bottom - 1, ToolbarFrameColor1); + end + else + begin + {left} + Pen.Color := ToolbarColor1; + Polyline([Point(Left, Top + 2), Point(Left, Bottom - 1)]); + + {right} + Pen.Color := ToolbarColor2; + Polyline([Point(Right - 1, Top + 1), Point(Right - 1, Bottom - 1)]); + Pen.Color := ToolbarFrameColor1; + Polyline([Point(Right, Top + 2), Point(Right, Bottom - 1)]); + + {top} + PaintIrregularGradient(Handle, Rect(Left + 1, Top, Right - 1, Top + 1), ToolbarColor1, ToolbarColor2, True); + + {bottom} + PaintIrregularGradient(Handle, Rect(Left + 2, Bottom - 1, Right - 1, Bottom), ToolbarColor1, ToolbarColor2, True); + PaintIrregularGradient(Handle, Rect(Left + 2, Bottom, Right - 1, Bottom + 1), ToolbarColor2, ToolbarFrameColor1, True); + + {pixels} + SetPixelV(Handle, Left + 1, Top, ToolbarFrameColor2); + SetPixelV(Handle, Left, Top + 1, ToolbarFrameColor2); + SetPixelV(Handle, Left + 1, Bottom - 1, ToolbarColor2); + SetPixelV(Handle, Left, Bottom - 2, ToolbarFrameColor2); + SetPixelV(Handle, Right - 1, Bottom - 1, ToolbarFrameColor1); + end; + end; + Brush.Style := bsSolid; + Inc(R.Left); + Inc(R.Top); + end + else + begin + Brush.Bitmap := AllocPatternBitmap(ToolbarColor1, BtnItemColors[bisDisabled, ipText]); + with R do + begin + FillRect(Rect(Left + 1, Top, Right - 1, Top + 1)); + FillRect(Rect(Left + 1, Bottom - 1, Right - 1, Bottom)); + FillRect(Rect(Left, Top + 1, Left + 1, Bottom - 1)); + FillRect(Rect(Right - 1, Top + 1, Right, Bottom - 1)); + end; + InflateRect(R, -1, -1); + Brush.Color := ToolbarColor1; + FillRect(R); + end; + end + else + InflateRect(R, -1, -1); + InflateRect(R, -1, -1); + + if not ToolbarInfo.AllowDrag then Exit; + + BtnVisible := (ToolbarInfo.CloseButtonState and CDBS_VISIBLE) <> 0; + Sz := GetTBXDragHandleSize(ToolbarInfo); + if Horz then R.Right := R.Left + Sz + else R.Bottom := R.Top + Sz; + + { Drag Handle } + if ToolbarInfo.DragHandleStyle <> DHS_NONE then + begin + R2 := R; + if Horz then + begin + Inc(R2.Left, DragHandleOffsets[BtnVisible, ToolbarInfo.DragHandleStyle]); + if BtnVisible then Inc(R2.Top, Sz - 2); + R2.Right := R2.Left + 3; + end + else + begin + Inc(R2.Top, DragHandleOffsets[BtnVisible, ToolbarInfo.DragHandleStyle]); + if BtnVisible then Dec(R2.Right, Sz - 2); + R2.Bottom := R2.Top + 3; + end; + + if not IsMenuBar then + PaintIrregularGradient(Canvas.Handle, Rect(R.Left - 1, R.Top - 1, R.Right, R.Bottom), ToolbarColor1, ToolbarColor2, not Horz) + else + begin + Inc(R2.Left); + Inc(R2.Top); + end; + + if Horz then + begin + I := R2.Top + Sz div 2; + while I < R2.Bottom - Sz div 2 - 2 do + begin + DrawHandleElement(Point(R2.Left, I)); + Inc(I, 4); + end; + end + else + begin + I := R2.Left + Sz div 2; + while I < R2.Right - Sz div 2 - 2 do + begin + DrawHandleElement(Point(I, R2.Top)); + Inc(I, 4); + end; + end; + end; + + { Close button } + if BtnVisible then + begin + R2 := R; + if Horz then + begin + Dec(R2.Right); + R2.Bottom := R2.Top + R2.Right - R2.Left; + end + else + begin + Dec(R2.Bottom); + R2.Left := R2.Right - R2.Bottom + R2.Top; + end; + + BtnItemState := GetBtnItemState(ToolbarInfo.CloseButtonState); + FrameRectEx(DC, R2, BtnItemColors[BtnItemState, ipFrame], True); + FillRectEx(DC, R2, BtnBodyColors[BtnItemState, False]); + DrawButtonBitmap(DC, R2, BtnItemColors[BtnItemState, ipText]); + end; + end; +end; + +procedure TTBXOffice2003Theme.PaintDock(Canvas: TCanvas; const ClientRect, + DockRect: TRect; DockPosition: Integer); +begin + FillRectEx(Canvas.Handle, DockRect, DockColor); +end; + +procedure TTBXOffice2003Theme.PaintDockPanelNCArea(Canvas: TCanvas; R: TRect; const DockPanelInfo: TTBXDockPanelInfo); + + function GetBtnItemState(BtnState: Integer): TBtnItemState; + begin + if (BtnState and CDBS_PRESSED) <> 0 then Result := bisPressed + else if (BtnState and CDBS_HOT) <> 0 then Result := bisHot + else Result := bisNormal; + end; + +var + DC: HDC; + C: TColor; + I, Sz, Flags: Integer; + R2: TRect; + BtnItemState: TBtnItemState; + B: HBRUSH; + OldBkMode: Cardinal; + OldFont: HFONT; + OldTextColor: TColorRef; +begin + DC := Canvas.Handle; + with DockPanelInfo do + begin + I := ColorIntensity(ColorToRGB(clBtnFace)); + R2 := R; + if not TBXLoColor and (I in [64..250]) then + begin + FrameRectEx(DC, R, ToolbarColor2, True); + FrameRectEx(DC, R, EffectiveColor, False); + with R do + begin + C := ToolbarColor2; + SetPixelV(DC, Left, Top, C); + if IsVertical then SetPixelV(DC, Right - 1, Top, C) + else SetPixelV(DC, Left, Bottom - 1, C); + end; + end + else + begin + FrameRectEx(DC, R, EffectiveColor, True); + + if I < 64 then B := CreateDitheredBrush(EffectiveColor, clWhite) + else B := CreateDitheredBrush(EffectiveColor, clBtnShadow); + Windows.FrameRect(DC, R, B); + DeleteObject(B); + + with R do + begin + SetPixelV(DC, Left, Top, EffectiveColor); + if IsVertical then SetPixelV(DC, Right - 1, Top, EffectiveColor) + else SetPixelV(DC, Left, Bottom - 1, EffectiveColor); + end; + InflateRect(R, -1, -1); + FrameRectEx(DC, R, EffectiveColor, False); + end; + R := R2; + InflateRect(R, -BorderSize.X, -BorderSize.Y); + Sz := GetSystemMetrics(SM_CYSMCAPTION); + if IsVertical then + begin + R.Bottom := R.Top + Sz - 1; + DrawLineEx(DC, R.Left, R.Bottom, R.Right, R.Bottom, EffectiveColor); + end + else + begin + R.Right := R.Left + Sz - 1; + DrawLineEx(DC, R.Right, R.Top, R.Right, R.Bottom, EffectiveColor); + end; + {$IFDEF DOCKPANELGRADIENTCAPTION} + PaintGradient(DC, R, ToolbarColor1, ToolbarColor2); + {$ELSE} + FillRectEx(DC, R, DockColor); + {$ENDIF} + + if (CDBS_VISIBLE and CloseButtonState) <> 0 then + begin + R2 := R; + if IsVertical then + begin + R2.Left := R2.Right - Sz + 1; + R.Right := R2.Left; + end + else + begin + R2.Top := R2.Bottom - Sz + 1; + R.Bottom := R2.Top; + end; + + BtnItemState := GetBtnItemState(CloseButtonState); + FrameRectEx(DC, R2, BtnItemColors[BtnItemState, ipFrame], True); + FillRectEx(DC, R2, BtnBodyColors[BtnItemState, False]); + DrawButtonBitmap(DC, R2, BtnItemColors[BtnItemState, ipText]); + end; + + if IsVertical then InflateRect(R, -4, 0) + else InflateRect(R, 0, -4); + + OldFont := SelectObject(DC, SmCaptionFont.Handle); + OldBkMode := SetBkMode(DC, TRANSPARENT); + OldTextColor := SetTextColor(DC, ColorToRGB(SmCaptionFont.Color)); + Flags := DT_SINGLELINE or DT_VCENTER or DT_END_ELLIPSIS or DT_NOPREFIX; + if IsVertical then DrawText(DC, Caption, -1, R, Flags) + else DrawRotatedText(DC, string(Caption), R, Flags); + SetTextColor(DC, OldTextColor); + SetBkMode(DC, OldBkMode); + SelectObject(DC, OldFont); + end; +end; + +procedure TTBXOffice2003Theme.SetupColorCache; +const + Office2003Colors: array[osBlue..osGreen, 0..27] of TColor = ( + ($F5BE9E, $FEECDD, $E2A981, $9C613B, $FAD5BD, $CB8C6A, $FFF9F1, $764127, + $FFFFFF, $F0C7A9, $B99D7F, $DEDEDE, $F6F6F6, $962D00, $000000, $8D8D8D, + $800000, $C9662A, $8CD5FF, $55ADFF, $4E91FE, $8ED3FF, $CCF4FF, $91D0FF, + $FFEFE3, $E7B593, $C2EEFF, $AE9990), + ($E5D7D7, $FAF4F3, $B59799, $947C7C, $EFE5E5, $8F6D6E, $FFFFFF, $755454, + $FFFFFF, $D3C0C0, $B2ACA5, $DEDEDE, $FFFAFD, $947C7C, $000000, $8D8D8D, + $6F4B4B, $99797A, $8CD5FF, $55ADFF, $4E91FE, $8ED3FF, $CCF4FF, $91D0FF, + $F1E9E8, $CDB9BA, $C2EEFF, $B39A9B), + ($A7D9D9, $DEF7F4, $91C6B7, $588060, $C0E7E5, $588060, $DEF7F4, $335E51, + $FFFFFF, $9FD4C5, $7FB9A4, $DEDEDE, $EEF4F4, $5E8D75, $000000, $8D8D8D, + $385D3F, $5E8674, $8CD5FF, $55ADFF, $4E91FE, $8ED3FF, $CCF4FF, $91D0FF, + $D5F0EC, $9FCEC2, $C2EEFF, $7BA097) + ); + Office2003IrregularGradientValues: array[TOffice2003Scheme] of Integer = (8, 8, 25, 15); + +var + DC: HDC; + MenuItemFrame, EnabledText, DisabledText: TColor; + Scheme: TOffice2003Scheme; + + procedure Undither(var C: TColor); + begin + if C <> clNone then C := GetNearestColor(DC, ColorToRGB(C)); + end; + +begin + DC := StockCompatibleBitmap.Canvas.Handle; + + if TBXLoColor then + begin + DockColor := clBtnFace; + + ToolbarColor1 := clBtnFace; + ToolbarColor2 := clBtnFace; + ToolbarFrameColor1 := clBtnShadow; + ToolbarFrameColor2 := clBtnShadow; + SeparatorColor1 := clBtnShadow; + SeparatorColor2 := clBtnHighlight; + DragHandleColor1 := clBtnText; + DragHandleColor2 := clBtnHighlight; + + EmbeddedColor := clBtnFace; + EmbeddedFrameColor := clBtnShadow; + EmbeddedDisabledColor := clBtnFace; + + PopupColor := clWindow; + PopupFrameColor := clBtnText; + + DockPanelColor := clWindow; + + DisabledText := clBtnShadow; + MenuItemFrame := clHighlight; + + WinFrameColors[wfpBorder] := clBtnShadow; + WinFrameColors[wfpCaption] := clBtnShadow; + WinFrameColors[wfpCaptionText] := clBtnHighlight; + + BtnItemColors[bisNormal, ipText] := clBtnText; + BtnItemColors[bisNormal, ipFrame] := clNone; + BtnItemColors[bisDisabled, ipText] := DisabledText; + BtnItemColors[bisDisabled, ipFrame] := clNone; + BtnItemColors[bisSelected, ipText] := clWindowText; + BtnItemColors[bisSelected, ipFrame] := MenuItemFrame; + BtnItemColors[bisPressed, ipText] := clHighlightText; + BtnItemColors[bisPressed, ipFrame] := MenuItemFrame; + BtnItemColors[bisHot, ipText] := clWindowText; + BtnItemColors[bisHot, ipFrame] := MenuItemFrame; + BtnItemColors[bisDisabledHot, ipText] := DisabledText; + BtnItemColors[bisDisabledHot, ipFrame] := MenuItemFrame; + BtnItemColors[bisSelectedHot, ipText] := clHighlightText; + BtnItemColors[bisSelectedHot, ipFrame] := MenuItemFrame; + BtnItemColors[bisPopupParent, ipText] := clBtnText; + BtnItemColors[bisPopupParent, ipFrame] := PopupFrameColor; + + BtnBodyColors[bisNormal, False] := clNone; + BtnBodyColors[bisNormal, True] := clNone; + BtnBodyColors[bisDisabled, False] := clNone; + BtnBodyColors[bisDisabled, True] := clNone; + BtnBodyColors[bisSelected, False] := clWindow; + BtnBodyColors[bisSelected, True] := clWindow; + BtnBodyColors[bisPressed, False] := clHighlight; + BtnBodyColors[bisPressed, True] := clHighlight; + BtnBodyColors[bisHot, False] := clWindow; + BtnBodyColors[bisHot, True] := clWindow; + BtnBodyColors[bisDisabledHot, False] := clWindow; + BtnBodyColors[bisDisabledHot, True] := clWindow; + BtnBodyColors[bisSelectedHot, False] := clHighlight; + BtnBodyColors[bisSelectedHot, True] := clHighlight; + BtnBodyColors[bisPopupParent, False] := clBtnFace; + BtnBodyColors[bisPopupParent, True] := clBtnFace; + + MenuItemColors[misNormal, ipBody] := clNone; + MenuItemColors[misNormal, ipText] := clWindowText; + MenuItemColors[misNormal, ipFrame] := clNone; + MenuItemColors[misDisabled, ipBody] := clNone; + MenuItemColors[misDisabled, ipText] := clGrayText; + MenuItemColors[misDisabled, ipFrame] := clNone; + MenuItemColors[misHot, ipBody] := clWindow; + MenuItemColors[misHot, ipText] := clWindowText; + MenuItemColors[misHot, ipFrame] := MenuItemFrame; + MenuItemColors[misDisabledHot, ipBody] := PopupColor; + MenuItemColors[misDisabledHot, ipText] := clGrayText; + MenuItemColors[misDisabledHot, ipFrame] := MenuItemFrame; + + StatusPanelFrameColor := clBtnShadow; + FMDIAreaColor := clBtnShadow; + end + else + begin + + Scheme := GetOffice2003Scheme; + if Scheme <> osUnknown then + begin + DockColor := Office2003Colors[Scheme, 0]; + + ToolbarColor1 := Office2003Colors[Scheme, 1]; + ToolbarColor2 := Office2003Colors[Scheme, 2]; + ToolbarFrameColor1 := Office2003Colors[Scheme, 3]; + ToolbarFrameColor2 := Office2003Colors[Scheme, 4]; + SeparatorColor1 := Office2003Colors[Scheme, 5]; + SeparatorColor2 := Office2003Colors[Scheme, 6]; + DragHandleColor1 := Office2003Colors[Scheme, 7]; + DragHandleColor2 := Office2003Colors[Scheme, 8]; + + EmbeddedColor := Office2003Colors[Scheme, 9]; + EmbeddedFrameColor := Office2003Colors[Scheme, 10]; + EmbeddedDisabledColor := Office2003Colors[Scheme, 11]; + + PopupColor := Office2003Colors[Scheme, 12]; + PopupFrameColor := Office2003Colors[Scheme, 13]; + + DockPanelColor := ToolbarColor1; + + EnabledText := Office2003Colors[Scheme, 14]; + DisabledText := Office2003Colors[Scheme, 15]; + MenuItemFrame := Office2003Colors[Scheme, 16]; + + WinFrameColors[wfpBorder] := Office2003Colors[Scheme, 17]; + WinFrameColors[wfpCaption] := WinFrameColors[wfpBorder]; + WinFrameColors[wfpCaptionText] := clWhite; + + BtnItemColors[bisNormal, ipText] := EnabledText; + BtnItemColors[bisNormal, ipFrame] := clNone; + BtnItemColors[bisDisabled, ipText] := DisabledText; + BtnItemColors[bisDisabled, ipFrame] := clNone; + BtnItemColors[bisSelected, ipText] := EnabledText; + BtnItemColors[bisSelected, ipFrame] := MenuItemFrame; + BtnItemColors[bisPressed, ipText] := EnabledText; + BtnItemColors[bisPressed, ipFrame] := MenuItemFrame; + BtnItemColors[bisHot, ipText] := EnabledText; + BtnItemColors[bisHot, ipFrame] := MenuItemFrame; + BtnItemColors[bisDisabledHot, ipText] := DisabledText; + BtnItemColors[bisDisabledHot, ipFrame] := MenuItemFrame; + BtnItemColors[bisSelectedHot, ipText] := EnabledText; + BtnItemColors[bisSelectedHot, ipFrame] := MenuItemFrame; + BtnItemColors[bisPopupParent, ipText] := EnabledText; + BtnItemColors[bisPopupParent, ipFrame] := PopupFrameColor; + + BtnBodyColors[bisNormal, False] := clNone; + BtnBodyColors[bisNormal, True] := clNone; + BtnBodyColors[bisDisabled, False] := clNone; + BtnBodyColors[bisDisabled, True] := clNone; + BtnBodyColors[bisSelected, False] := Office2003Colors[Scheme, 18]; + BtnBodyColors[bisSelected, True] := Office2003Colors[Scheme, 19]; + BtnBodyColors[bisPressed, False] := Office2003Colors[Scheme, 20]; + BtnBodyColors[bisPressed, True] := Office2003Colors[Scheme, 21]; + BtnBodyColors[bisHot, False] := Office2003Colors[Scheme, 22]; + BtnBodyColors[bisHot, True] := Office2003Colors[Scheme, 23]; + BtnBodyColors[bisDisabledHot, False] := BtnBodyColors[bisHot, False]; + BtnBodyColors[bisDisabledHot, True] := BtnBodyColors[bisHot, True]; + BtnBodyColors[bisSelectedHot, False] := BtnBodyColors[bisPressed, False]; + BtnBodyColors[bisSelectedHot, True] := BtnBodyColors[bisPressed, True]; + BtnBodyColors[bisPopupParent, False] := Office2003Colors[Scheme, 24]; + BtnBodyColors[bisPopupParent, True] := Office2003Colors[Scheme, 25]; + + MenuItemColors[misNormal, ipBody] := clNone; + MenuItemColors[misNormal, ipText] := EnabledText; + MenuItemColors[misNormal, ipFrame] := clNone; + MenuItemColors[misDisabled, ipBody] := clNone; + MenuItemColors[misDisabled, ipText] := DisabledText; + MenuItemColors[misDisabled, ipFrame] := clNone; + MenuItemColors[misHot, ipBody] := Office2003Colors[Scheme, 26]; + MenuItemColors[misHot, ipText] := MenuItemColors[misNormal, ipText]; + MenuItemColors[misHot, ipFrame] := MenuItemFrame; + MenuItemColors[misDisabledHot, ipBody] := PopupColor; + MenuItemColors[misDisabledHot, ipText] := DisabledText; + MenuItemColors[misDisabledHot, ipFrame] := MenuItemColors[misHot, ipFrame]; + + StatusPanelFrameColor := Blend(ToolbarColor2, clBlack, 90); + FMDIAreaColor := Office2003Colors[Scheme, 27]; + end + else + begin + DockColor := clBtnFace; + + ToolbarColor1 := Blend(clBtnFace, clWindow, 23); + ToolbarColor2 := Blend(clBtnFace, clWindow, 96); + ToolbarFrameColor1 := Blend(clBtnFace, clWindow, 85); + ToolbarFrameColor2 := Blend(clBtnFace, clWindow, 62); + SeparatorColor1 := Blend(clBtnShadow, clWindow, 70); + SeparatorColor2 := clWhite; + DragHandleColor1 := Blend(clBtnShadow, clWindow, 75); + DragHandleColor2 := clWindow; + + EmbeddedColor := clBtnFace; + EmbeddedFrameColor := clBtnShadow; + EmbeddedDisabledColor := clBtnFace; + + PopupColor := Blend(clBtnFace, clWindow, 15); + PopupFrameColor := Blend(clBtnText, clBtnShadow, 20); + + DockPanelColor := ToolbarColor1; + + EnabledText := clBtnText; + DisabledText := clGrayText; + MenuItemFrame := clHighlight; + + WinFrameColors[wfpBorder] := Blend(clBtnText, clBtnShadow, 15); + WinFrameColors[wfpCaption] := clBtnShadow; + WinFrameColors[wfpCaptionText] := clBtnHighlight; + + BtnBodyColors[bisNormal, False] := clNone; + BtnBodyColors[bisNormal, True] := clNone; + BtnBodyColors[bisDisabled, False] := clNone; + BtnBodyColors[bisDisabled, True] := clNone; + BtnBodyColors[bisSelected, False] := Blend(clHighlight, Blend(clBtnFace, clWindow, 50), 10); + + BtnItemColors[bisNormal, ipText] := EnabledText; + BtnItemColors[bisNormal, ipFrame] := clNone; + BtnItemColors[bisDisabled, ipText] := DisabledText; + BtnItemColors[bisDisabled, ipFrame] := clNone; + BtnItemColors[bisSelected, ipText] := EnabledText; + BtnItemColors[bisSelected, ipFrame] := MenuItemFrame; + BtnItemColors[bisPressed, ipText] := EnabledText; + BtnItemColors[bisPressed, ipFrame] := MenuItemFrame; + BtnItemColors[bisHot, ipText] := EnabledText; + BtnItemColors[bisHot, ipFrame] := MenuItemFrame; + BtnItemColors[bisDisabledHot, ipText] := DisabledText; + BtnItemColors[bisDisabledHot, ipFrame] := MenuItemFrame; + BtnItemColors[bisSelectedHot, ipText] := EnabledText; + BtnItemColors[bisSelectedHot, ipFrame] := MenuItemFrame; + BtnItemColors[bisPopupParent, ipText] := EnabledText; + BtnItemColors[bisPopupParent, ipFrame] := PopupFrameColor; + + BtnBodyColors[bisSelected, True] := BtnBodyColors[bisSelected, False]; + BtnBodyColors[bisPressed, False] := Blend(clHighlight, clWindow, 50); + BtnBodyColors[bisPressed, True] := BtnBodyColors[bisPressed, False]; + BtnBodyColors[bisHot, False] := Blend(clHighlight, clWindow, 30); + BtnBodyColors[bisHot, True] := BtnBodyColors[bisHot, False]; + BtnBodyColors[bisDisabledHot, False] := BtnBodyColors[bisHot, False]; + BtnBodyColors[bisDisabledHot, True] := BtnBodyColors[bisHot, True]; + BtnBodyColors[bisSelectedHot, False] := BtnBodyColors[bisPressed, False]; + BtnBodyColors[bisSelectedHot, True] := BtnBodyColors[bisPressed, True]; + BtnBodyColors[bisPopupParent, False] := Blend(clBtnFace, clWindow, 16); + BtnBodyColors[bisPopupParent, True] := Blend(clBtnFace, clWindow, 42); + + MenuItemColors[misNormal, ipBody] := clNone; + MenuItemColors[misNormal, ipText] := EnabledText; + MenuItemColors[misNormal, ipFrame] := clNone; + MenuItemColors[misDisabled, ipBody] := clNone; + MenuItemColors[misDisabled, ipText] := DisabledText; + MenuItemColors[misDisabled, ipFrame] := clNone; + MenuItemColors[misHot, ipBody] := BtnBodyColors[bisHot, False]; + MenuItemColors[misHot, ipText] := MenuItemColors[misNormal, ipText]; + MenuItemColors[misHot, ipFrame] := MenuItemFrame; + MenuItemColors[misDisabledHot, ipBody] := PopupColor; + MenuItemColors[misDisabledHot, ipText] := DisabledText; + MenuItemColors[misDisabledHot, ipFrame] := MenuItemColors[misHot, ipFrame]; + + StatusPanelFrameColor := Blend(ToolbarColor2, clBlack, 90); + FMDIAreaColor := clBtnShadow; + end; + + IrregularGradientValue := Office2003IrregularGradientValues[Scheme]; + + Undither(DockColor); + + Undither(ToolbarColor1); + Undither(ToolbarColor2); + Undither(ToolbarFrameColor1); + Undither(ToolbarFrameColor2); + Undither(SeparatorColor1); + Undither(SeparatorColor2); + Undither(DragHandleColor1); + Undither(DragHandleColor2); + + Undither(EmbeddedColor); + Undither(EmbeddedFrameColor); + Undither(EmbeddedDisabledColor); + + Undither(PopupColor); + Undither(PopupFrameColor); + + Undither(DockPanelColor); + + Undither(WinFrameColors[wfpBorder]); + Undither(WinFrameColors[wfpCaption]); + Undither(WinFrameColors[wfpCaptionText]); + + Undither(BtnItemColors[bisNormal, ipText]); + Undither(BtnItemColors[bisNormal, ipFrame]); + Undither(BtnItemColors[bisDisabled, ipText]); + Undither(BtnItemColors[bisDisabled, ipFrame]); + Undither(BtnItemColors[bisSelected, ipText]); + Undither(BtnItemColors[bisSelected, ipFrame]); + Undither(BtnItemColors[bisPressed, ipText]); + Undither(BtnItemColors[bisPressed, ipFrame]); + Undither(BtnItemColors[bisHot, ipText]); + Undither(BtnItemColors[bisHot, ipFrame]); + Undither(BtnItemColors[bisDisabledHot, ipText]); + Undither(BtnItemColors[bisDisabledHot, ipFrame]); + Undither(BtnItemColors[bisSelectedHot, ipText]); + Undither(BtnItemColors[bisSelectedHot, ipFrame]); + Undither(BtnItemColors[bisPopupParent, ipText]); + Undither(BtnItemColors[bisPopupParent, ipFrame]); + + Undither(BtnBodyColors[bisNormal, False]); + Undither(BtnBodyColors[bisNormal, True]); + Undither(BtnBodyColors[bisDisabled, False]); + Undither(BtnBodyColors[bisDisabled, True]); + Undither(BtnBodyColors[bisSelected, False]); + Undither(BtnBodyColors[bisSelected, True]); + Undither(BtnBodyColors[bisPressed, False]); + Undither(BtnBodyColors[bisPressed, True]); + Undither(BtnBodyColors[bisHot, False]); + Undither(BtnBodyColors[bisHot, True]); + Undither(BtnBodyColors[bisDisabledHot, False]); + Undither(BtnBodyColors[bisDisabledHot, True]); + Undither(BtnBodyColors[bisSelectedHot, False]); + Undither(BtnBodyColors[bisSelectedHot, True]); + Undither(BtnBodyColors[bisPopupParent, False]); + Undither(BtnBodyColors[bisPopupParent, True]); + + Undither(MenuItemColors[misNormal, ipBody]); + Undither(MenuItemColors[misNormal, ipText]); + Undither(MenuItemColors[misNormal, ipFrame]); + Undither(MenuItemColors[misDisabled, ipBody]); + Undither(MenuItemColors[misDisabled, ipText]); + Undither(MenuItemColors[misDisabled, ipFrame]); + Undither(MenuItemColors[misHot, ipBody]); + Undither(MenuItemColors[misHot, ipText]); + Undither(MenuItemColors[misHot, ipFrame]); + Undither(MenuItemColors[misDisabledHot, ipBody]); + Undither(MenuItemColors[misDisabledHot, ipText]); + Undither(MenuItemColors[misDisabledHot, ipFrame]); + + Undither(StatusPanelFrameColor); + Undither(FMDIAreaColor); + end; + + if Assigned(FOnSetupColorCache) then FOnSetupColorCache(Self); +end; + +function TTBXOffice2003Theme.GetPopupShadowType: Integer; +begin + Result := PST_OFFICEXP; +end; + +constructor TTBXOffice2003Theme.Create(const AName: string); +begin + inherited; + if CounterLock = 0 then InitializeStock; + Inc(CounterLock); + AddTBXSysChangeNotification(Self); + SetupColorCache; +end; + +destructor TTBXOffice2003Theme.Destroy; +begin + RemoveTBXSysChangeNotification(Self); + Dec(CounterLock); + if CounterLock = 0 then FinalizeStock; + inherited; +end; + +procedure TTBXOffice2003Theme.GetViewMargins(ViewType: Integer; out Margins: TTBXMargins); +begin + Margins.LeftWidth := 0; + Margins.TopHeight := 0; + Margins.RightWidth := 0; + Margins.BottomHeight := 0; +end; + +procedure TTBXOffice2003Theme.PaintPageScrollButton(Canvas: TCanvas; + const ARect: TRect; ButtonType: Integer; Hot: Boolean); +var + DC: HDC; + R: TRect; + X, Y, Sz: Integer; + C: TColor; +begin + DC := Canvas.Handle; + R := ARect; + if Hot then C := BtnItemColors[bisHot, ipFrame] + else C := EmbeddedFrameColor; + FrameRectEx(DC, R, C, False); + InflateRect(R, -1, -1); + if Hot then C := BtnBodyColors[bisHot, False] + else C := EmbeddedColor; + FillRectEx(DC, R, C); + X := (R.Left + R.Right) div 2; + Y := (R.Top + R.Bottom) div 2; + Sz := Min(X - R.Left, Y - R.Top) * 3 div 4; + + if Hot then C := BtnItemColors[bisHot, ipText] + else C := BtnItemColors[bisNormal, ipText]; + + case ButtonType of + PSBT_UP: + begin + Inc(Y, Sz div 2); + PolygonEx(DC, [Point(X + Sz, Y), Point(X, Y - Sz), Point(X - Sz, Y)], C, C); + end; + PSBT_DOWN: + begin + Y := (R.Top + R.Bottom - 1) div 2; + Dec(Y, Sz div 2); + PolygonEx(DC, [Point(X + Sz, Y), Point(X, Y + Sz), Point(X - Sz, Y)], C, C); + end; + PSBT_LEFT: + begin + Inc(X, Sz div 2); + PolygonEx(DC, [Point(X, Y + Sz), Point(X - Sz, Y), Point(X, Y - Sz)], C, C); + end; + PSBT_RIGHT: + begin + X := (R.Left + R.Right - 1) div 2; + Dec(X, Sz div 2); + PolygonEx(DC, [Point(X, Y + Sz), Point(X + Sz, Y), Point(X, Y - Sz)], C, C); + end; + end; +end; + +procedure TTBXOffice2003Theme.PaintFrameControl(Canvas: TCanvas; R: TRect; Kind, State: Integer; Params: Pointer); +var + DC: HDC; + X, Y: Integer; + Pen, OldPen: HPen; + Brush, OldBrush: HBRUSH; + C: TColor; + + function GetPenColor: TColor; + begin + if Boolean(State and PFS_DISABLED) then Result := clBtnShadow + else if Boolean(State and PFS_PUSHED) then Result := BtnItemColors[bisPressed, ipFrame] + else if Boolean(State and PFS_HOT) then Result := BtnItemColors[bisHot, ipFrame] + else Result := EmbeddedFrameColor; + end; + + function GetBrush: HBRUSH; + begin + if Boolean(State and PFS_DISABLED) then Result := CreateDitheredBrush(clWindow, clBtnFace) + else if Boolean(State and PFS_PUSHED) then Result := CreateBrushEx(BtnBodyColors[bisPressed, False]) + else if Boolean(State and PFS_HOT) then Result := CreateBrushEx(BtnBodyColors[bisHot, False]) + else if Boolean(State and PFS_MIXED) then Result := CreateDitheredBrush(clWindow, clBtnFace) + else Result := CreateBrushEx(clNone); + end; + + function GetTextColor: TColor; + begin + if Boolean(State and PFS_DISABLED) then Result := BtnItemColors[bisDisabled, ipText] + else if Boolean(State and PFS_PUSHED) then Result := BtnItemColors[bisPressed, ipText] + else if Boolean(State and PFS_MIXED) then Result := clBtnShadow + else if Boolean(State and PFS_HOT) then Result := BtnItemColors[bisHot, ipText] + else Result := BtnItemColors[bisNormal, ipText]; + end; + +begin + DC := Canvas.Handle; + case Kind of + PFC_CHECKBOX: + begin + InflateRect(R, -1, -1); + FrameRectEx(DC, R, GetPenColor, True); + Brush := GetBrush; + Windows.FillRect(DC, R, Brush); + DeleteObject(Brush); + InflateRect(R, 1, 1); + + if Boolean(State and (PFS_CHECKED or PFS_MIXED)) then + begin + X := (R.Left + R.Right) div 2 - 1; + Y := (R.Top + R.Bottom) div 2 + 1; + C := GetTextColor; + PolygonEx(DC, [Point(X - 2, Y), Point(X, Y + 2), Point(X + 4, Y - 2), + Point(X + 4, Y - 4), Point(X, Y), Point(X - 2, Y - 2), Point(X - 2, Y)], C, C); + end; + end; + PFC_RADIOBUTTON: + begin + InflateRect(R, -1, -1); + + with R do + begin + Brush := GetBrush; + OldBrush := SelectObject(DC, Brush); + Pen := CreatePenEx(GetPenColor); + OldPen := SelectObject(DC, Pen); + Windows.Ellipse(DC, Left, Top, Right, Bottom); + SelectObject(DC, OldPen); + DeleteObject(Pen); + SelectObject(DC, OldBrush); + DeleteObject(Brush); + end; + + if Boolean(State and PFS_CHECKED) then + begin + InflateRect(R, -3, -3); + C := GetTextColor; + Brush := CreateBrushEx(C); + OldBrush := SelectObject(DC, Brush); + Pen := CreatePenEx(C); + OldPen := SelectObject(DC, Pen); + with R do Windows.Ellipse(DC, Left, Top, Right, Bottom); + SelectObject(DC, OldPen); + DeleteObject(Pen); + SelectObject(DC, OldBrush); + DeleteObject(Brush); + end; + end; + end; +end; + +procedure TTBXOffice2003Theme.PaintStatusBar(Canvas: TCanvas; R: TRect; Part: Integer); + + procedure DrawHandleElement(const P: TPoint); + begin + Canvas.Brush.Color := DragHandleColor2; + Canvas.FillRect(Rect(P.X - 2, P.Y - 2, P.X, P.Y)); + Canvas.Brush.Color := DragHandleColor1; + Canvas.FillRect(Rect(P.X - 3, P.Y - 3, P.X - 1, P.Y - 1)); + end; + +begin + case Part of + SBP_BODY: + PaintIrregularGradient(Canvas.Handle, R, ToolbarColor1, ToolbarColor2, False); + SBP_PANE, SBP_LASTPANE: + begin + if Part = SBP_PANE then Dec(R.Right, 2); + FrameRectEx(Canvas.Handle, R, StatusPanelFrameColor, False); + end; + SBP_GRIPPER: + begin + Dec(R.Right); + Dec(R.Bottom); + DrawHandleElement(Point(R.Right, R.Bottom)); + DrawHandleElement(Point(R.Right, R.Bottom - 4)); + DrawHandleElement(Point(R.Right, R.Bottom - 8)); + + Dec(R.Right, 4); + DrawHandleElement(Point(R.Right, R.Bottom)); + DrawHandleElement(Point(R.Right, R.Bottom - 4)); + + Dec(R.Right, 4); + DrawHandleElement(Point(R.Right, R.Bottom)); + end; + end; +end; + +procedure TTBXOffice2003Theme.TBXSysCommand(var Message: TMessage); +begin + if Message.WParam = TSC_VIEWCHANGE then SetupColorCache; +end; + +initialization + if not IsTBXThemeAvailable('Office2003') then + RegisterTBXTheme('Office2003', TTBXOffice2003Theme); + +end. diff --git a/official/2.1.6+2.1.beta1/TBX/TBXOffice2003Theme.pas.orig b/official/2.1.6+2.1.beta1/TBX/TBXOffice2003Theme.pas.orig new file mode 100644 index 0000000..96cb1af --- /dev/null +++ b/official/2.1.6+2.1.beta1/TBX/TBXOffice2003Theme.pas.orig @@ -0,0 +1,1983 @@ +unit TBXOffice2003Theme; + +// TBX Package +// Copyright 2001-2002 Alex A. Denisov. All Rights Reserved +// See TBX.chm for license and installation instructions +// +// $Id: TBXOfficeXPTheme.pas,v 1.55 2002/12/24 04:32:45 Alex Exp $ +// +// Modified OfficeXP theme by Roy Magne Klever - I named it 'Office11XPtheme' +// +// 07.02.2003 - Roy Magne Klever roy.magne@os.ino.no +// Added gradient to toolbars +// Changed statusbar and draghandels... +// Unknown Changes by Dmitriy Babkin mailto:dimonka@tnt.gov.lv +// Added gradients to menu popups +// Added TBXDock +// Color adjustment... +// 10.04.2003 - Roy Magne Klever +// Just change menu title color... +// Your modifications here + +interface + +uses + Windows, Messages, Graphics, TBXThemes, ImgList; + +{$DEFINE ALTERNATIVE_DISABLED_STYLE} // remove the asterisk to change appearance of disabled images +{*$DEFINE SMALL_CLOSE_BUTTON} // remove the asterisk for smaller close button size + +type + TGradDir = (tGLeftRight, tGTopBottom); + TItemPart = (ipBody, ipText, ipFrame); + TBtnItemState = (bisNormal, bisDisabled, bisSelected, bisPressed, bisHot, + bisDisabledHot, bisSelectedHot, bisPopupParent); + TMenuItemState = (misNormal, misDisabled, misHot, misDisabledHot); + TWinFramePart = (wfpBorder, wfpCaption, wfpCaptionText); + TWinFrameState = (wfsActive, wfsInactive); + + TTBXOffice2003Theme = class(TTBXTheme) + private + procedure TBXSysCommand(var Message: TMessage); message TBX_SYSCOMMAND; + protected + { View/Window Colors } + MenubarColor: TColor; + ToolbarColor: TColor; + PopupColor: TColor; + DockPanelColor: TColor; + + PopupFrameColor: TColor; + WinFrameColors: array [TWinFrameState, TWinFramePart] of TColor; + PnlFrameColors: array [TWinFrameState, TWinFramePart] of TColor; + MenuItemColors: array [TMenuItemState, TItemPart] of TColor; + BtnItemColors: array [TBtnItemState, TItemPart] of TColor; + + { Other Colors } + DragHandleColor: TColor; + PopupSeparatorColor: TColor; + ToolbarSeparatorColor: TColor; + IconShadowColor: TColor; + StatusPanelFrameColor: TColor; + + procedure SetupColorCache; virtual; + protected + { Internal Methods } + function GetPartColor(const ItemInfo: TTBXItemInfo; ItemPart: TItemPart): TColor; + function GetBtnColor(const ItemInfo: TTBXItemInfo; ItemPart: TItemPart): TColor; + public + constructor Create(const AName: string); override; + destructor Destroy; override; + + { Metrics access} + function GetBooleanMetrics(Index: Integer): Boolean; override; + function GetImageOffset(Canvas: TCanvas; const ItemInfo: TTBXItemInfo; ImageList: TCustomImageList): TPoint; override; + function GetIntegerMetrics(Index: Integer): Integer; override; + function GetItemColor(const ItemInfo: TTBXItemInfo): TColor; override; + function GetItemTextColor(const ItemInfo: TTBXItemInfo): TColor; override; + function GetItemImageBackground(const ItemInfo: TTBXItemInfo): TColor; override; + procedure GetMargins(MarginID: Integer; out Margins: TTBXMargins); override; + function GetPopupShadowType: Integer; override; + procedure GetViewBorder(ViewType: Integer; out Border: TPoint); override; + function GetViewColor(AViewType: Integer): TColor; override; + procedure GetViewMargins(ViewType: Integer; out Margins: TTBXMargins); override; + + { Painting routines } + procedure PaintBackgnd(Canvas: TCanvas; const ADockRect, ARect, AClipRect: TRect; AColor: TColor; Transparent: Boolean; AViewType: Integer); override; + procedure PaintButton(Canvas: TCanvas; const ARect: TRect; const ItemInfo: TTBXItemInfo); override; + procedure PaintCaption(Canvas: TCanvas; const ARect: TRect; const ItemInfo: TTBXItemInfo; const ACaption: string; AFormat: Cardinal; Rotated: Boolean); override; + procedure PaintCheckMark(Canvas: TCanvas; ARect: TRect; const ItemInfo: TTBXItemInfo); override; + procedure PaintChevron(Canvas: TCanvas; ARect: TRect; const ItemInfo: TTBXItemInfo); override; + procedure PaintDockPanelNCArea(Canvas: TCanvas; R: TRect; const DockPanelInfo: TTBXDockPanelInfo); override; + procedure PaintDropDownArrow(Canvas: TCanvas; const ARect: TRect; const ItemInfo: TTBXItemInfo); override; + procedure PaintEditButton(Canvas: TCanvas; const ARect: TRect; var ItemInfo: TTBXItemInfo; ButtonInfo: TTBXEditBtnInfo); override; + procedure PaintEditFrame(Canvas: TCanvas; const ARect: TRect; var ItemInfo: TTBXItemInfo; const EditInfo: TTBXEditInfo); override; + procedure PaintFloatingBorder(Canvas: TCanvas; const ARect: TRect; const WindowInfo: TTBXWindowInfo); override; + procedure PaintFrame(Canvas: TCanvas; const ARect: TRect; const ItemInfo: TTBXItemInfo); override; + procedure PaintImage(Canvas: TCanvas; ARect: TRect; const ItemInfo: TTBXItemInfo; ImageList: TCustomImageList; ImageIndex: Integer); override; + procedure PaintMDIButton(Canvas: TCanvas; ARect: TRect; const ItemInfo: TTBXItemInfo; ButtonKind: Cardinal); override; + procedure PaintMenuItem(Canvas: TCanvas; var ARect: TRect; var ItemInfo: TTBXItemInfo); override; + procedure PaintMenuItemFrame(Canvas: TCanvas; const ARect: TRect; const ItemInfo: TTBXItemInfo); override; + procedure PaintPageScrollButton(Canvas: TCanvas; const ARect: TRect; ButtonType: Integer; Hot: Boolean); override; + procedure PaintPopupNCArea(Canvas: TCanvas; R: TRect; const PopupInfo: TTBXPopupInfo); override; + procedure PaintSeparator(Canvas: TCanvas; ARect: TRect; ItemInfo: TTBXItemInfo; Horizontal, LineSeparator: Boolean); override; + procedure PaintToolbarNCArea(Canvas: TCanvas; R: TRect; const ToolbarInfo: TTBXToolbarInfo); override; + procedure PaintGlyph(Canvas: TCanvas; R: TRect; Kind, State: Integer); override; + procedure PaintStatusBar(Canvas: TCanvas; R: TRect; Part: Integer); override; + end; + +implementation + +{.$R tbx_glyphs.res} + +uses TBXUtils, TB2Common, TB2Item, Classes, Controls, Commctrl, Forms; + +var + StockImgList: TImageList; + StockPatternBitmap: TBitmap; + CounterLock: Integer; + gradCol1, gradCol2, gradHandle1, gradHandle2, gradHandle3, gradBL: TColor; + +procedure InitializeStock; +begin + StockImgList := TImageList.Create(nil); + StockImgList.Handle := ImageList_LoadBitmap(HInstance, 'TBXGLYPHS', 16, 0, clWhite); +end; + +procedure FinalizeStock; +begin + StockImgList.Free; +end; + +{ TTBXOffice2003Theme } + +function TTBXOffice2003Theme.GetBooleanMetrics(Index: Integer): Boolean; +begin + case Index of + TMB_OFFICEXPPOPUPALIGNMENT: Result := True; + TMB_EDITCAPTIONINDENTED: Result := True; + TMB_EDITHEIGHTEVEN: Result := False; + else + Result := False; + end; +end; + +function TTBXOffice2003Theme.GetIntegerMetrics(Index: Integer): Integer; +const + DEFAULT = -1; +begin + case Index of + TMI_SPLITBTN_ARROWWIDTH: Result := 12; + + TMI_DROPDOWN_ARROWWIDTH: Result := 8; + TMI_DROPDOWN_ARROWMARGIN: Result := 3; + + TMI_MENU_VMARGIN: Result := 3; + TMI_MENU_HMARGIN: Result := 1; + TMI_MENU_IMGTEXTSPACE: Result := 0; + TMI_MENU_LCAPTIONMARGIN: Result := 8; + TMI_MENU_RCAPTIONMARGIN: Result := 3; + TMI_MENU_SEPARATORSIZE: Result := 3; + TMI_MENU_MDI_DW: Result := 2; + TMI_MENU_MDI_DH: Result := 2; + + TMI_LINE_SPACING: Result := 6; + + TMI_TLBR_SEPARATORSIZE: Result := DEFAULT; + + TMI_EDIT_FRAMEWIDTH: Result := 1; + TMI_EDIT_TEXTMARGINHORZ: Result := 2; + TMI_EDIT_TEXTMARGINVERT: Result := 2; + TMI_EDIT_MENUMIDWIDTH: Result := 0; + TMI_EDIT_BTNWIDTH: Result := 14; + else + Result := DEFAULT; + end; +end; + +function TTBXOffice2003Theme.GetViewColor(AViewType: Integer): TColor; +begin + Result := clBtnFace; + if (AViewType and VT_TOOLBAR) = VT_TOOLBAR then + begin + if (AViewType and TVT_MENUBAR) = TVT_MENUBAR then Result := MenubarColor + else Result := ToolbarColor; + end + else if (AViewType and VT_POPUP) = VT_POPUP then + begin + if (AViewType and PVT_LISTBOX) = PVT_LISTBOX then Result := clWindow + else Result := PopupColor; + end + else if (AViewType and VT_DOCKPANEL) = VT_DOCKPANEL then Result := DockPanelColor; +end; + +function TTBXOffice2003Theme.GetBtnColor(const ItemInfo: TTBXItemInfo; ItemPart: TItemPart): TColor; +const + BFlags1: array [Boolean] of TBtnItemState = (bisDisabled, bisDisabledHot); + BFlags2: array [Boolean] of TBtnItemState = (bisSelected, bisSelectedHot); + BFlags3: array [Boolean] of TBtnItemState = (bisNormal, bisHot); +var + B: TBtnItemState; + Embedded: Boolean; +begin + with ItemInfo do + begin + Embedded := (ViewType and VT_TOOLBAR = VT_TOOLBAR) and + (ViewType and TVT_EMBEDDED = TVT_EMBEDDED); + if not Enabled then B := BFlags1[HoverKind = hkKeyboardHover] + else if ItemInfo.IsPopupParent then + B := bisPopupParent + else if Pushed then B := bisPressed + else if Selected then B := BFlags2[HoverKind <> hkNone] + else B := BFlags3[HoverKind <> hkNone]; + Result := BtnItemColors[B, ItemPart]; + if Embedded then + begin + if (ItemPart = ipBody) and (Result = clNone) then Result := ToolbarColor; + if ItemPart = ipFrame then + begin + if Selected then Result := clWindowFrame + else if (Result = clNone) then Result := clBtnShadow; + end; + end; + end; +end; + +function TTBXOffice2003Theme.GetPartColor(const ItemInfo: TTBXItemInfo; ItemPart: TItemPart): TColor; +const + MFlags1: array [Boolean] of TMenuItemState = (misDisabled, misDisabledHot); + MFlags2: array [Boolean] of TMenuItemState = (misNormal, misHot); + BFlags1: array [Boolean] of TBtnItemState = (bisDisabled, bisDisabledHot); + BFlags2: array [Boolean] of TBtnItemState = (bisSelected, bisSelectedHot); + BFlags3: array [Boolean] of TBtnItemState = (bisNormal, bisHot); +var + IsMenuItem, Embedded: Boolean; + M: TMenuItemState; + B: TBtnItemState; +begin + with ItemInfo do + begin + IsMenuItem := ((ViewType and PVT_POPUPMENU) = PVT_POPUPMENU) and + ((ItemOptions and IO_TOOLBARSTYLE) = 0); + Embedded := ((ViewType and VT_TOOLBAR) = VT_TOOLBAR) and + ((ViewType and TVT_EMBEDDED) = TVT_EMBEDDED); + if IsMenuItem then + begin + if not Enabled then M := MFlags1[HoverKind = hkKeyboardHover] + else M := MFlags2[HoverKind <> hkNone]; + Result := MenuItemColors[M, ItemPart]; + end + else + begin + if not Enabled then B := BFlags1[HoverKind = hkKeyboardHover] + else if ItemInfo.IsPopupParent then B := bisPopupParent + else if Pushed then B := bisPressed + else if Selected then B := BFlags2[HoverKind <> hkNone] + else B := BFlags3[HoverKind <> hkNone]; + Result := BtnItemColors[B, ItemPart]; + if Embedded and (Result = clNone) then + begin + if ItemPart = ipBody then Result := ToolbarColor; + if ItemPart = ipFrame then Result := clBtnShadow; + end; + end; + end; +end; + +procedure FillGradient(const DC: HDC; const ARect: TRect; + const StartColor, EndColor: TColor; + const Direction: TGradDir); +var + rc1, rc2, gc1, gc2, + bc1, bc2, Counter: Integer; + Brush: HBrush; +begin + rc1 := GetRValue(ColorToRGB(StartColor)); + gc1 := GetGValue(ColorToRGB(StartColor)); + bc1 := GetBValue(ColorToRGB(StartColor)); + rc2 := GetRValue(ColorToRGB(EndColor)); + gc2 := GetGValue(ColorToRGB(EndColor)); + bc2 := GetBValue(ColorToRGB(EndColor)); + + if Direction = tGTopBottom then + for Counter := ARect.Top to ARect.Bottom - 1 do + begin + Brush:= CreateSolidBrush( + RGB(Byte(rc1 + (((rc2 - rc1) * (ARect.Top + Counter)) div ARect.Bottom)), + Byte(gc1 + (((gc2 - gc1) * (ARect.Top + Counter)) div ARect.Bottom)), + Byte(bc1 + (((bc2 - bc1) * (ARect.Top + Counter)) div ARect.Bottom)))); + FillRect(DC, Rect(ARect.Left, ARect.Top, ARect.Right, ARect.Bottom - Counter + 1), Brush); + DeleteObject(Brush); + end else + for Counter := ARect.Left to ARect.Right - 1 do + begin + Brush := CreateSolidBrush( + RGB(Byte(rc1 + (((rc2 - rc1) * (ARect.Left + Counter)) div ARect.Right)), + Byte(gc1 + (((gc2 - gc1) * (ARect.Left + Counter)) div ARect.Right)), + Byte(bc1 + (((bc2 - bc1) * (ARect.Left + Counter)) div ARect.Right)))); + FillRect(DC, Rect(ARect.Left, ARect.Top, ARect.Right - Counter +1, ARect.Bottom), Brush); + DeleteObject(Brush); + end; +end; + +function TTBXOffice2003Theme.GetItemColor(const ItemInfo: TTBXItemInfo): TColor; +begin + Result := GetPartColor(ItemInfo, ipBody); + if Result = clNone then Result := GetViewColor(ItemInfo.ViewType); +end; + +function TTBXOffice2003Theme.GetItemTextColor(const ItemInfo: TTBXItemInfo): TColor; +begin + Result := GetPartColor(ItemInfo, ipText); +end; + +function TTBXOffice2003Theme.GetItemImageBackground(const ItemInfo: TTBXItemInfo): TColor; +begin + Result := GetBtnColor(ItemInfo, ipBody); + if Result = clNone then result := GetViewColor(ItemInfo.ViewType); +end; + +procedure TTBXOffice2003Theme.GetViewBorder(ViewType: Integer; out Border: TPoint); +const + XMetrics: array [Boolean] of Integer = (SM_CXDLGFRAME, SM_CXFRAME); + YMetrics: array [Boolean] of Integer = (SM_CYDLGFRAME, SM_CYFRAME); +var + Resizable: Boolean; + + procedure SetBorder(X, Y: Integer); + begin + Border.X := X; + Border.Y := Y; + end; + +begin + if (ViewType and VT_TOOLBAR) = VT_TOOLBAR then + begin + if (ViewType and TVT_FLOATING) = TVT_FLOATING then + begin + Resizable := (ViewType and TVT_RESIZABLE) = TVT_RESIZABLE; + Border.X := GetSystemMetrics(XMetrics[Resizable]) - 1; + Border.Y := GetSystemMetrics(YMetrics[Resizable]) - 1; + end + else SetBorder(2, 2); + end + else if (ViewType and VT_POPUP) = VT_POPUP then + begin + if (ViewType and PVT_POPUPMENU) = PVT_POPUPMENU then Border.X := 1 + else Border.X := 2; + Border.Y := 2; + end + else if (ViewType and VT_DOCKPANEL) = VT_DOCKPANEL then + begin + if (ViewType and DPVT_FLOATING) = DPVT_FLOATING then + begin + Resizable := (ViewType and DPVT_RESIZABLE) = DPVT_RESIZABLE; + Border.X := GetSystemMetrics(XMetrics[Resizable]) - 1; + Border.Y := GetSystemMetrics(YMetrics[Resizable]) - 1; + end + else SetBorder(2, 2); + end + else SetBorder(0, 0); +end; + +procedure TTBXOffice2003Theme.GetMargins(MarginID: Integer; out Margins: TTBXMargins); +begin + with Margins do + case MarginID of + MID_TOOLBARITEM: + begin + LeftWidth := 2; + RightWidth := 2; + TopHeight := 2; + BottomHeight := 2; + end; + MID_STATUSPANE: + begin + LeftWidth := 1; + RightWidth := 3; + TopHeight := 1; + BottomHeight := 1; + end; + else + LeftWidth := 0; + RightWidth := 0; + TopHeight := 0; + BottomHeight := 0; + end; +end; + +procedure TTBXOffice2003Theme.PaintBackgnd(Canvas: TCanvas; const ADockRect, ARect, AClipRect: TRect; + AColor: TColor; Transparent: Boolean; AViewType: Integer); +var + Brush: HBrush; + R, AR: TRect; + IsHoriz: boolean; +begin + if not Transparent then + begin + if ((AViewType and TVT_NORMALTOOLBAR) = TVT_NORMALTOOLBAR) + //or ((AViewType and TVT_TOOLWINDOW) = TVT_TOOLWINDOW) + {or ((AViewType and TVT_MENUBAR) = TVT_MENUBAR)} then + begin + IntersectRect(R, ARect, AClipRect); + if (ADockRect.Top = 0) and + (ADockRect.Left = 0) and + (ADockRect.Right = 0) and + (ADockRect.Bottom = 0) then + IsHoriz:= (ARect.Right > ARect.Bottom) + else + IsHoriz:= Abs(R.Right - R.Left) > Abs(R.Bottom - R.Top); + + if IsHoriz then begin + R.Bottom:= R.Bottom + 1; + FillGradient(Canvas.Handle, R, gradCol1, gradCol2, TGTopBottom); + R.Bottom:= R.Bottom - 1; + end else begin + R.Right:= R.Right + 1; + FillGradient(Canvas.Handle, R, gradCol1, gradCol2, TGLeftRight); + R.Right:= R.Right - 1; + end; + end else begin + Brush := CreateSolidBrush(ColorToRGB(AColor)); + IntersectRect(R, ARect, AClipRect); + + //The rects are compared to determine if we're drawing a toolbar, not a popup menu... + if (ADockRect.Left <> ARect.Left) or (ADockRect.Top <> ARect.Top) + or (ADockRect.Right <> ARect.Right) or (ADockRect.Bottom <> ARect.Bottom) then + FillGradient(Canvas.Handle, R, gradCol2, gradCol1, TGLeftRight) + else + FillRect(Canvas.Handle, R, Brush); + + DeleteObject(Brush); + end; + end; +end; + +procedure TTBXOffice2003Theme.PaintCaption(Canvas: TCanvas; + const ARect: TRect; const ItemInfo: TTBXItemInfo; const ACaption: string; + AFormat: Cardinal; Rotated: Boolean); +var + R: TRect; +begin + with ItemInfo, Canvas do + begin + R := ARect; + Brush.Style := bsClear; + Font.Color := GetPartColor(ItemInfo, ipText); + if not Rotated then Windows.DrawText(Handle, PChar(ACaption), Length(ACaption), R, AFormat) + else DrawRotatedText(Handle, ACaption, R, AFormat); + Brush.Style := bsSolid; + end; +end; + +procedure TTBXOffice2003Theme.PaintCheckMark(Canvas: TCanvas; ARect: TRect; const ItemInfo: TTBXItemInfo); +var + X, Y: Integer; +begin + X := (ARect.Left + ARect.Right) div 2 - 2; + Y := (ARect.Top + ARect.Bottom) div 2 + 1; + Canvas.Pen.Color := GetBtnColor(ItemInfo, ipText); + Canvas.Polyline([Point(X-2, Y-2), Point(X, Y), Point(X+4, Y-4), + Point(X+4, Y-3), Point(X, Y+1), Point(X-2, Y-1), Point(X-2, Y-2)]); +end; + +procedure TTBXOffice2003Theme.PaintChevron(Canvas: TCanvas; ARect: TRect; const ItemInfo: TTBXItemInfo); +const + Pattern: array[Boolean, 0..15] of Byte = ( + ($CC, 0, $66, 0, $33, 0, $66, 0, $CC, 0, 0, 0, 0, 0, 0, 0), + ($88, 0, $D8, 0, $70, 0, $20, 0, $88, 0, $D8, 0, $70, 0, $20, 0)); +var + R2: TRect; + Bmp: TBitmap; +begin + R2 := ARect; + PaintButton(Canvas, ARect, ItemInfo); + if not ItemInfo.IsVertical then + begin + R2.Top := 4; + R2.Bottom := R2.Top + 5; + Inc(R2.Left, 2); + R2.Right := R2.Left + 8; + end + else + begin + R2.Left := R2.Right - 9; + R2.Right := R2.Left + 5; + Inc(R2.Top, 2); + R2.Bottom := R2.Top + 8; + end; + Bmp := TBitmap.Create; + try + Bmp.Handle := CreateBitmap(8, 8, 1, 1, @Pattern[ItemInfo.IsVertical]); + Canvas.Brush.Color := GetPartColor(ItemInfo, ipText); + SetTextColor(Canvas.Handle, clBlack); + SetBkColor(Canvas.Handle, clWhite); + with R2 do BitBlt(Canvas.Handle, Left, Top, Right - Left, + Bottom - Top, Bmp.Canvas.Handle, 0, 0, ROP_DSPDxax); + finally + Bmp.Free; + end; +end; + +procedure TTBXOffice2003Theme.PaintEditButton(Canvas: TCanvas; const ARect: TRect; + var ItemInfo: TTBXItemInfo; ButtonInfo: TTBXEditBtnInfo); +var + BtnDisabled, BtnHot, BtnPressed, Embedded: Boolean; + R, BR: TRect; + X, Y: Integer; + SaveItemInfoPushed: Boolean; +begin + R := ARect; + Embedded := ((ItemInfo.ViewType and VT_TOOLBAR) = VT_TOOLBAR) and + ((ItemInfo.ViewType and TVT_EMBEDDED) = TVT_EMBEDDED); + + InflateRect(R, 1, 1); + Inc(R.Left); + with Canvas do + if ButtonInfo.ButtonType = EBT_DROPDOWN then + begin + BtnDisabled := (ButtonInfo.ButtonState and EBDS_DISABLED) <> 0; + BtnHot := (ButtonInfo.ButtonState and EBDS_HOT) <> 0; + BtnPressed := (ButtonInfo.ButtonState and EBDS_PRESSED) <> 0; + if not BtnDisabled then + begin + if BtnPressed or BtnHot or Embedded then PaintButton(Canvas, R, ItemInfo) + else if (ItemInfo.ViewType and VT_TOOLBAR) = VT_TOOLBAR then + begin + R := ARect; + if not Embedded then + begin + FrameRectEx(Canvas, R, clWindow); + Pen.Color := clWindow; + end + else Pen.Color := GetBtnColor(ItemInfo, ipFrame); + MoveTo(R.Left - 1, R.Top); LineTo(R.Left - 1, R.Bottom); + end; + end; + PaintDropDownArrow(Canvas, R, ItemInfo); + end + else if ButtonInfo.ButtonType = EBT_SPIN then + begin + BtnDisabled := (ButtonInfo.ButtonState and EBSS_DISABLED) <> 0; + BtnHot := (ButtonInfo.ButtonState and EBSS_HOT) <> 0; + + { Upper button } + BR := R; + BR.Bottom := (R.Top + R.Bottom + 1) div 2; + BtnPressed := (ButtonInfo.ButtonState and EBSS_UP) <> 0; + SaveItemInfoPushed := ItemInfo.Pushed; + ItemInfo.Pushed := BtnPressed; + if not BtnDisabled then + begin + if BtnPressed or BtnHot or Embedded then PaintButton(Canvas, BR, ItemInfo) + else if (ItemInfo.ViewType and VT_TOOLBAR) = VT_TOOLBAR then + begin + BR.Left := ARect.Left; BR.Top := ARect.Top; BR.Right := ARect.Right; + if not Embedded then + begin + FrameRectEx(Canvas, BR, clWindow); + Pen.Color := clWindow; + end + else Pen.Color := GetBtnColor(ItemInfo, ipFrame); + MoveTo(BR.Left - 1, BR.Top); LineTo(BR.Left - 1, BR.Bottom); + end; + end; + X := (BR.Left + BR.Right) div 2; + Y := (BR.Top + BR.Bottom - 1) div 2; + Pen.Color := GetPartColor(ItemInfo, ipText); + Brush.Color := Pen.Color; + Polygon([Point(X - 2, Y + 1), Point(X + 2, Y + 1), Point(X, Y - 1)]); + + { Lower button } + BR := R; + BR.Top := (R.Top + R.Bottom) div 2; + BtnPressed := (ButtonInfo.ButtonState and EBSS_DOWN) <> 0; + ItemInfo.Pushed := BtnPressed; + if not BtnDisabled then + begin + if BtnPressed or BtnHot or Embedded then PaintButton(Canvas, BR, ItemInfo) + else if (ItemInfo.ViewType and VT_TOOLBAR) = VT_TOOLBAR then + begin + BR.Left := ARect.Left; BR.Bottom := ARect.Bottom; BR.Right := ARect.Right; + if not Embedded then + begin + FrameRectEx(Canvas, BR, clWindow); + Pen.Color := clWindow; + end + else Pen.Color := GetBtnColor(ItemInfo, ipFrame); + MoveTo(BR.Left - 1, BR.Top); LineTo(BR.Left - 1, BR.Bottom); + end; + end; + X := (BR.Left + BR.Right) div 2; + Y := (BR.Top + BR.Bottom) div 2; + Pen.Color := GetPartColor(ItemInfo, ipText); + Brush.Color := Pen.Color; + Polygon([Point(X - 2, Y - 1), Point(X + 2, Y - 1), Point(X, Y + 1)]); + + ItemInfo.Pushed := SaveItemInfoPushed; + end; +end; + +procedure TTBXOffice2003Theme.PaintEditFrame(Canvas: TCanvas; + const ARect: TRect; var ItemInfo: TTBXItemInfo; const EditInfo: TTBXEditInfo); +var + R: TRect; + W: Integer; + Embedded: Boolean; +begin + R := ARect; + PaintFrame(Canvas, R, ItemInfo); + W := EditFrameWidth; + InflateRect(R, -W, -W); + Embedded := ((ItemInfo.ViewType and VT_TOOLBAR) = VT_TOOLBAR) and + ((ItemInfo.ViewType and TVT_EMBEDDED) = TVT_EMBEDDED); + if not (ItemInfo.Enabled or Embedded) then + FrameRectEx(Canvas, R, BtnItemColors[bisDisabled, ipText]); + + with EditInfo do + begin + if LeftBtnWidth > 0 then Inc(R.Left, LeftBtnWidth - 2); + if RightBtnWidth > 0 then Dec(R.Right, RightBtnWidth - 2); + end; + + if ItemInfo.Enabled then + begin + if ((ItemInfo.ViewType and VT_TOOLBAR) <> VT_TOOLBAR) and + (GetPartColor(ItemInfo, ipFrame) = clNone) then + FrameRectEx(Canvas, R, ToolbarColor) + else + begin + Canvas.Brush.Color := clWindow; + Canvas.FrameRect(R); + end; + end; + InflateRect(R, -1, -1); + if ItemInfo.Enabled then + begin + Canvas.Brush.Color := clWindow; + Canvas.FillRect(R); + if ((ItemInfo.ViewType and VT_TOOLBAR) <> VT_TOOLBAR) and + (GetPartColor(ItemInfo, ipFrame) = clNone) then + begin + Canvas.Brush.Color := ToolbarColor; + R := ARect; + InflateRect(R, -1, -1); + Canvas.FrameRect(R); + end; + end; + if EditInfo.RightBtnWidth > 0 then + begin + R := ARect; + InflateRect(R, -W, -W); + R.Left := R.Right - EditInfo.RightBtnWidth; + PaintEditButton(Canvas, R, ItemInfo, EditInfo.RightBtnInfo); + end; +end; + +procedure TTBXOffice2003Theme.PaintDropDownArrow(Canvas: TCanvas; + const ARect: TRect; const ItemInfo: TTBXItemInfo); +var + X, Y: Integer; +begin + with ARect, Canvas do + begin + X := (Left + Right) div 2; + Y := (Top + Bottom) div 2 - 1; + Pen.Color := GetPartColor(ItemInfo, ipText); + Brush.Color := Pen.Color; + if ItemInfo.IsVertical then Polygon([Point(X, Y + 2), Point(X, Y - 2), Point(X - 2, Y)]) + else Polygon([Point(X - 2, Y), Point(X + 2, Y), Point(X, Y + 2)]); + end; +end; + +procedure TTBXOffice2003Theme.PaintButton(Canvas: TCanvas; const ARect: TRect; const ItemInfo: TTBXItemInfo); +var + R: TRect; +begin + with ItemInfo, Canvas do + begin + R := ARect; + if ((ItemOptions and IO_DESIGNING) <> 0) and not Selected then + begin + Brush.Color := GetNearestColor(Handle, MixColors(clBtnShadow, clBtnFace, 100)); + if ComboPart = cpSplitRight then Dec(R.Left); + FrameRect(R); + end + else + begin + FrameRectEx(Canvas, R, GetBtnColor(ItemInfo, ipFrame), True); + if (ComboPart = cpSplitLeft) and IsPopupParent then Inc(R.Right); + if ComboPart = cpSplitRight then Dec(R.Left); + // rmk + if (Selected) and ((ViewType and VT_TOOLBAR) = VT_TOOLBAR) then begin + if IsVertical then + FillGradient(Canvas.Handle, R, GetBtnColor(ItemInfo, ipBody), gradCol2, TGLeftRight) + else + FillGradient(Canvas.Handle, R, GetBtnColor(ItemInfo, ipBody), gradCol2, TGTopBottom); + end else + FillRectEx(Canvas, R, GetBtnColor(ItemInfo, ipBody)); + end; + if ComboPart = cpSplitRight then PaintDropDownArrow(Canvas, R, ItemInfo); + end; +end; + +procedure TTBXOffice2003Theme.PaintFloatingBorder(Canvas: TCanvas; const ARect: TRect; + const WindowInfo: TTBXWindowInfo); +const + WinStates: array [Boolean] of TWinFramestate = (wfsInactive, wfsActive); + + function GetBtnItemState(BtnState: Integer): TBtnItemState; + begin + if not WindowInfo.Active then Result := bisDisabled + else if (BtnState and CDBS_PRESSED) <> 0 then Result := bisPressed + else if (BtnState and CDBS_HOT) <> 0 then Result := bisHot + else Result := bisNormal; + end; + +var + WinState: TWinFrameState; + BtnItemState: TBtnItemState; + SaveIndex, X, Y: Integer; + Sz: TPoint; + R: TRect; + BodyColor, CaptionColor, CaptionText: TColor; + IsDockPanel: Boolean; + + procedure DrawGlyph(C: TColor); + var + Bmp: TBitmap; + DC: HDC; + begin + Bmp := TBitmap.Create; + try + Bmp.Monochrome := True; + StockImgList.GetBitmap(0, Bmp); + Canvas.Brush.Color := C; + DC := Canvas.Handle; + SetTextColor(DC, clBlack); + SetBkColor(DC, clWhite); + BitBlt(DC, X, Y, StockImgList.Width, StockImgList.Height, + Bmp.Canvas.Handle, 0, 0, ROP_DSPDxax); + finally + Bmp.Free; + end; + end; + +begin + with Canvas do + begin + WinState := WinStates[WindowInfo.Active]; + IsDockPanel := (WindowInfo.ViewType and VT_DOCKPANEL) = VT_DOCKPANEL; + BodyColor := Brush.Color; + + if (WRP_BORDER and WindowInfo.RedrawPart) <> 0 then + begin + R := ARect; + + if not IsDockPanel then + Brush.Color := WinFrameColors[WinState, wfpBorder] + else + Brush.Color := PnlFrameColors[WinState, wfpBorder]; + SaveIndex := SaveDC(Canvas.Handle); + Sz := WindowInfo.FloatingBorderSize; + with R, Sz do ExcludeClipRect(Canvas.Handle, Left + X, Top + Y, Right - X, Bottom - Y); + FillRect(R); + RestoreDC(Canvas.Handle, SaveIndex); + InflateRect(R, -Sz.X, -Sz.Y); + Pen.Color := BodyColor; + with R do + if not IsDockPanel then + Canvas.Polyline([ + Point(Left, Top - 1), Point(Right - 1, Top - 1), + Point(Right, Top), Point(Right, Bottom - 1), + Point(Right - 1, Bottom), + Point(Left, Bottom), Point(Left - 1, Bottom - 1), + Point(Left - 1, Top), Point(Left, Top - 1) + ]) + else + Canvas.Polyline([ + Point(Left, Top - 1), Point(Right - 1, Top - 1), + Point(Right, Top), Point(Right, Bottom), + Point(Left - 1, Bottom), + Point(Left - 1, Top), Point(Left, Top - 1) + ]); + end; + + if not WindowInfo.ShowCaption then Exit; + + if (WindowInfo.ViewType and VT_TOOLBAR) = VT_TOOLBAR then + begin + CaptionColor := WinFrameColors[WinState, wfpCaption]; + CaptionText := WinFrameColors[WinState, wfpCaptionText]; + end + else + begin + CaptionColor := PnlFrameColors[WinState, wfpCaption]; + CaptionText := PnlFrameColors[WinState, wfpCaptionText]; + end; + + { Caption } + if (WRP_CAPTION and WindowInfo.RedrawPart) <> 0 then + begin + R := Rect(0, 0, WindowInfo.ClientWidth, GetSystemMetrics(SM_CYSMCAPTION) - 1); + with WindowInfo.FloatingBorderSize do OffsetRect(R, X, Y); + DrawLineEx(Canvas, R.Left, R.Bottom, R.Right, R.Bottom, BodyColor); + + if ((CDBS_VISIBLE and WindowInfo.CloseButtonState) <> 0) and + ((WRP_CLOSEBTN and WindowInfo.RedrawPart) <> 0) then + Dec(R.Right, GetSystemMetrics(SM_CYSMCAPTION) - 1); + + Brush.Color := CaptionColor; + FillRect(R); + InflateRect(R, -2, 0); + Font.Assign(SmCaptionFont); + Font.Color := CaptionText; + DrawText(Canvas.Handle, WindowInfo.Caption, -1, R, + DT_SINGLELINE or DT_VCENTER or DT_END_ELLIPSIS or DT_HIDEPREFIX); + end; + + { Close button } + if (CDBS_VISIBLE and WindowInfo.CloseButtonState) <> 0 then + begin + R := Rect(0, 0, WindowInfo.ClientWidth, GetSystemMetrics(SM_CYSMCAPTION) - 1); + with WindowInfo.FloatingBorderSize do OffsetRect(R, X, Y); + R.Left := R.Right - (R.Bottom - R.Top); + DrawLineEx(Canvas, R.Left - 1, R.Bottom, R.Right, R.Bottom, BodyColor); + Brush.Color := CaptionColor; + FillRect(R); + with R do + begin + X := (Left + Right - StockImgList.Width + 1) div 2; + Y := (Top + Bottom - StockImgList.Height) div 2; + end; + BtnItemState := GetBtnItemState(WindowInfo.CloseButtonState); + FrameRectEx(Canvas, R, BtnItemColors[BtnItemState, ipFrame], True); + if FillRectEx(Canvas, R, BtnItemColors[BtnItemState, ipBody]) then + DrawGlyph(BtnItemColors[BtnItemState, ipText]) + else + DrawGlyph(CaptionText); + end; + end; +end; + +procedure TTBXOffice2003Theme.PaintFrame(Canvas: TCanvas; const ARect: TRect; + const ItemInfo: TTBXItemInfo); +var + R: TRect; +begin + R := ARect; + FrameRectEx(Canvas, R, GetPartColor(ItemInfo, ipFrame), True); + FillRectEx(Canvas, R, GetPartColor(ItemInfo, ipBody)); +end; + +function TTBXOffice2003Theme.GetImageOffset(Canvas: TCanvas; + const ItemInfo: TTBXItemInfo; ImageList: TCustomImageList): TPoint; +begin + Result.X := 0; + if not (ImageList is TTBCustomImageList) then + with ItemInfo do + if Enabled and (HoverKind <> hkNone) and + not (Selected or Pushed and not IsPopupParent) then + Result.X := -1; + Result.Y := Result.X +end; + +procedure TTBXOffice2003Theme.PaintImage(Canvas: TCanvas; ARect: TRect; + const ItemInfo: TTBXItemInfo; ImageList: TCustomImageList; ImageIndex: Integer); +var + HiContrast: Boolean; +begin + with ItemInfo do + begin + if ImageList is TTBCustomImageList then + begin + TTBCustomImageList(ImageList).DrawState(Canvas, ARect.Left, ARect.Top, + ImageIndex, Enabled, (HoverKind <> hkNone), Selected); + Exit; + end; + +{$IFNDEF ALTERNATIVE_DISABLED_STYLE} + HiContrast := IsDarkColor(GetItemImageBackground(ItemInfo), 64); + + if not Enabled then + begin + DrawTBXIconFlatShadow(Canvas, ARect, ImageList, ImageIndex, + BtnItemColors[bisDisabled, ipText]); + end + else if Selected or Pushed or (HoverKind <> hkNone) then + begin + if not (Selected or Pushed and not IsPopupParent) then + begin + OffsetRect(ARect, 1, 1); + DrawTBXIconFullShadow(Canvas, ARect, ImageList, ImageIndex, IconShadowColor); + OffsetRect(ARect, -2, -2); + end; + DrawTBXIcon(Canvas, ARect, ImageList, ImageIndex, HiContrast); + end + else if HiContrast or TBXHiContrast or TBXLoColor then + DrawTBXIcon(Canvas, ARect, ImageList, ImageIndex, HiContrast) + else + HighlightTBXIcon(Canvas, ARect, ImageList, ImageIndex, clWindow, 178); +{$ELSE} + HiContrast := ColorIntensity(GetItemImageBackground(ItemInfo)) < 80; + if not Enabled then + begin + if not HiContrast then + DrawTBXIconShadow(Canvas, ARect, ImageList, ImageIndex, 0) + else + DrawTBXIconFlatShadow(Canvas, ARect, ImageList, ImageIndex, clBtnShadow); + end + else if Selected or Pushed or (HoverKind <> hkNone) then + begin + if not (Selected or Pushed and not IsPopupParent) then + begin + //DrawTBXIconShadow(Canvas, ARect, ImageList, ImageIndex, 1); + //OffsetRect(ARect, 1, 1); + //DrawTBXIconShadow(Canvas, ARect, ImageList, ImageIndex, 1); + //OffsetRect(ARect, -2, -2); + end; + DrawTBXIcon(Canvas, ARect, ImageList, ImageIndex, HiContrast); + end + else if HiContrast or TBXHiContrast or TBXLoColor then + DrawTBXIcon(Canvas, ARect, ImageList, ImageIndex, HiContrast) + else + HighlightTBXIcon(Canvas, ARect, ImageList, ImageIndex, clWindow, 178); +{$ENDIF} + end; +end; + +procedure TTBXOffice2003Theme.PaintMDIButton(Canvas: TCanvas; ARect: TRect; + const ItemInfo: TTBXItemInfo; ButtonKind: Cardinal); +var + Index: Integer; + X, Y: Integer; + Bmp: TBitmap; +begin + PaintButton(Canvas, ARect, ItemInfo); + with ARect do + begin + X := (Left + Right - StockImgList.Width) div 2; + Y := (Top + Bottom - StockImgList.Height) div 2; + end; + case ButtonKind of + DFCS_CAPTIONMIN: Index := 2; + DFCS_CAPTIONRESTORE: Index := 3; + DFCS_CAPTIONCLOSE: Index := 0; + else + Exit; + end; + Bmp := TBitmap.Create; + Bmp.Monochrome := True; + StockImgList.GetBitmap(Index, Bmp); + Canvas.Brush.Color := GetPartColor(ItemInfo, ipText); + SetTextColor(Canvas.Handle, clBlack); + SetBkColor(Canvas.Handle, clWhite); + BitBlt(Canvas.Handle, X, Y, StockImgList.Width, StockImgList.Height, + Bmp.Canvas.Handle, 0, 0, ROP_DSPDxax); + Bmp.Free; +end; + +procedure TTBXOffice2003Theme.PaintMenuItemFrame(Canvas: TCanvas; + const ARect: TRect; const ItemInfo: TTBXItemInfo); +var + R: TRect; +begin + R := ARect; + if (ItemInfo.ViewType and PVT_TOOLBOX) <> PVT_TOOLBOX then with Canvas do + begin + R.Right := R.Left + ItemInfo.PopupMargin + 2; + Brush.Color := ToolbarColor; + //FillRect(R); + FillGradient(Handle, R, gradCol1, gradCol2, tGLeftRight); + Inc(R.Left); + R.Right := ARect.Right - 1; + end; + PaintFrame(Canvas, R, ItemInfo); +end; + +procedure TTBXOffice2003Theme.PaintMenuItem(Canvas: TCanvas; var ARect: TRect; + var ItemInfo: TTBXItemInfo); +var + R: TRect; + X, Y: Integer; + ArrowWidth: Integer; + ClrText: TColor; + + procedure DrawArrow(AColor: TColor); + begin + Canvas.Pen.Color := AColor; + Canvas.Brush.Color := AColor; + Canvas.Polygon([Point(X, Y - 3), Point(X, Y + 3), Point(X + 3, Y)]); + end; + +begin + with Canvas, ItemInfo do + begin + ArrowWidth := GetSystemMetrics(SM_CXMENUCHECK); + PaintMenuItemFrame(Canvas, ARect, ItemInfo); + ClrText := GetPartColor(ItemInfo, ipText); + R := ARect; + + if (ItemOptions and IO_COMBO) <> 0 then + begin + X := R.Right - ArrowWidth - 1; + if not ItemInfo.Enabled then Pen.Color := ClrText + else if HoverKind = hkMouseHover then Pen.Color := GetPartColor(ItemInfo, ipFrame) + else Pen.Color := PopupSeparatorColor; + MoveTo(X, R.Top + 1); + LineTo(X, R.Bottom - 1); + end; + + if (ItemOptions and IO_SUBMENUITEM) <> 0 then + begin + Y := ARect.Bottom div 2; + X := ARect.Right - ArrowWidth * 2 div 3 - 1; + DrawArrow(ClrText); + end; + + InflateRect(ARect, -1, -1); + + if Selected and Enabled then + begin + R := ARect; + R.Left := ARect.Left + 1; + R.Right := R.Left + ItemInfo.PopupMargin - 2; + FrameRectEx(Canvas, R, GetBtnColor(ItemInfo, ipFrame), True); + // rmk + FillGradient(Canvas.Handle, R, GetBtnColor(ItemInfo, ipBody), gradCol2, TGTopBottom); + //FillRectEx(Canvas, R, GetBtnColor(ItemInfo, ipBody)); + end; + end; +end; + +procedure TTBXOffice2003Theme.PaintPopupNCArea(Canvas: TCanvas; R: TRect; const PopupInfo: TTBXPopupInfo); +var + PR: TRect; +begin + with Canvas do + begin + Brush.Color := PopupFrameColor; + FrameRect(R); + InflateRect(R, -1, -1); + Brush.Color := PopupColor; + FillRect(R); + + if not IsRectEmpty(PopupInfo.ParentRect) then + begin + PR := PopupInfo.ParentRect; + if not IsRectEmpty(PR) then with PR do + begin + Pen.Color := ToolbarColor; + if Bottom = R.Top then + begin + if Left <= R.Left then Left := R.Left - 1; + if Right >= R.Right then Right := R.Right + 1; + MoveTo(Left + 1, Bottom - 1); + LineTo(Right - 1, Bottom- 1); + end + else if Top = R.Bottom then + begin + if Left <= R.Left then Left := R.Left - 1; + if Right >= R.Right then Right := R.Right + 1; + MoveTo(Left + 1, Top); + LineTo(Right - 1, Top); + end; + if Right = R.Left then + begin + if Top <= R.Top then Top := R.Top - 1; + if Bottom >= R.Bottom then Bottom := R.Bottom + 1; + MoveTo(Right - 1, Top + 1); + LineTo(Right - 1, Bottom - 1); + end + else if Left = R.Right then + begin + if Top <= R.Top then Top := R.Top - 1; + if Bottom >= R.Bottom then Bottom := R.Bottom + 1; + MoveTo(Left, Top + 1); + LineTo(Left, Bottom - 1); + end; + end; + end; + end; +end; + +procedure TTBXOffice2003Theme.PaintSeparator(Canvas: TCanvas; ARect: TRect; + ItemInfo: TTBXItemInfo; Horizontal, LineSeparator: Boolean); +var + IsToolbox: Boolean; + R: TRect; +begin + with ItemInfo, ARect, Canvas do + begin + if Horizontal then + begin + IsToolbox := (ViewType and PVT_TOOLBOX) = PVT_TOOLBOX; + if ((ItemOptions and IO_TOOLBARSTYLE) = 0) and not IsToolBox then + begin + R := ARect; + R.Right := ItemInfo.PopupMargin + 2; + Brush.Color := ToolbarColor; + //FillRect(R); + FillGradient(Canvas.Handle, R, gradCol1, gradCol2, tGLeftRight); + Inc(Left, ItemInfo.PopupMargin + 9); + Pen.Color := PopupSeparatorColor; + end + else + Pen.Color := ToolbarSeparatorColor; + + // rmkPaint + Top:= Bottom div 2; + Left:= Left + 1; + Right:= Right - 2; + Bottom:= Top + 1; + DrawLineEx(Canvas, Left, Top, Right, Top, clWhite); + Left:= Left - 1; + Right:= Right + 2; + DrawLineEx(Canvas, Left, Top, Right, Top, PopupSeparatorColor); + + //Top := Bottom div 2; + //MoveTo(Left, Top); LineTo(Right, Top); + end else begin + Top:= Top + 4; + Bottom:= Bottom - 4; + Left:= Right div 2; + DrawLineEx(Canvas, Left, Top, Left, Bottom, clWhite); + Top:= Top - 1; + Left:= Left - 1; + Bottom:= Bottom - 1; + DrawLineEx(Canvas, Left, Top, Left, Bottom, ToolbarSeparatorColor); + end; + end; +end; + +procedure DrawButtonBitmap(Canvas: TCanvas; R: TRect; Color: TColor); +const +{$IFNDEF SMALL_CLOSE_BUTTON} + Pattern: array [0..15] of Byte = + ($C3, 0, $66, 0, $3C, 0, $18, 0, $3C, 0, $66, 0, $C3, 0, 0, 0); +{$ELSE} + Pattern: array [0..15] of Byte = + (0, 0, $63, 0, $36, 0, $1C, 0, $1C, 0, $36, 0, $63, 0, 0, 0); +{$ENDIF} +var + Bmp: TBitmap; + W, H: Integer; + Index: Integer; +begin + Bmp := TBitmap.Create; + try + Bmp.Handle := CreateBitmap(8, 8, 1, 1, @Pattern); + Index := SaveDC(Canvas.Handle); + Canvas.Brush.Color := Color; + SetTextColor(Canvas.Handle, clBlack); + SetBkColor(Canvas.Handle, clWhite); + W := 8; + H := 7; + with R do + begin + BitBlt(Canvas.Handle, (Left + Right - W + 1) div 2, (Top + Bottom - H) div 2, W, H, + Bmp.Canvas.Handle, 0, 0, ROP_DSPDxax); + end; + RestoreDC(Canvas.Handle, Index); + finally + Bmp.Free; + end; +end; + +procedure TTBXOffice2003Theme.PaintToolbarNCArea(Canvas: TCanvas; R: TRect; + const ToolbarInfo: TTBXToolbarInfo); +const + DragHandleOffsets: array [Boolean, DHS_DOUBLE..DHS_SINGLE] of Integer = ((2, 0, 1), (5, 0, 5)); + + function GetBtnItemState(BtnState: Integer): TBtnItemState; + begin + if (BtnState and CDBS_PRESSED) <> 0 then Result := bisPressed + else if (BtnState and CDBS_HOT) <> 0 then Result := bisHot + else Result := bisNormal; + end; + +var + Sz: Integer; + R2: TRect; + C: TColor; + Hi1, Lo1, Hi2, Lo2, Hi3, Lo3, Hi4: TColor; + I: Integer; + BtnVisible, Horz: Boolean; + BtnItemState: TBtnItemState; +begin + with Canvas do + begin + if ((ToolbarInfo.ViewType and TVT_NORMALTOOLBAR) = TVT_NORMALTOOLBAR) then begin + with R do begin + if (R.Right > R.Bottom) then begin + FillGradient(Canvas.Handle, R, gradCol1, gradCol2, TGTopBottom); + R2:= R; + R2.Left:= R2.Right - 1; + FillGradient(Canvas.Handle, R2, GradBL, gradCol1, TGTopBottom); + + Pen.Color:= gradBL; + MoveTo(Left+ 1, Bottom - 1); + LineTo(Right-1, Bottom - 1); + + Pen.Color:= gradCol1; + MoveTo(Right-1, Bottom - 1); + LineTo(Right-1, Bottom - 2); + + Pen.Color:= gradCol1; + MoveTo(Left, Top); + LineTo(Left, Top + 1); + MoveTo(Right-2, Top); + LineTo(Right-2, Top + 1); + end else begin + FillGradient(Canvas.Handle, R, gradCol1, gradCol2, TGLeftRight); + R2:= R; + R2.Top:= R2.Bottom - 1; + FillGradient(Canvas.Handle, R2, GradBL, gradCol1, TGLeftRight); + + Pen.Color:= gradBL;; + MoveTo(Right-1, Top + 1); + LineTo(Right-1, Bottom - 1); + Pen.Color:= gradCol1; + MoveTo(Left, Top); + LineTo(Left, Top + 1); + MoveTo(Left, Bottom - 2); + LineTo(Left, Bottom); + end; + end; + InflateRect(R, -2, -2); + end else + begin + FillGradient(Handle, R, gradCol2, gradCol1, TGLeftRight); + InflateRect(R, -2, -2); + end; + + if not ToolbarInfo.AllowDrag then Exit; + + BtnVisible := (ToolbarInfo.CloseButtonState and CDBS_VISIBLE) <> 0; + Sz := GetTBXDragHandleSize(ToolbarInfo); + Horz := not ToolbarInfo.IsVertical; + if Horz then R.Right := R.Left + Sz + else R.Bottom := R.Top + Sz; + + { Drag Handle } + c:= gradHandle1;//clBtnFace; clBtnShadow + Brush.Color:= c; + Hi1:= GetNearestColor(Handle, MixColors(c, gradHandle2, 64)); + Lo1:= GetNearestColor(Handle, MixColors(c, gradHandle2, 48)); + Hi2:= GetNearestColor(Handle, MixColors(c, gradHandle2, 32)); + Lo2:= GetNearestColor(Handle, MixColors(c, gradHandle2, 16)); + Hi3:= GetNearestColor(Handle, MixColors(c, gradHandle3, 128)); + Lo3:= GetNearestColor(Handle, MixColors(c, gradHandle3, 96)); + Hi4:= GetNearestColor(Handle, MixColors(c, gradHandle3, 72)); + +{ if (ToolbarInfo.ViewType and TVT_MENUBAR) <> TVT_MenuBar then + begin + if (R.Right < R.Bottom) then begin + R.Left:= R.Left - 1; + R.Bottom:= R.Bottom + 1; + FillGradient(Canvas.Handle, R, gradCol1, gradCol2, TGTopBottom); + with R do + begin + Pixels[Left, Top]:= gradCol1; + Pixels[Left, Bottom - 2]:= gradCol1; + end; + R.Bottom:= R.Bottom - 1; + R.Left:= R.Left + 1 + end else begin + R.Top:= R.Top - 1; + R.Right:= R.Right + 1; + FillGradient(Canvas.Handle, R, gradCol1, gradCol2, TGLeftRight); + with R do + begin + Pixels[Left, Top]:= gradCol1; + Pixels[Right - 2, Top]:= gradCol1; + end; + R.Right:= R.Right - 1; + R.Top:= R.Top + 1; + end; + end; +} + if ToolbarInfo.DragHandleStyle <> DHS_NONE then + begin + R2:= R; + if Horz then + begin + Inc(R2.Top, 4); + Dec(R2.Bottom, 2); + Inc(R2.Left, 1); + if BtnVisible then begin + Inc(R2.Top, Sz - 2); + Inc(R2.Left, 4); + Dec(R2.Right, 4); + end; + i:= R2.Top; + while (i < R2.Bottom-3) do + begin + Pixels[R2.Left, i]:= Hi1; + Pixels[R2.Left, i + 1]:= Hi2; + Pixels[R2.Left + 1, i]:= Lo1; + Pixels[R2.Left + 1, i + 1]:= Lo2; + Pixels[R2.Left + 1, i + 2]:= Hi4; + Pixels[R2.Left + 2, i + 2]:= Hi3; + Pixels[R2.Left + 2, i + 1]:= Lo3; + if ToolbarInfo.DragHandleStyle = DHS_DOUBLE then + begin + Pixels[R2.Left + 4, i]:= Hi1; + Pixels[R2.Left + 4, i + 1]:= Hi2; + Pixels[R2.Left + 4 + 1, i]:= Lo1; + Pixels[R2.Left + 4 + 1, i + 1]:= Lo2; + Pixels[R2.Left + 4 + 1, i + 2]:= Hi4; + Pixels[R2.Left + 4 + 2, i + 2]:= Hi3; + Pixels[R2.Left + 4 + 2, i + 1]:= Lo3; + end; + Inc(i, 4); + end; + end else + begin + Inc(R2.Left, 4); + Dec(R2.Right, 2); + Inc(R2.Top, 1); + if BtnVisible then begin + Dec(R2.Right, Sz - 2); + Inc(R2.Top, 4); + Dec(R2.Bottom, 4); + end; + i:= R2.Left; + while (i < R2.Right-3) do + begin + Pixels[i, R2.Top]:= Hi1; + Pixels[i, R2.Top + 1]:= Hi2; + Pixels[i + 1, R2.Top]:= Lo1; + Pixels[i + 1, R2.Top + 1]:= Lo2; + Pixels[i + 1, R2.Top + 2]:= Hi4; + Pixels[i + 2, R2.Top + 2]:= Hi3; + Pixels[i + 2, R2.Top + 1]:= Lo3; + if ToolbarInfo.DragHandleStyle = DHS_DOUBLE then + begin + Pixels[i, R2.Top + 4]:= Hi1; + Pixels[i, R2.Top + 1 + 4]:= Hi2; + Pixels[i + 1, R2.Top + 4]:= Lo1; + Pixels[i + 1, R2.Top + 1 + 4]:= Lo2; + Pixels[i + 1, R2.Top + 2 + 4]:= Hi4; + Pixels[i + 2, R2.Top + 2 + 4]:= Hi3; + Pixels[i + 2, R2.Top + 1 + 4]:= Lo3; + end; + Inc(i, 4); + end; + end; + end; + + { Close button } + if BtnVisible then + begin + R2 := R; + if Horz then + begin + Dec(R2.Right); + R2.Bottom := R2.Top + R2.Right - R2.Left; + end + else + begin + Dec(R2.Bottom); + R2.Left := R2.Right - R2.Bottom + R2.Top; + end; + + BtnItemState := GetBtnItemState(ToolbarInfo.CloseButtonState); + FrameRectEx(Canvas, R2, BtnItemColors[BtnItemState, ipFrame], True); + FillRectEx(Canvas, R2, BtnItemColors[BtnItemState, ipBody]); + DrawButtonBitmap(Canvas, R2, BtnItemColors[BtnItemState, ipText]); + end; + end; +end; + + +procedure TTBXOffice2003Theme.PaintDockPanelNCArea(Canvas: TCanvas; R: TRect; const DockPanelInfo: TTBXDockPanelInfo); + + function GetBtnItemState(BtnState: Integer): TBtnItemState; + begin + if (BtnState and CDBS_PRESSED) <> 0 then Result := bisPressed + else if (BtnState and CDBS_HOT) <> 0 then Result := bisHot + else Result := bisNormal; + end; + +var + C, HeaderColor: TColor; + I, Sz, Flags: Integer; + R2: TRect; + BtnItemState: TBtnItemState; +begin + with Canvas, DockPanelInfo do + begin + C := Brush.Color; // Dock panel passes its body color in Canvas.Brush + I := ColorIntensity(ColorToRGB(clBtnFace)); + R2 := R; + if not TBXLoColor and (I in [64..250]) then + begin + FrameRectEx(Canvas, R, clBtnFace, True); + FrameRectEx(Canvas, R, C); + with R do + begin + Pixels[Left, Top] := clBtnFace; + if IsVertical then Pixels[Right - 1, Top] := clBtnFace + else Pixels[Left, Bottom - 1] := clBtnFace; + end; + end + else + begin + FrameRectEx(Canvas, R, C, True); + if I < 64 then Brush.Bitmap := AllocPatternBitmap(C, clWhite) + else Brush.Bitmap := AllocPatternBitmap(C, clBtnShadow); + FrameRect(R); + with R do + begin + Pixels[Left, Top] := C; + if IsVertical then Pixels[Right - 1, Top] := C + else Pixels[Left, Bottom - 1] := C; + end; + InflateRect(R, -1, -1); + FrameRectEx(Canvas, R, C); + end; + R := R2; + InflateRect(R, -BorderSize.X, -BorderSize.Y); + Sz := GetSystemMetrics(SM_CYSMCAPTION); + if IsVertical then + begin + R.Bottom := R.Top + Sz - 1; + DrawLineEx(Canvas, R.Left, R.Bottom, R.Right, R.Bottom, C); + end + else + begin + R.Right := R.Left + Sz - 1; + DrawLineEx(Canvas, R.Right, R.Top, R.Right, R.Bottom, C); + end; + HeaderColor := clBtnFace; + FillRectEx(Canvas, R, HeaderColor); + + if (CDBS_VISIBLE and CloseButtonState) <> 0 then + begin + R2 := R; + if IsVertical then + begin + R2.Left := R2.Right - Sz + 1; + R.Right := R2.Left; + end + else + begin + R2.Top := R2.Bottom - Sz + 1; + R.Bottom := R2.Top; + end; + + BtnItemState := GetBtnItemState(CloseButtonState); + FrameRectEx(Canvas, R2, BtnItemColors[BtnItemState, ipFrame], True); + FillRectEx(Canvas, R2, BtnItemColors[BtnItemState, ipBody]); + DrawButtonBitmap(Canvas, R2, BtnItemColors[BtnItemState, ipText]); + end; + + + if IsVertical then InflateRect(R, -4, 0) + else InflateRect(R, 0, -4); + Font.Assign(SmCaptionFont); + Font.Color := clBtnText; + Brush.Color := HeaderColor; + Brush.Style := bsSolid; + Flags := DT_SINGLELINE or DT_VCENTER or DT_END_ELLIPSIS or DT_HIDEPREFIX; + if IsVertical then DrawText(Canvas.Handle, Caption, -1, R, Flags) + else DrawRotatedText(Canvas.Handle, string(Caption), R, Flags); + end; +end; + +procedure TTBXOffice2003Theme.SetupColorCache; +var + DC: HDC; + HotBtnFace, DisabledText: TColor; + + procedure Undither(var C: TColor); + begin + if C <> clNone then C := GetNearestColor(DC, ColorToRGB(C)); + end; + +begin + DC := StockCompatibleBitmap.Canvas.Handle; + + // gradColors rmk + gradCol1:= clBtnFace; + gradCol2:= RGB(245, 244, 242); + gradHandle1:= clBtnFace; + gradHandle2:= clGray; + gradHandle3:= clWhite; + gradBL:= RGB(219, 216, 209); //clBtnShadow; + + // alternativ colors why not give it a try! + // Blue + { + gradCol1:= $00FECA9C; + gradCol2:= clWhite; + gradHandle1:= $00FECA9C; + gradHandle2:= clNavy; + gradHandle3:= clWhite; + gradBL:= clNavy; + } + + //Olive + { + gradCol1:= $009CCFCF; + gradCol2:= clWhite; + gradHandle1:= $009CCFCF; + gradHandle2:= clOlive; + gradHandle3:= clWhite; + gradBL:= clOlive; + + // Maybe these are better? + gradCol1:= $00B8DCDC; + gradHandle1:= $00B8DCDC; + } + + // gradColors rmk end + + if TBXLoColor then + begin + { View/Window Colors } + MenubarColor := clBtnFace; + ToolbarColor := clBtnFace; + PopupColor := clWindow; + DockPanelColor := clWindow; + StatusPanelFrameColor := clBtnShadow; + + PopupFrameColor := clBtnText; + WinFrameColors[wfsActive, wfpBorder] := clBtnShadow; + WinFrameColors[wfsActive, wfpCaption] := clBtnShadow; + WinFrameColors[wfsActive, wfpCaptionText] := clBtnHighlight; + WinFrameColors[wfsInactive, wfpBorder] := clBtnShadow; + WinFrameColors[wfsInactive, wfpCaption] := clBtnShadow; + WinFrameColors[wfsInactive, wfpCaptionText] := clBtnHighlight; + + PnlFrameColors[wfsActive, wfpBorder] := clBtnShadow; + PnlFrameColors[wfsActive, wfpCaption] := clBtnFace; + PnlFrameColors[wfsActive, wfpCaptionText] := clBtnText; + PnlFrameColors[wfsInactive, wfpBorder] := clBtnShadow; + PnlFrameColors[wfsInactive, wfpCaption] := clBtnFace; + PnlFrameColors[wfsInactive, wfpCaptionText] := clBtnText; + + MenuItemColors[misNormal, ipBody] := clNone; + MenuItemColors[misNormal, ipText] := clWindowText; + MenuItemColors[misNormal, ipFrame] := clNone; + MenuItemColors[misDisabled, ipBody] := clNone; + MenuItemColors[misDisabled, ipText] := clGrayText; + MenuItemColors[misDisabled, ipFrame] := clNone; + MenuItemColors[misHot, ipBody] := clWindow; + MenuItemColors[misHot, ipText] := clWindowtext; + MenuItemColors[misHot, ipFrame] := clHighlight; + MenuItemColors[misDisabledHot, ipBody] := clWindow; + MenuItemColors[misDisabledHot, ipText] := clGrayText; + MenuItemColors[misDisabledHot, ipFrame] := clHighlight; + + BtnItemColors[bisNormal, ipBody] := clNone; + BtnItemColors[bisNormal, ipText] := clBtnText; + BtnItemColors[bisNormal, ipFrame] := clNone; + BtnItemColors[bisDisabled, ipBody] := clNone; + BtnItemColors[bisDisabled, ipText] := clBtnShadow; + BtnItemColors[bisDisabled, ipFrame] := clNone; + BtnItemColors[bisSelected, ipBody] := clWindow; + BtnItemColors[bisSelected, ipText] := clWindowText; + BtnItemColors[bisSelected, ipFrame] := clHighlight; + BtnItemColors[bisPressed, ipBody] := clHighlight; + BtnItemColors[bisPressed, ipText] := clHighlightText; + BtnItemColors[bisPressed, ipFrame] := clHighlight; + BtnItemColors[bisHot, ipBody] := clWindow; + BtnItemColors[bisHot, ipText] := clWindowText; + BtnItemColors[bisHot, ipFrame] := clHighlight; + BtnItemColors[bisDisabledHot, ipBody] := clWindow; + BtnItemColors[bisDisabledHot, ipText] := clBtnShadow; + BtnItemColors[bisDisabledHot, ipFrame] := clHighlight; + BtnItemColors[bisSelectedHot, ipBody] := clHighlight; + BtnItemColors[bisSelectedHot, ipText] := clHighlightText; + BtnItemColors[bisSelectedHot, ipFrame] := clHighlight; + BtnItemColors[bisPopupParent, ipBody] := clBtnFace; + BtnItemColors[bisPopupParent, ipText] := clBtnText; + BtnItemColors[bisPopupParent, ipFrame] := PopupFrameColor; + + { Other Colors } + DragHandleColor := clBtnText; + IconShadowColor := clBtnFace; + PopupSeparatorColor := RGB(166,166,166); //clBtnShadow; + ToolbarSeparatorColor := RGB(166,166,166); //clBtnShadow; + end + else + begin + { View/Window Colors } + MenubarColor := gradCol1; + ToolbarColor := gradCol2; + PopupColor := Blend(clBtnFace, clWindow, 143); + DockPanelColor := PopupColor; + PopupFrameColor := Blend(clBtnText, clBtnShadow, 20); + SetContrast(PopupFrameColor, PopupColor, 100); + + HotBtnFace := Blend(clHighlight, clWindow, 30); + SetContrast(HotBtnFace, ToolbarColor, 50); + DisabledText := Blend(clBtnshadow, clWindow, 90); + + WinFrameColors[wfsActive, wfpBorder] := Blend(clBtnText, clBtnShadow, 15); + SetContrast(WinFrameColors[wfsActive, wfpBorder], ToolbarColor, 120); + WinFrameColors[wfsActive, wfpCaption] := clBtnShadow; + WinFrameColors[wfsActive, wfpCaptionText] := clBtnHighlight; + SetContrast(WinFrameColors[wfsActive, wfpCaptionText], clBtnShadow, 180); + WinFrameColors[wfsInactive, wfpBorder] := WinFrameColors[wfsActive, wfpBorder]; + WinFrameColors[wfsInactive, wfpCaption] := clBtnFace; + WinFrameColors[wfsInactive, wfpCaptionText] := DisabledText; + SetContrast(WinFrameColors[wfsInactive, wfpCaptionText], clBtnFace, 120); + + PnlFrameColors[wfsActive, wfpBorder] := clBtnShadow; + PnlFrameColors[wfsActive, wfpCaption] := clBtnFace; + PnlFrameColors[wfsActive, wfpCaptionText] := clBtnText; + PnlFrameColors[wfsInactive, wfpBorder] := clBtnShadow; + PnlFrameColors[wfsInactive, wfpCaption] := clBtnFace; + PnlFrameColors[wfsInactive, wfpCaptionText] := DisabledText; + SetContrast(PnlFrameColors[wfsInactive, wfpCaptionText], clBtnFace, 120); + + BtnItemColors[bisNormal, ipBody] := clNone; + BtnItemColors[bisNormal, ipText] := clBtnText; + SetContrast(BtnItemColors[bisNormal, ipText], ToolbarColor, 180); + BtnItemColors[bisNormal, ipFrame] := clNone; + BtnItemColors[bisDisabled, ipBody] := clNone; + BtnItemColors[bisDisabled, ipText] := DisabledText; + SetContrast(BtnItemColors[bisDisabled, ipText], ToolbarColor, 80); + BtnItemColors[bisDisabled, ipFrame] := clNone; + BtnItemColors[bisSelected, ipBody] := Blend(clHighlight, Blend(clBtnFace, clWindow, 50), 10); + SetContrast(BtnItemColors[bisSelected, ipBody], ToolbarColor, 5); + BtnItemColors[bisSelected, ipText] := BtnItemColors[bisNormal, ipText]; + BtnItemColors[bisSelected, ipFrame] := clHighlight; + BtnItemColors[bisPressed, ipBody] := Blend(clHighlight, clWindow, 50); + BtnItemColors[bisPressed, ipText] := clHighlightText; + BtnItemColors[bisPressed, ipFrame] := clHighlight; + BtnItemColors[bisHot, ipBody] := HotBtnFace; + BtnItemColors[bisHot, ipText] := clMenuText; + SetContrast(BtnItemColors[bisHot, ipText], BtnItemColors[bisHot, ipBody], 180); + BtnItemColors[bisHot, ipFrame] := clHighlight; + SetContrast(BtnItemColors[bisHot, ipFrame], ToolbarColor, 100); + BtnItemColors[bisDisabledHot, ipBody] := HotBtnFace; + BtnItemColors[bisDisabledHot, ipText] := DisabledText; + BtnItemColors[bisDisabledHot, ipFrame] := clHighlight; + BtnItemColors[bisSelectedHot, ipBody] := Blend(clHighlight, clWindow, 50); + SetContrast(BtnItemColors[bisSelectedHot, ipBody], ToolbarColor, 30); + BtnItemColors[bisSelectedHot, ipText] := clHighlightText; + SetContrast(BtnItemColors[bisSelectedHot, ipText], BtnItemColors[bisSelectedHot, ipBody], 180); + BtnItemColors[bisSelectedHot, ipFrame] := clHighlight; + SetContrast(BtnItemColors[bisSelectedHot, ipFrame], BtnItemColors[bisSelectedHot, ipBody], 100); + BtnItemColors[bisPopupParent, ipBody] := ToolbarColor; + BtnItemColors[bisPopupParent, ipText] := BtnItemColors[bisNormal, ipText]; + BtnItemColors[bisPopupParent, ipFrame] := PopupFrameColor; + + MenuItemColors[misNormal, ipBody] := clNone; + MenuItemColors[misNormal, ipText] := clWindowText; + SetContrast(MenuItemColors[misNormal, ipText], PopupColor, 180); + + MenuItemColors[misNormal, ipFrame] := clNone; + MenuItemColors[misDisabled, ipBody] := clNone; + MenuItemColors[misDisabled, ipText] := Blend(clGrayText, clWindow, 70); + SetContrast(MenuItemColors[misDisabled, ipText], PopupColor, 80); // 145? + MenuItemColors[misDisabled, ipFrame] := clNone; + + MenuItemColors[misHot, ipBody] := BtnItemColors[bisHot, ipBody]; + MenuItemColors[misHot, ipText] := BtnItemColors[bisHot, ipText]; + MenuItemColors[misHot, ipFrame] := BtnItemColors[bisHot, ipFrame]; + MenuItemColors[misDisabledHot, ipBody] := PopupColor; + MenuItemColors[misDisabledHot, ipText] := Blend(clGrayText, clWindow, 70); + MenuItemColors[misDisabledHot, ipFrame] := clHighlight; + + + DragHandleColor := Blend(clBtnShadow, clWindow, 75); + SetContrast(DragHandleColor, ToolbarColor, 85); + IconShadowColor := Blend(clBlack, HotBtnFace, 25); + ToolbarSeparatorColor := Blend(clBtnShadow, clWindow, 70); + SetContrast(ToolbarSeparatorColor, ToolbarColor, 50); + PopupSeparatorColor := ToolbarSeparatorColor; + StatusPanelFrameColor := Blend(clWindow, clBtnFace, 30); + SetContrast(StatusPanelFrameColor, clBtnFace, 30); + + Undither(MenubarColor); + Undither(ToolbarColor); + Undither(PopupColor); + Undither(DockPanelColor); + Undither(PopupFrameColor); + Undither(WinFrameColors[wfsActive, wfpBorder]); + Undither(WinFrameColors[wfsActive, wfpCaption]); + Undither(WinFrameColors[wfsActive, wfpCaptionText]); + Undither(WinFrameColors[wfsInactive, wfpBorder]); + Undither(WinFrameColors[wfsInactive, wfpCaption]); + Undither(WinFrameColors[wfsInactive, wfpCaptionText]); + Undither(PnlFrameColors[wfsActive, wfpBorder]); + Undither(PnlFrameColors[wfsActive, wfpCaption]); + Undither(PnlFrameColors[wfsActive, wfpCaptionText]); + Undither(PnlFrameColors[wfsInactive, wfpBorder]); + Undither(PnlFrameColors[wfsInactive, wfpCaption]); + Undither(PnlFrameColors[wfsInactive, wfpCaptionText]); + Undither(BtnItemColors[bisNormal, ipBody]); + Undither(BtnItemColors[bisNormal, ipText]); + Undither(BtnItemColors[bisNormal, ipFrame]); + Undither(BtnItemColors[bisDisabled, ipBody]); + Undither(BtnItemColors[bisDisabled, ipText]); + Undither(BtnItemColors[bisDisabled, ipFrame]); + Undither(BtnItemColors[bisSelected, ipBody]); + Undither(BtnItemColors[bisSelected, ipText]); + Undither(BtnItemColors[bisSelected, ipFrame]); + Undither(BtnItemColors[bisPressed, ipBody]); + Undither(BtnItemColors[bisPressed, ipText]); + Undither(BtnItemColors[bisPressed, ipFrame]); + Undither(BtnItemColors[bisHot, ipBody]); + Undither(BtnItemColors[bisHot, ipText]); + Undither(BtnItemColors[bisHot, ipFrame]); + Undither(BtnItemColors[bisDisabledHot, ipBody]); + Undither(BtnItemColors[bisDisabledHot, ipText]); + Undither(BtnItemColors[bisDisabledHot, ipFrame]); + Undither(BtnItemColors[bisSelectedHot, ipBody]); + Undither(BtnItemColors[bisSelectedHot, ipText]); + Undither(BtnItemColors[bisSelectedHot, ipFrame]); + Undither(BtnItemColors[bisPopupParent, ipBody]); + Undither(BtnItemColors[bisPopupParent, ipText]); + Undither(BtnItemColors[bisPopupParent, ipFrame]); + Undither(MenuItemColors[misNormal, ipBody]); + Undither(MenuItemColors[misNormal, ipText]); + Undither(MenuItemColors[misNormal, ipFrame]); + Undither(MenuItemColors[misDisabled, ipBody]); + Undither(MenuItemColors[misDisabled, ipText]); + Undither(MenuItemColors[misDisabled, ipFrame]); + Undither(MenuItemColors[misHot, ipBody]); + Undither(MenuItemColors[misHot, ipText]); + Undither(MenuItemColors[misHot, ipFrame]); + Undither(MenuItemColors[misDisabledHot, ipBody]); + Undither(MenuItemColors[misDisabledHot, ipText]); + Undither(MenuItemColors[misDisabledHot, ipFrame]); + Undither(DragHandleColor); + Undither(IconShadowColor); + Undither(ToolbarSeparatorColor); + Undither(PopupSeparatorColor); + Undither(StatusPanelFrameColor); + end; +end; + +function TTBXOffice2003Theme.GetPopupShadowType: Integer; +begin + Result := PST_OFFICEXP; +end; + +constructor TTBXOffice2003Theme.Create(const AName: string); +begin + inherited; + if CounterLock = 0 then InitializeStock; + Inc(CounterLock); + AddTBXSysChangeNotification(Self); + SetupColorCache; +end; + +destructor TTBXOffice2003Theme.Destroy; +begin + RemoveTBXSysChangeNotification(Self); + Dec(CounterLock); + if CounterLock = 0 then FinalizeStock; + inherited; +end; + +procedure TTBXOffice2003Theme.GetViewMargins(ViewType: Integer; + out Margins: TTBXMargins); +begin + Margins.LeftWidth := 0; + Margins.TopHeight := 0; + Margins.RightWidth := 0; + Margins.BottomHeight := 0; +end; + +procedure TTBXOffice2003Theme.PaintPageScrollButton(Canvas: TCanvas; + const ARect: TRect; ButtonType: Integer; Hot: Boolean); +var + R: TRect; + X, Y, Sz: Integer; +begin + R := ARect; + if Hot then Canvas.Brush.Color := BtnItemColors[bisHot, ipFrame] + else Canvas.Brush.Color := clBtnShadow; + Canvas.FrameRect(R); + if Hot then Canvas.Brush.Color := BtnItemColors[bisHot, ipBody] + else Canvas.Brush.Color := clBtnFace; + InflateRect(R, -1, -1); + Canvas.FillRect(R); + X := (R.Left + R.Right) div 2; + Y := (R.Top + R.Bottom) div 2; + Sz := Min(X - R.Left, Y - R.Top) * 3 div 4; + if Hot then Canvas.Pen.Color := BtnItemColors[bisHot, ipText] + else Canvas.Pen.Color := BtnItemColors[bisNormal, ipText]; + Canvas.Brush.Color := Canvas.Pen.Color; + case ButtonType of + PSBT_UP: + begin + Inc(Y, Sz div 2); + Canvas.Polygon([Point(X + Sz, Y), Point(X, Y - Sz), Point(X - Sz, Y)]); + end; + PSBT_DOWN: + begin + Y := (R.Top + R.Bottom - 1) div 2; + Dec(Y, Sz div 2); + Canvas.Polygon([Point(X + Sz, Y), Point(X, Y + Sz), Point(X - Sz, Y)]); + end; + PSBT_LEFT: + begin + Inc(X, Sz div 2); + Canvas.Polygon([Point(X, Y + Sz), Point(X - Sz, Y), Point(X, Y - Sz)]); + end; + PSBT_RIGHT: + begin + X := (R.Left + R.Right - 1) div 2; + Dec(X, Sz div 2); + Canvas.Polygon([Point(X, Y + Sz), Point(X + Sz, Y), Point(X, Y - Sz)]); + end; + end; +end; + +procedure TTBXOffice2003Theme.PaintGlyph(Canvas: TCanvas; R: TRect; Kind, State: Integer); +var + X, Y: Integer; + + procedure SetupPen; + begin + if Boolean(State and GS_DISABLED) then Canvas.Pen.Color := clBtnShadow + else if Boolean(State and GS_PUSHED) then Canvas.Pen.Color := BtnItemColors[bisPressed, ipFrame] + else if Boolean(State and GS_HOT) then Canvas.Pen.Color := BtnItemColors[bisHot, ipFrame] + else Canvas.Pen.Color := clBtnShadow; + end; + + procedure SetupBrush; + begin + Canvas.Brush.Style := bsSolid; + if Boolean(State and GS_DISABLED) then Canvas.Brush.Style := bsClear + else if Boolean(State and GS_PUSHED) then Canvas.Brush.Color := BtnItemColors[bisPressed, ipBody] + else if Boolean(State and GS_HOT) then Canvas.Brush.Color := BtnItemColors[bisHot, ipBody] + else if Boolean(State and GS_MIXED) then Canvas.Brush.Bitmap := AllocPatternBitmap(clWindow, clBtnFace) + else Canvas.Brush.Style := bsClear; + end; + + function TextColor: TColor; + begin + if Boolean(State and GS_DISABLED) then Result := BtnItemColors[bisDisabled, ipText] + else if Boolean(State and GS_PUSHED) then Result := BtnItemColors[bisPressed, ipText] + else if Boolean(State and GS_MIXED) then Result := clBtnShadow + else if Boolean(State and GS_HOT) then Result := BtnItemColors[bisHot, ipText] + else Result := BtnItemColors[bisNormal, ipText]; + end; + + procedure DiagLine(C: TColor); + begin + with Canvas, R do + begin + Pen.Color := C; + MoveTo(Right - 1 - X, Bottom - 1); LineTo(Right, Bottom - X - 2); + Inc(X); + end; + end; + +begin + with Canvas do case Kind of + GK_CHECKBOX: + begin + SetupPen; + SetupBrush; + InflateRect(R, -1, -1); + with R do Rectangle(Left, Top, Right, Bottom); + Pen.Style := psSolid; + Brush.Style := bsSolid; + + if Boolean(State and (GS_CHECKED or GS_MIXED)) then + begin + X := (R.Left + R.Right) div 2 - 1; + Y := (R.Top + R.Bottom) div 2 + 1; + Pen.Color := TextColor; + Brush.Color := Pen.Color; + Polygon([Point(X-2, Y), Point(X, Y+2), Point(X+4, Y-2), + Point(X+4, Y-4), Point(X, Y), Point(X-2, Y-2), Point(X-2, Y)]); + end; + end; + GK_RADIOBUTTON: + begin + SetupPen; + SetupBrush; + InflateRect(R, -1, -1); + with R do Ellipse(Left, Top, Right, Bottom); + Pen.Style := psSolid; + Brush.Style := bsSolid; + if Boolean(State and GS_CHECKED) then + begin + InflateRect(R, -3, -3); + Pen.Color := TextColor; + Brush.Color := Pen.Color; + with R do Ellipse(Left, Top, Right, Bottom); + end; + end; + end; +end; + +procedure TTBXOffice2003Theme.PaintStatusBar(Canvas: TCanvas; R: TRect; Part: Integer); +var + I, D, Sz: integer; + + procedure DiagLine(C: TColor); + begin + with R do + DrawLineEx(Canvas, Right - 1 - D, Bottom - 1, Right, Bottom - D - 2, C); + Inc(D); + end; + +begin + with Canvas do + case Part of + SBP_BODY: + begin + FillRectEx(Canvas, R, clBtnFace); + end; + SBP_PANE, SBP_LASTPANE: + begin + if Part = SBP_PANE then Dec(R.Right, 2); + FrameRectEx(Canvas, R, StatusPanelFrameColor); + end; + SBP_GRIPPER: + begin + D := 0; + Sz := Min(R.Right - R.Left, R.Bottom - R.Top); + //for I := 1 to 3 do + case Sz of + 0..8: + begin + DiagLine(clBtnShadow); + DiagLine(clBtnHighlight); + DiagLine(clBtnShadow); + DiagLine(clBtnHighlight); + DiagLine(clBtnShadow); + DiagLine(clBtnHighlight); + end; + 9..11: + begin + DiagLine(clBtnFace); + DiagLine(clBtnShadow); + DiagLine(clBtnHighlight); + DiagLine(clBtnFace); + DiagLine(clBtnShadow); + DiagLine(clBtnHighlight); + DiagLine(clBtnFace); + DiagLine(clBtnShadow); + DiagLine(clBtnHighlight); + end; + 12..14: + begin + DiagLine(clBtnShadow); + DiagLine(clBtnShadow); + DiagLine(clBtnHighlight); + DiagLine(clBtnShadow); + DiagLine(clBtnShadow); + DiagLine(clBtnHighlight); + DiagLine(clBtnShadow); + DiagLine(clBtnShadow); + DiagLine(clBtnHighlight); + end; + else + DiagLine(clBtnShadow); + DiagLine(clBtnShadow); + DiagLine(clBtnHighlight); + DiagLine(clBtnFace); + DiagLine(clBtnShadow); + DiagLine(clBtnShadow); + DiagLine(clBtnShadow); + DiagLine(clBtnHighlight); + DiagLine(clBtnFace); + DiagLine(clBtnShadow); + DiagLine(clBtnShadow); + DiagLine(clBtnShadow); + DiagLine(clBtnHighlight); + end; + end; + end; +end; + +procedure TTBXOffice2003Theme.TBXSysCommand(var Message: TMessage); +begin + if Message.WParam = TSC_VIEWCHANGE then SetupColorCache; +end; + +initialization + RegisterTBXTheme('Office2003', TTBXOffice2003Theme); +end. diff --git a/official/2.1.6+2.1.beta1/TBX/TBXOfficeXPTheme.pas b/official/2.1.6+2.1.beta1/TBX/TBXOfficeXPTheme.pas new file mode 100644 index 0000000..d7d6397 --- /dev/null +++ b/official/2.1.6+2.1.beta1/TBX/TBXOfficeXPTheme.pas @@ -0,0 +1,1700 @@ +unit TBXOfficeXPTheme; + +// TBX Package +// Copyright 2001-2004 Alex A. Denisov. All Rights Reserved +// See TBX.chm for license and installation instructions +// +// $Id: TBXOfficeXPTheme.pas 16 2004-05-26 02:02:55Z Alex@ZEISS $ + +interface + +{$I ..\..\Source\TB2Ver.inc} +{$I TBX.inc} + +uses + Windows, Messages, Graphics, TBXThemes, TBXDefaultTheme, ImgList; + +{$DEFINE ALTERNATIVE_DISABLED_STYLE} // remove the asterisk to change appearance of disabled images + +type + TItemPart = (ipBody, ipText, ipFrame); + TBtnItemState = (bisNormal, bisDisabled, bisSelected, bisPressed, bisHot, + bisDisabledHot, bisSelectedHot, bisPopupParent); + TMenuItemState = (misNormal, misDisabled, misHot, misDisabledHot); + TWinFramePart = (wfpBorder, wfpCaption, wfpCaptionText); + TWinFrameState = (wfsActive, wfsInactive); + + TTBXOfficeXPTheme = class(TTBXTheme) + private + procedure TBXSysCommand(var Message: TMessage); message TBX_SYSCOMMAND; + protected + { View/Window Colors } + MenubarColor: TColor; + ToolbarColor: TColor; + PopupColor: TColor; + DockPanelColor: TColor; + PopupFrameColor: TColor; + WinFrameColors: array [TWinFrameState, TWinFramePart] of TColor; + PnlFrameColors: array [TWinFrameState, TWinFramePart] of TColor; + MenuItemColors: array [TMenuItemState, TItemPart] of TColor; + BtnItemColors: array [TBtnItemState, TItemPart] of TColor; + + { Other Colors } + DragHandleColor: TColor; + PopupSeparatorColor: TColor; + ToolbarSeparatorColor: TColor; + IconShadowColor: TColor; + StatusPanelFrameColor: TColor; + + procedure SetupColorCache; virtual; + protected + { Internal Methods } + function GetPartColor(const ItemInfo: TTBXItemInfo; ItemPart: TItemPart): TColor; + function GetBtnColor(const ItemInfo: TTBXItemInfo; ItemPart: TItemPart): TColor; + public + constructor Create(const AName: string); override; + destructor Destroy; override; + + { Metrics access} + function GetBooleanMetrics(Index: Integer): Boolean; override; + function GetIntegerMetrics(Index: Integer): Integer; override; + procedure GetMargins(MarginID: Integer; out Margins: TTBXMargins); override; + function GetImageOffset(Canvas: TCanvas; const ItemInfo: TTBXItemInfo; ImageList: TCustomImageList): TPoint; override; + function GetItemColor(const ItemInfo: TTBXItemInfo): TColor; override; + function GetItemTextColor(const ItemInfo: TTBXItemInfo): TColor; override; + function GetItemImageBackground(const ItemInfo: TTBXItemInfo): TColor; override; + function GetPopupShadowType: Integer; override; + procedure GetViewBorder(ViewType: Integer; out Border: TPoint); override; + function GetViewColor(AViewType: Integer): TColor; override; + procedure GetViewMargins(ViewType: Integer; out Margins: TTBXMargins); override; + + { Painting routines } + procedure PaintBackgnd(Canvas: TCanvas; const ADockRect, ARect, AClipRect: TRect; AColor: TColor; Transparent: Boolean; AViewType: Integer); override; + procedure PaintButton(Canvas: TCanvas; const ARect: TRect; const ItemInfo: TTBXItemInfo); override; + procedure PaintCaption(Canvas: TCanvas; const ARect: TRect; const ItemInfo: TTBXItemInfo; const ACaption: string; AFormat: Cardinal; Rotated: Boolean); override; + procedure PaintCheckMark(Canvas: TCanvas; ARect: TRect; const ItemInfo: TTBXItemInfo); override; + procedure PaintChevron(Canvas: TCanvas; ARect: TRect; const ItemInfo: TTBXItemInfo); override; + procedure PaintDock(Canvas: TCanvas; const ClientRect, DockRect: TRect; DockPosition: Integer); override; + procedure PaintDockPanelNCArea(Canvas: TCanvas; R: TRect; const DockPanelInfo: TTBXDockPanelInfo); override; + procedure PaintDropDownArrow(Canvas: TCanvas; const ARect: TRect; const ItemInfo: TTBXItemInfo); override; + procedure PaintEditButton(Canvas: TCanvas; const ARect: TRect; var ItemInfo: TTBXItemInfo; ButtonInfo: TTBXEditBtnInfo); override; + procedure PaintEditFrame(Canvas: TCanvas; const ARect: TRect; var ItemInfo: TTBXItemInfo; const EditInfo: TTBXEditInfo); override; + procedure PaintFloatingBorder(Canvas: TCanvas; const ARect: TRect; const WindowInfo: TTBXWindowInfo); override; + procedure PaintFrame(Canvas: TCanvas; const ARect: TRect; const ItemInfo: TTBXItemInfo); override; + procedure PaintImage(Canvas: TCanvas; ARect: TRect; const ItemInfo: TTBXItemInfo; ImageList: TCustomImageList; ImageIndex: Integer); override; + procedure PaintMDIButton(Canvas: TCanvas; ARect: TRect; const ItemInfo: TTBXItemInfo; ButtonKind: Cardinal); override; + procedure PaintMenuItem(Canvas: TCanvas; const ARect: TRect; var ItemInfo: TTBXItemInfo); override; + procedure PaintMenuItemFrame(Canvas: TCanvas; const ARect: TRect; const ItemInfo: TTBXItemInfo); override; + procedure PaintPageScrollButton(Canvas: TCanvas; const ARect: TRect; ButtonType: Integer; Hot: Boolean); override; + procedure PaintPopupNCArea(Canvas: TCanvas; R: TRect; const PopupInfo: TTBXPopupInfo); override; + procedure PaintSeparator(Canvas: TCanvas; ARect: TRect; ItemInfo: TTBXItemInfo; Horizontal, LineSeparator: Boolean); override; + procedure PaintToolbarNCArea(Canvas: TCanvas; R: TRect; const ToolbarInfo: TTBXToolbarInfo); override; + procedure PaintFrameControl(Canvas: TCanvas; R: TRect; Kind, State: Integer; Params: Pointer); override; + procedure PaintStatusBar(Canvas: TCanvas; R: TRect; Part: Integer); override; + end; + +implementation + +uses TBXUtils, TB2Common, TB2Item, Classes, Controls, Commctrl, Forms; + +var + StockImgList: TImageList; + CounterLock: Integer; + +procedure InitializeStock; +begin + StockImgList := TImageList.Create(nil); + StockImgList.Handle := ImageList_LoadBitmap(HInstance, 'TBXGLYPHS', 16, 0, clWhite); +end; + +procedure FinalizeStock; +begin + StockImgList.Free; +end; + +{ TTBXOfficeXPTheme } + +function TTBXOfficeXPTheme.GetBooleanMetrics(Index: Integer): Boolean; +begin + case Index of + TMB_OFFICEXPPOPUPALIGNMENT: Result := True; + TMB_EDITMENUFULLSELECT: Result := True; + TMB_EDITHEIGHTEVEN: Result := False; + TMB_SOLIDTOOLBARNCAREA: Result := False; + TMB_SOLIDTOOLBARCLIENTAREA: Result := True; + else + Result := False; + end; +end; + +function TTBXOfficeXPTheme.GetIntegerMetrics(Index: Integer): Integer; +const + DEFAULT = -1; +begin + case Index of + TMI_SPLITBTN_ARROWWIDTH: Result := 12; + + TMI_DROPDOWN_ARROWWIDTH: Result := 8; + TMI_DROPDOWN_ARROWMARGIN: Result := 3; + + TMI_MENU_IMGTEXTSPACE: Result := 5; + TMI_MENU_LCAPTIONMARGIN: Result := 3; + TMI_MENU_RCAPTIONMARGIN: Result := 3; + TMI_MENU_SEPARATORSIZE: Result := 3; + TMI_MENU_MDI_DW: Result := 2; + TMI_MENU_MDI_DH: Result := 2; + + TMI_TLBR_SEPARATORSIZE: Result := 6; + + TMI_EDIT_FRAMEWIDTH: Result := 1; + TMI_EDIT_TEXTMARGINHORZ: Result := 2; + TMI_EDIT_TEXTMARGINVERT: Result := 2; + TMI_EDIT_BTNWIDTH: Result := 14; + TMI_EDIT_MENURIGHTINDENT: Result := 1; + else + Result := DEFAULT; + end; +end; + +function TTBXOfficeXPTheme.GetViewColor(AViewType: Integer): TColor; +begin + Result := clBtnFace; + if (AViewType and VT_TOOLBAR) = VT_TOOLBAR then + begin + if (AViewType and TVT_MENUBAR) = TVT_MENUBAR then Result := MenubarColor + else Result := ToolbarColor; + end + else if (AViewType and VT_POPUP) = VT_POPUP then + begin + if (AViewType and PVT_LISTBOX) = PVT_LISTBOX then Result := clWindow + else Result := PopupColor; + end + else if (AViewType and VT_DOCKPANEL) = VT_DOCKPANEL then Result := DockPanelColor; +end; + +function TTBXOfficeXPTheme.GetBtnColor(const ItemInfo: TTBXItemInfo; ItemPart: TItemPart): TColor; +const + BFlags1: array [Boolean] of TBtnItemState = (bisDisabled, bisDisabledHot); + BFlags2: array [Boolean] of TBtnItemState = (bisSelected, bisSelectedHot); + BFlags3: array [Boolean] of TBtnItemState = (bisNormal, bisHot); +var + B: TBtnItemState; + Embedded: Boolean; +begin + with ItemInfo do + begin + Embedded := (ViewType and VT_TOOLBAR = VT_TOOLBAR) and + (ViewType and TVT_EMBEDDED = TVT_EMBEDDED); + if not Enabled then B := BFlags1[HoverKind = hkKeyboardHover] + else if ItemInfo.IsPopupParent then B := bisPopupParent + else if Pushed then B := bisPressed + else if Selected then B := BFlags2[HoverKind <> hkNone] + else B := BFlags3[HoverKind <> hkNone]; + Result := BtnItemColors[B, ItemPart]; + if Embedded then + begin + if (ItemPart = ipBody) and (Result = clNone) then Result := ToolbarColor; + if ItemPart = ipFrame then + begin + if Selected then Result := clWindowFrame + else if (Result = clNone) then Result := clBtnShadow; + end; + end; + end; +end; + +function TTBXOfficeXPTheme.GetPartColor(const ItemInfo: TTBXItemInfo; ItemPart: TItemPart): TColor; +const + MFlags1: array [Boolean] of TMenuItemState = (misDisabled, misDisabledHot); + MFlags2: array [Boolean] of TMenuItemState = (misNormal, misHot); + BFlags1: array [Boolean] of TBtnItemState = (bisDisabled, bisDisabledHot); + BFlags2: array [Boolean] of TBtnItemState = (bisSelected, bisSelectedHot); + BFlags3: array [Boolean] of TBtnItemState = (bisNormal, bisHot); +var + IsMenuItem, Embedded: Boolean; + M: TMenuItemState; + B: TBtnItemState; +begin + with ItemInfo do + begin + IsMenuItem := ((ViewType and PVT_POPUPMENU) = PVT_POPUPMENU) and + ((ItemOptions and IO_TOOLBARSTYLE) = 0); + Embedded := ((ViewType and VT_TOOLBAR) = VT_TOOLBAR) and + ((ViewType and TVT_EMBEDDED) = TVT_EMBEDDED); + if IsMenuItem then + begin + if not Enabled then M := MFlags1[HoverKind = hkKeyboardHover] + else M := MFlags2[HoverKind <> hkNone]; + Result := MenuItemColors[M, ItemPart]; + end + else + begin + if not Enabled then B := BFlags1[HoverKind = hkKeyboardHover] + else if ItemInfo.IsPopupParent then B := bisPopupParent + else if Pushed then B := bisPressed + else if Selected then B := BFlags2[HoverKind <> hkNone] + else B := BFlags3[HoverKind <> hkNone]; + Result := BtnItemColors[B, ItemPart]; + if Embedded and (Result = clNone) then + begin + if ItemPart = ipBody then Result := ToolbarColor; + if ItemPart = ipFrame then Result := clBtnShadow; + end; + end; + end; +end; + +function TTBXOfficeXPTheme.GetItemColor(const ItemInfo: TTBXItemInfo): TColor; +begin + Result := GetPartColor(ItemInfo, ipBody); + if Result = clNone then Result := GetViewColor(ItemInfo.ViewType); +end; + +function TTBXOfficeXPTheme.GetItemTextColor(const ItemInfo: TTBXItemInfo): TColor; +begin + Result := GetPartColor(ItemInfo, ipText); +end; + +function TTBXOfficeXPTheme.GetItemImageBackground(const ItemInfo: TTBXItemInfo): TColor; +begin + Result := GetBtnColor(ItemInfo, ipBody); + if Result = clNone then Result := GetViewColor(ItemInfo.ViewType); +end; + +procedure TTBXOfficeXPTheme.GetViewBorder(ViewType: Integer; out Border: TPoint); +const + XMetrics: array [Boolean] of Integer = (SM_CXDLGFRAME, SM_CXFRAME); + YMetrics: array [Boolean] of Integer = (SM_CYDLGFRAME, SM_CYFRAME); +var + Resizable: Boolean; + + procedure SetBorder(X, Y: Integer); + begin + Border.X := X; + Border.Y := Y; + end; + +begin + if (ViewType and VT_TOOLBAR) = VT_TOOLBAR then + begin + if (ViewType and TVT_FLOATING) = TVT_FLOATING then + begin + Resizable := (ViewType and TVT_RESIZABLE) = TVT_RESIZABLE; + Border.X := GetSystemMetrics(XMetrics[Resizable]) - 1; + Border.Y := GetSystemMetrics(YMetrics[Resizable]) - 1; + end + else SetBorder(2, 2); + end + else if (ViewType and VT_POPUP) = VT_POPUP then + begin + if (ViewType and PVT_POPUPMENU) = PVT_POPUPMENU then Border.X := 1 + else Border.X := 2; + Border.Y := 2; + end + else if (ViewType and VT_DOCKPANEL) = VT_DOCKPANEL then + begin + if (ViewType and DPVT_FLOATING) = DPVT_FLOATING then + begin + Resizable := (ViewType and DPVT_RESIZABLE) = DPVT_RESIZABLE; + Border.X := GetSystemMetrics(XMetrics[Resizable]) - 1; + Border.Y := GetSystemMetrics(YMetrics[Resizable]) - 1; + end + else SetBorder(2, 2); + end + else SetBorder(0, 0); +end; + +procedure TTBXOfficeXPTheme.GetMargins(MarginID: Integer; out Margins: TTBXMargins); +begin + with Margins do + case MarginID of + MID_TOOLBARITEM: + begin + LeftWidth := 2; RightWidth := 2; + TopHeight := 2; BottomHeight := 2; + end; + + MID_MENUITEM: + begin + LeftWidth := 1; RightWidth := 1; + TopHeight := 3; BottomHeight := 3; + end; + + MID_STATUSPANE: + begin + LeftWidth := 1; RightWidth := 3; + TopHeight := 1; BottomHeight := 1; + end; + else + LeftWidth := 0; + RightWidth := 0; + TopHeight := 0; + BottomHeight := 0; + end; +end; + +procedure TTBXOfficeXPTheme.PaintBackgnd(Canvas: TCanvas; const ADockRect, ARect, AClipRect: TRect; + AColor: TColor; Transparent: Boolean; AViewType: Integer); +var + DC: HDC; + R: TRect; +begin + DC := Canvas.Handle; + if not Transparent then + begin + IntersectRect(R, ARect, AClipRect); + FillRectEx(DC, R, AColor); + end; +end; + +procedure TTBXOfficeXPTheme.PaintCaption(Canvas: TCanvas; + const ARect: TRect; const ItemInfo: TTBXItemInfo; const ACaption: string; + AFormat: Cardinal; Rotated: Boolean); +var + R: TRect; +begin + with ItemInfo, Canvas do + begin + R := ARect; + Brush.Style := bsClear; + if Font.Color = clNone then Font.Color := GetPartColor(ItemInfo, ipText); + if not Rotated then Windows.DrawText(Handle, PChar(ACaption), Length(ACaption), R, AFormat) + else DrawRotatedText(Handle, ACaption, R, AFormat); + Brush.Style := bsSolid; + end; +end; + +procedure TTBXOfficeXPTheme.PaintCheckMark(Canvas: TCanvas; ARect: TRect; const ItemInfo: TTBXItemInfo); +var + DC: HDC; + X, Y: Integer; + C: TColor; +begin + DC := Canvas.Handle; + X := (ARect.Left + ARect.Right) div 2 - 1; + Y := (ARect.Top + ARect.Bottom) div 2 + 1; + C := GetBtnColor(ItemInfo, ipText); + if ItemInfo.ItemOptions and IO_RADIO > 0 then + begin + RoundRectEx(DC, X-2, Y-4, X+4, Y+2, 2, 2, + MixColors(C, ToolbarColor, 200), clNone); + RoundRectEx(DC, X-2, Y-4, X+4, Y+2, 6, 6, C, C); + end + else + PolylineEx(DC, [Point(X-2, Y-2), Point(X, Y), Point(X+4, Y-4), + Point(X+4, Y-3), Point(X, Y+1), Point(X-2, Y-1), Point(X-2, Y-2)], C); +end; + +procedure TTBXOfficeXPTheme.PaintChevron(Canvas: TCanvas; ARect: TRect; const ItemInfo: TTBXItemInfo); +const + Pattern: array[Boolean, 0..15] of Byte = ( + ($CC, 0, $66, 0, $33, 0, $66, 0, $CC, 0, 0, 0, 0, 0, 0, 0), + ($88, 0, $D8, 0, $70, 0, $20, 0, $88, 0, $D8, 0, $70, 0, $20, 0)); +var + R2: TRect; + W, H: Integer; +begin + R2 := ARect; + PaintButton(Canvas, ARect, ItemInfo); + if not ItemInfo.IsVertical then + begin + Inc(R2.Top, 4); + R2.Bottom := R2.Top + 5; + W := 8; + H := 5; + end + else + begin + R2.Left := R2.Right - 9; + R2.Right := R2.Left + 5; + W := 5; + H := 8; + end; + DrawGlyph(Canvas.Handle, R2, W, H, Pattern[ItemInfo.IsVertical][0], GetPartColor(ItemInfo, ipText)); +end; + +procedure TTBXOfficeXPTheme.PaintEditButton(Canvas: TCanvas; const ARect: TRect; + var ItemInfo: TTBXItemInfo; ButtonInfo: TTBXEditBtnInfo); +var + DC: HDC; + BtnDisabled, BtnHot, BtnPressed, Embedded: Boolean; + R, BR: TRect; + X, Y: Integer; + SaveItemInfoPushed: Boolean; + C: TColor; +begin + DC := Canvas.Handle; + R := ARect; + Embedded := ((ItemInfo.ViewType and VT_TOOLBAR) = VT_TOOLBAR) and + ((ItemInfo.ViewType and TVT_EMBEDDED) = TVT_EMBEDDED); + + InflateRect(R, 1, 1); + Inc(R.Left); + with Canvas do + if ButtonInfo.ButtonType = EBT_DROPDOWN then + begin + BtnDisabled := (ButtonInfo.ButtonState and EBDS_DISABLED) <> 0; + BtnHot := (ButtonInfo.ButtonState and EBDS_HOT) <> 0; + BtnPressed := (ButtonInfo.ButtonState and EBDS_PRESSED) <> 0; + if not BtnDisabled then + begin + if BtnPressed or BtnHot or Embedded then PaintButton(Canvas, R, ItemInfo) + else if (ItemInfo.ViewType and VT_TOOLBAR) = VT_TOOLBAR then + begin + R := ARect; + if not Embedded then + begin + FrameRectEx(DC, R, clWindow, False); + C := clWindow; + end + else C := GetBtnColor(ItemInfo, ipFrame); + DrawLineEx(DC, R.Left - 1, R.Top, R.Left - 1, R.Bottom, C); + end; + end; + PaintDropDownArrow(Canvas, R, ItemInfo); + end + else if ButtonInfo.ButtonType = EBT_SPIN then + begin + BtnDisabled := (ButtonInfo.ButtonState and EBSS_DISABLED) <> 0; + BtnHot := (ButtonInfo.ButtonState and EBSS_HOT) <> 0; + + { Upper button } + BR := R; + BR.Bottom := (R.Top + R.Bottom + 1) div 2; + BtnPressed := (ButtonInfo.ButtonState and EBSS_UP) <> 0; + SaveItemInfoPushed := ItemInfo.Pushed; + ItemInfo.Pushed := BtnPressed; + if not BtnDisabled then + begin + if BtnPressed or BtnHot or Embedded then PaintButton(Canvas, BR, ItemInfo) + else if (ItemInfo.ViewType and VT_TOOLBAR) = VT_TOOLBAR then + begin + BR.Left := ARect.Left; BR.Top := ARect.Top; BR.Right := ARect.Right; + if not Embedded then + begin + FrameRectEx(DC, BR, clWindow, False); + C := clWindow; + end + else C := GetBtnColor(ItemInfo, ipFrame); + DrawLineEx(DC, BR.Left - 1, BR.Top, BR.Left - 1, BR.Bottom, C); + end; + end; + X := (BR.Left + BR.Right) div 2; + Y := (BR.Top + BR.Bottom - 1) div 2; + Pen.Color := GetPartColor(ItemInfo, ipText); + Brush.Color := Pen.Color; + Polygon([Point(X - 2, Y + 1), Point(X + 2, Y + 1), Point(X, Y - 1)]); + + { Lower button } + BR := R; + BR.Top := (R.Top + R.Bottom) div 2; + BtnPressed := (ButtonInfo.ButtonState and EBSS_DOWN) <> 0; + ItemInfo.Pushed := BtnPressed; + if not BtnDisabled then + begin + if BtnPressed or BtnHot or Embedded then PaintButton(Canvas, BR, ItemInfo) + else if (ItemInfo.ViewType and VT_TOOLBAR) = VT_TOOLBAR then + begin + BR.Left := ARect.Left; BR.Bottom := ARect.Bottom; BR.Right := ARect.Right; + if not Embedded then + begin + FrameRectEx(DC, BR, clWindow, False); + C := clWindow; + end + else C := GetBtnColor(ItemInfo, ipFrame); + DrawLineEx(DC, BR.Left - 1, BR.Top, BR.Left - 1, BR.Bottom, C); + end; + end; + X := (BR.Left + BR.Right) div 2; + Y := (BR.Top + BR.Bottom) div 2; + C := GetPartColor(ItemInfo, ipText); + PolygonEx(DC, [Point(X - 2, Y - 1), Point(X + 2, Y - 1), Point(X, Y + 1)], C, C); + + ItemInfo.Pushed := SaveItemInfoPushed; + end; +end; + +procedure TTBXOfficeXPTheme.PaintEditFrame(Canvas: TCanvas; + const ARect: TRect; var ItemInfo: TTBXItemInfo; const EditInfo: TTBXEditInfo); +var + DC: HDC; + R: TRect; + W: Integer; + Embedded: Boolean; +begin + DC := Canvas.Handle; + R := ARect; + PaintFrame(Canvas, R, ItemInfo); + W := EditFrameWidth; + InflateRect(R, -W, -W); + Embedded := ((ItemInfo.ViewType and VT_TOOLBAR) = VT_TOOLBAR) and + ((ItemInfo.ViewType and TVT_EMBEDDED) = TVT_EMBEDDED); + if not (ItemInfo.Enabled or Embedded) then + FrameRectEx(DC, R, BtnItemColors[bisDisabled, ipText], False); + + with EditInfo do if RightBtnWidth > 0 then Dec(R.Right, RightBtnWidth - 2); + + if ItemInfo.Enabled then + begin + if ((ItemInfo.ViewType and VT_TOOLBAR) <> VT_TOOLBAR) and (GetPartColor(ItemInfo, ipFrame) = clNone) then + FrameRectEx(DC, R, ToolbarColor, False) + else + FrameRectEx(DC, R, clWindow, False); + + InflateRect(R, -1, -1); + FillRectEx(DC, R, clWindow); + if ((ItemInfo.ViewType and VT_TOOLBAR) <> VT_TOOLBAR) and (GetPartColor(ItemInfo, ipFrame) = clNone) then + begin + R := ARect; + InflateRect(R, -1, -1); + FrameRectEx(DC, R, ToolbarColor, False); + end; + end + else InflateRect(R, -1, -1); + + with EditInfo do if LeftBtnWidth > 0 then Inc(R.Left, LeftBtnWidth - 2); + + if EditInfo.RightBtnWidth > 0 then + begin + R := ARect; + InflateRect(R, -W, -W); + R.Left := R.Right - EditInfo.RightBtnWidth; + PaintEditButton(Canvas, R, ItemInfo, EditInfo.RightBtnInfo); + end; +end; + +procedure TTBXOfficeXPTheme.PaintDropDownArrow(Canvas: TCanvas; + const ARect: TRect; const ItemInfo: TTBXItemInfo); +var + X, Y: Integer; +begin + with ARect, Canvas do + begin + X := (Left + Right) div 2; + Y := (Top + Bottom) div 2 - 1; + Pen.Color := GetPartColor(ItemInfo, ipText); + Brush.Color := Pen.Color; + if ItemInfo.IsVertical then Polygon([Point(X, Y + 2), Point(X, Y - 2), Point(X - 2, Y)]) + else Polygon([Point(X - 2, Y), Point(X + 2, Y), Point(X, Y + 2)]); + end; +end; + +procedure TTBXOfficeXPTheme.PaintButton(Canvas: TCanvas; const ARect: TRect; const ItemInfo: TTBXItemInfo); +var + DC: HDC; + R: TRect; +begin + DC := Canvas.Handle; + with ItemInfo do + begin + R := ARect; + if ((ItemOptions and IO_DESIGNING) <> 0) and not Selected then + begin + if ComboPart = cpSplitRight then Dec(R.Left); + FrameRectEx(DC, R, GetNearestColor(DC, MixColors(clBtnShadow, clBtnFace, 100)), False); + end + else + begin + FrameRectEx(DC, R, GetBtnColor(ItemInfo, ipFrame), True); + if (ComboPart = cpSplitLeft) and IsPopupParent then Inc(R.Right); + if ComboPart = cpSplitRight then Dec(R.Left); + FillRectEx(DC, R, GetBtnColor(ItemInfo, ipBody)); + end; + if ComboPart = cpSplitRight then PaintDropDownArrow(Canvas, R, ItemInfo); + end; +end; + +procedure TTBXOfficeXPTheme.PaintFloatingBorder(Canvas: TCanvas; const ARect: TRect; + const WindowInfo: TTBXWindowInfo); +const + WinStates: array [Boolean] of TWinFramestate = (wfsInactive, wfsActive); + + function GetBtnItemState(BtnState: Integer): TBtnItemState; + begin + if not WindowInfo.Active then Result := bisDisabled + else if (BtnState and CDBS_PRESSED) <> 0 then Result := bisPressed + else if (BtnState and CDBS_HOT) <> 0 then Result := bisHot + else Result := bisNormal; + end; + +var + WinState: TWinFrameState; + BtnItemState: TBtnItemState; + SaveIndex, X, Y: Integer; + Sz: TPoint; + R: TRect; + BodyColor, CaptionColor, CaptionText: TColor; + IsDockPanel: Boolean; +begin + with Canvas do + begin + WinState := WinStates[WindowInfo.Active]; + IsDockPanel := (WindowInfo.ViewType and VT_DOCKPANEL) = VT_DOCKPANEL; + BodyColor := Brush.Color; + + if (WRP_BORDER and WindowInfo.RedrawPart) <> 0 then + begin + R := ARect; + + if not IsDockPanel then Brush.Color := WinFrameColors[WinState, wfpBorder] + else Brush.Color := PnlFrameColors[WinState, wfpBorder]; + + SaveIndex := SaveDC(Canvas.Handle); + Sz := WindowInfo.FloatingBorderSize; + with R, Sz do ExcludeClipRect(Canvas.Handle, Left + X, Top + Y, Right - X, Bottom - Y); + FillRect(R); + RestoreDC(Canvas.Handle, SaveIndex); + InflateRect(R, -Sz.X, -Sz.Y); + Pen.Color := BodyColor; + with R do + if not IsDockPanel then + Canvas.Polyline([ + Point(Left, Top - 1), Point(Right - 1, Top - 1), + Point(Right, Top), Point(Right, Bottom - 1), + Point(Right - 1, Bottom), + Point(Left, Bottom), Point(Left - 1, Bottom - 1), + Point(Left - 1, Top), Point(Left, Top - 1) + ]) + else + Canvas.Polyline([ + Point(Left, Top - 1), Point(Right - 1, Top - 1), + Point(Right, Top), Point(Right, Bottom), + Point(Left - 1, Bottom), + Point(Left - 1, Top), Point(Left, Top - 1) + ]); + end; + + if not WindowInfo.ShowCaption then Exit; + + if (WindowInfo.ViewType and VT_TOOLBAR) = VT_TOOLBAR then + begin + CaptionColor := WinFrameColors[WinState, wfpCaption]; + CaptionText := WinFrameColors[WinState, wfpCaptionText]; + end + else + begin + CaptionColor := PnlFrameColors[WinState, wfpCaption]; + CaptionText := PnlFrameColors[WinState, wfpCaptionText]; + end; + + { Caption } + if (WRP_CAPTION and WindowInfo.RedrawPart) <> 0 then + begin + R := Rect(0, 0, WindowInfo.ClientWidth, GetSystemMetrics(SM_CYSMCAPTION) - 1); + with WindowInfo.FloatingBorderSize do OffsetRect(R, X, Y); + DrawLineEx(Canvas.Handle, R.Left, R.Bottom, R.Right, R.Bottom, BodyColor); + + if ((CDBS_VISIBLE and WindowInfo.CloseButtonState) <> 0) and + ((WRP_CLOSEBTN and WindowInfo.RedrawPart) <> 0) then + Dec(R.Right, GetSystemMetrics(SM_CYSMCAPTION) - 1); + + Brush.Color := CaptionColor; + FillRect(R); + InflateRect(R, -2, 0); + Font.Assign(SmCaptionFont); + Font.Color := CaptionText; + DrawText(Canvas.Handle, WindowInfo.Caption, -1, R, + DT_SINGLELINE or DT_VCENTER or DT_END_ELLIPSIS or DT_NOPREFIX); + end; + + { Close button } + if (CDBS_VISIBLE and WindowInfo.CloseButtonState) <> 0 then + begin + R := Rect(0, 0, WindowInfo.ClientWidth, GetSystemMetrics(SM_CYSMCAPTION) - 1); + with WindowInfo.FloatingBorderSize do OffsetRect(R, X, Y); + R.Left := R.Right - (R.Bottom - R.Top); + DrawLineEx(Canvas.Handle, R.Left - 1, R.Bottom, R.Right, R.Bottom, BodyColor); + Brush.Color := CaptionColor; + FillRect(R); + with R do + begin + X := (Left + Right - StockImgList.Width + 1) div 2; + Y := (Top + Bottom - StockImgList.Height) div 2; + end; + BtnItemState := GetBtnItemState(WindowInfo.CloseButtonState); + FrameRectEx(Canvas.Handle, R, BtnItemColors[BtnItemState, ipFrame], True); + if FillRectEx(Canvas.Handle, R, BtnItemColors[BtnItemState, ipBody]) then + DrawGlyph(Canvas.Handle, X, Y, StockImgList, 0, BtnItemColors[BtnItemState, ipText]) + else + DrawGlyph(Canvas.Handle, X, Y, StockImgList, 0, CaptionText); + end; + end; +end; + +procedure TTBXOfficeXPTheme.PaintFrame(Canvas: TCanvas; const ARect: TRect; + const ItemInfo: TTBXItemInfo); +var + DC: HDC; + R: TRect; +begin + DC := Canvas.Handle; + R := ARect; + FrameRectEx(DC, R, GetPartColor(ItemInfo, ipFrame), True); + FillRectEx(DC, R, GetPartColor(ItemInfo, ipBody)); +end; + +function TTBXOfficeXPTheme.GetImageOffset(Canvas: TCanvas; + const ItemInfo: TTBXItemInfo; ImageList: TCustomImageList): TPoint; +begin + Result.X := 0; + if not (ImageList is TTBCustomImageList) then + with ItemInfo do + if Enabled and (HoverKind <> hkNone) and + not (Selected or Pushed and not IsPopupParent) then + Result.X := -1; + Result.Y := Result.X +end; + +procedure TTBXOfficeXPTheme.PaintImage(Canvas: TCanvas; ARect: TRect; + const ItemInfo: TTBXItemInfo; ImageList: TCustomImageList; ImageIndex: Integer); +var + HiContrast: Boolean; +begin + with ItemInfo do + begin + if ImageList is TTBCustomImageList then + begin + TTBCustomImageList(ImageList).DrawState(Canvas, ARect.Left, ARect.Top, + ImageIndex, Enabled, (HoverKind <> hkNone), Selected); + Exit; + end; + +{$IFNDEF ALTERNATIVE_DISABLED_STYLE} + HiContrast := IsDarkColor(GetItemImageBackground(ItemInfo), 64); + + if not Enabled then + begin + DrawTBXIconFlatShadow(Canvas, ARect, ImageList, ImageIndex, + BtnItemColors[bisDisabled, ipText]); + end + else if Selected or Pushed or (HoverKind <> hkNone) then + begin + if not (Selected or Pushed and not IsPopupParent) then + begin + OffsetRect(ARect, 1, 1); + DrawTBXIconFullShadow(Canvas, ARect, ImageList, ImageIndex, IconShadowColor); + OffsetRect(ARect, -2, -2); + end; + DrawTBXIcon(Canvas, ARect, ImageList, ImageIndex, HiContrast); + end + else if HiContrast or TBXHiContrast or TBXLoColor then + DrawTBXIcon(Canvas, ARect, ImageList, ImageIndex, HiContrast) + else + HighlightTBXIcon(Canvas, ARect, ImageList, ImageIndex, clWindow, 178); +{$ELSE} + HiContrast := ColorIntensity(GetItemImageBackground(ItemInfo)) < 80; + if not Enabled then + begin + if not HiContrast then + DrawTBXIconShadow(Canvas, ARect, ImageList, ImageIndex, 0) + else + DrawTBXIconFlatShadow(Canvas, ARect, ImageList, ImageIndex, clBtnShadow); + end + else if Selected or Pushed or (HoverKind <> hkNone) then + begin + if not (Selected or Pushed and not IsPopupParent) then + begin + DrawTBXIconShadow(Canvas, ARect, ImageList, ImageIndex, 1); + OffsetRect(ARect, 1, 1); + DrawTBXIconShadow(Canvas, ARect, ImageList, ImageIndex, 1); + OffsetRect(ARect, -2, -2); + end; + DrawTBXIcon(Canvas, ARect, ImageList, ImageIndex, HiContrast); + end + else if HiContrast or TBXHiContrast or TBXLoColor then + DrawTBXIcon(Canvas, ARect, ImageList, ImageIndex, HiContrast) + else + HighlightTBXIcon(Canvas, ARect, ImageList, ImageIndex, clWindow, 178); +{$ENDIF} + end; +end; + +procedure TTBXOfficeXPTheme.PaintMDIButton(Canvas: TCanvas; ARect: TRect; + const ItemInfo: TTBXItemInfo; ButtonKind: Cardinal); +var + Index: Integer; +begin + PaintButton(Canvas, ARect, ItemInfo); + Dec(ARect.Bottom); + case ButtonKind of + DFCS_CAPTIONMIN: Index := 2; + DFCS_CAPTIONRESTORE: Index := 3; + DFCS_CAPTIONCLOSE: Index := 0; + else + Exit; + end; + DrawGlyph(Canvas.Handle, ARect, StockImgList, Index, GetPartColor(ItemInfo, ipText)); +end; + +procedure TTBXOfficeXPTheme.PaintMenuItemFrame(Canvas: TCanvas; + const ARect: TRect; const ItemInfo: TTBXItemInfo); +var + R: TRect; +begin + R := ARect; + if (ItemInfo.ViewType and PVT_TOOLBOX) <> PVT_TOOLBOX then with Canvas do + begin + R.Right := R.Left + ItemInfo.PopupMargin + 2; + Brush.Color := ToolbarColor; + FillRect(R); + Inc(R.Left); + R.Right := ARect.Right - 1; + end; + PaintFrame(Canvas, R, ItemInfo); +end; + +procedure TTBXOfficeXPTheme.PaintMenuItem(Canvas: TCanvas; const ARect: TRect; var ItemInfo: TTBXItemInfo); +var + DC: HDC; + R: TRect; + X, Y: Integer; + ArrowWidth: Integer; + C, ClrText: TColor; +begin + DC := Canvas.Handle; + with ItemInfo do + begin + ArrowWidth := GetSystemMetrics(SM_CXMENUCHECK); + PaintMenuItemFrame(Canvas, ARect, ItemInfo); + ClrText := GetPartColor(ItemInfo, ipText); + R := ARect; + + if (ItemOptions and IO_COMBO) <> 0 then + begin + X := R.Right - ArrowWidth - 1; + if not ItemInfo.Enabled then C := ClrText + else if HoverKind = hkMouseHover then C := GetPartColor(ItemInfo, ipFrame) + else C := PopupSeparatorColor; + DrawLineEx(DC, X, R.Top + 1, X, R.Bottom - 1, C); + end; + + if (ItemOptions and IO_SUBMENUITEM) <> 0 then + begin + Y := ARect.Bottom div 2; + X := ARect.Right - ArrowWidth * 2 div 3 - 1; + PolygonEx(DC, [Point(X, Y - 3), Point(X, Y + 3), Point(X + 3, Y)], ClrText, ClrText); + end; + + if Selected and Enabled then + begin + R := ARect; + R.Left := ARect.Left + 1; + R.Right := R.Left + ItemInfo.PopupMargin; + InflateRect(R, -1, -1); + FrameRectEx(DC, R, GetBtnColor(ItemInfo, ipFrame), True); + FillRectEx(DC, R, GetBtnColor(ItemInfo, ipBody)); + end; + end; +end; + +procedure TTBXOfficeXPTheme.PaintPopupNCArea(Canvas: TCanvas; R: TRect; const PopupInfo: TTBXPopupInfo); +var + PR: TRect; +begin + with Canvas do + begin + Brush.Color := PopupFrameColor; + FrameRect(R); + InflateRect(R, -1, -1); + Brush.Color := PopupColor; + FillRect(R); + + if not IsRectEmpty(PopupInfo.ParentRect) then + begin + PR := PopupInfo.ParentRect; + if not IsRectEmpty(PR) then with PR do + begin + Pen.Color := ToolbarColor; + if Bottom = R.Top then + begin + if Left <= R.Left then Left := R.Left - 1; + if Right >= R.Right then Right := R.Right + 1; + MoveTo(Left + 1, Bottom - 1); LineTo(Right - 1, Bottom- 1); + end + else if Top = R.Bottom then + begin + if Left <= R.Left then Left := R.Left - 1; + if Right >= R.Right then Right := R.Right + 1; + MoveTo(Left + 1, Top); LineTo(Right - 1, Top); + end; + if Right = R.Left then + begin + if Top <= R.Top then Top := R.Top - 1; + if Bottom >= R.Bottom then Bottom := R.Bottom + 1; + MoveTo(Right - 1, Top + 1); LineTo(Right - 1, Bottom - 1); + end + else if Left = R.Right then + begin + if Top <= R.Top then Top := R.Top - 1; + if Bottom >= R.Bottom then Bottom := R.Bottom + 1; + MoveTo(Left, Top + 1); LineTo(Left, Bottom - 1); + end; + end; + end; + end; +end; + +procedure TTBXOfficeXPTheme.PaintSeparator(Canvas: TCanvas; ARect: TRect; + ItemInfo: TTBXItemInfo; Horizontal, LineSeparator: Boolean); +var + DC: HDC; + IsToolbox: Boolean; + R: TRect; + C: TColor; +begin + { Note: for blank separators, Enabled = False } + DC := Canvas.Handle; + with ItemInfo, ARect do + begin + if Horizontal then + begin + IsToolbox := (ViewType and PVT_TOOLBOX) = PVT_TOOLBOX; + if ((ItemOptions and IO_TOOLBARSTYLE) = 0) and not IsToolBox then + begin + R := ARect; + R.Right := ItemInfo.PopupMargin + 2; + FillRectEx(DC, R, ToolbarColor); + Inc(Left, ItemInfo.PopupMargin + 9); + C := PopupSeparatorColor; + end + else + C := ToolbarSeparatorColor; + Top := (Top + Bottom) div 2; + if Enabled then DrawLineEx(DC, Left, Top, Right, Top, C); + end + else if Enabled then + begin + Left := (Left + Right) div 2; + DrawLineEx(DC, Left, Top, Left, Bottom, ToolbarSeparatorColor); + end; + end; +end; + +procedure DrawButtonBitmap(DC: HDC; R: TRect; Color: TColor); +const +{$IFNDEF SMALL_CLOSE_BUTTON} + Pattern: array [0..15] of Byte = + ($C3, 0, $66, 0, $3C, 0, $18, 0, $3C, 0, $66, 0, $C3, 0, 0, 0); +{$ELSE} + Pattern: array [0..15] of Byte = + (0, 0, $63, 0, $36, 0, $1C, 0, $1C, 0, $36, 0, $63, 0, 0, 0); +{$ENDIF} +begin + DrawGlyph(DC, R, 8, 7, Pattern[0], Color); +end; + +procedure TTBXOfficeXPTheme.PaintToolbarNCArea(Canvas: TCanvas; R: TRect; const ToolbarInfo: TTBXToolbarInfo); +const + DragHandleOffsets: array [Boolean, DHS_DOUBLE..DHS_SINGLE] of Integer = ((2, 0, 1), (5, 0, 5)); + + function GetBtnItemState(BtnState: Integer): TBtnItemState; + begin + if (BtnState and CDBS_PRESSED) <> 0 then Result := bisPressed + else if (BtnState and CDBS_HOT) <> 0 then Result := bisHot + else Result := bisNormal; + end; + +var + DC: HDC; + Sz: Integer; + R2: TRect; + SaveColor: TColor; + SaveStyle: TBrushStyle; + I: Integer; + BtnVisible, Horz: Boolean; + BtnItemState: TBtnItemState; +begin + DC := Canvas.Handle; + with Canvas do + begin + SaveColor := Brush.Color; + SaveStyle := Brush.Style; + if ToolbarInfo.BorderStyle = bsSingle then + begin + I := ColorIntensity(clBtnFace); + if not (TBXLoColor or not (I in [50..254])) or + ((ToolbarInfo.ViewType and TVT_MENUBAR) = TVT_MENUBAR) then + begin + InflateRect(R, -1, -1); + Dec(R.Right); Dec(R.Bottom); + Pen.Color := SaveColor; + Pen.Style := psSolid; + Brush.Color := SaveColor; + Brush.Style := SaveStyle; // should be either bsSolid or bsClear + with R do + Polygon([Point(Left + 1, Top), Point(Right - 1, Top), Point(Right, Top + 1), + Point(Right, Bottom - 1), Point(Right - 1, Bottom), Point(Left + 1, Bottom), + Point(Left, Bottom - 1), Point(Left, Top + 1)]); + Brush.Style := bsSolid; + Inc(R.Left); + Inc(R.Top); + end + else + begin + Brush.Bitmap := AllocPatternBitmap(ToolbarColor, BtnItemColors[bisDisabled, ipText]); + with R do + begin + FillRect(Rect(Left + 1, Top, Right - 1, Top + 1)); + FillRect(Rect(Left + 1, Bottom - 1, Right - 1, Bottom)); + FillRect(Rect(Left, Top + 1, Left + 1, Bottom - 1)); + FillRect(Rect(Right - 1, Top + 1, Right, Bottom - 1)); + end; + InflateRect(R, -1, -1); + Brush.Color := SaveColor; + FillRect(R); + end; + end + else + InflateRect(R, -1, -1); + InflateRect(R, -1, -1); + + if not ToolbarInfo.AllowDrag then Exit; + + BtnVisible := (ToolbarInfo.CloseButtonState and CDBS_VISIBLE) <> 0; + Sz := GetTBXDragHandleSize(ToolbarInfo); + Horz := not ToolbarInfo.IsVertical; + if Horz then R.Right := R.Left + Sz + else R.Bottom := R.Top + Sz; + + { Drag Handle } + if ToolbarInfo.DragHandleStyle <> DHS_NONE then + begin + R2 := R; + if Horz then + begin + Inc(R2.Left, DragHandleOffsets[BtnVisible, ToolbarInfo.DragHandleStyle]); + if BtnVisible then Inc(R2.Top, Sz - 2); + R2.Right := R2.Left + 3; + end + else + begin + Inc(R2.Top, DragHandleOffsets[BtnVisible, ToolbarInfo.DragHandleStyle]); + if BtnVisible then Dec(R2.Right, Sz - 2); + R2.Bottom := R2.Top + 3; + end; + + Pen.Color := DragHandleColor; + if Horz then + begin + I := R2.Top + 3; + while I < R2.Bottom - 3 do + begin + MoveTo(R2.Left, I); LineTo(R2.Right, I); + Inc(I, 2); + end; + end + else + begin + I := R2.Left + 3; + while I < R2.Right - 3 do + begin + MoveTo(I, R2.Top); LineTo(I, R2.Bottom); + Inc(I, 2); + end; + end; + end; + + { Close button } + if BtnVisible then + begin + R2 := R; + if Horz then + begin + Dec(R2.Right); + R2.Bottom := R2.Top + R2.Right - R2.Left; + end + else + begin + Dec(R2.Bottom); + R2.Left := R2.Right - R2.Bottom + R2.Top; + end; + + BtnItemState := GetBtnItemState(ToolbarInfo.CloseButtonState); + FrameRectEx(DC, R2, BtnItemColors[BtnItemState, ipFrame], True); + FillRectEx(DC, R2, BtnItemColors[BtnItemState, ipBody]); + DrawButtonBitmap(DC, R2, BtnItemColors[BtnItemState, ipText]); + end; + end; +end; + +procedure TTBXOfficeXPTheme.PaintDock(Canvas: TCanvas; const ClientRect, + DockRect: TRect; DockPosition: Integer); +begin + // this theme does not support dock painting +end; + +procedure TTBXOfficeXPTheme.PaintDockPanelNCArea(Canvas: TCanvas; R: TRect; const DockPanelInfo: TTBXDockPanelInfo); + + function GetBtnItemState(BtnState: Integer): TBtnItemState; + begin + if (BtnState and CDBS_PRESSED) <> 0 then Result := bisPressed + else if (BtnState and CDBS_HOT) <> 0 then Result := bisHot + else Result := bisNormal; + end; + +var + DC: HDC; + C, HeaderColor: TColor; + I, Sz, Flags: Integer; + R2: TRect; + BtnItemState: TBtnItemState; + B: HBrush; + OldBkMode: Cardinal; + OldFont: HFont; + OldTextColor: TColorRef; +begin + DC := Canvas.Handle; + with DockPanelInfo do + begin + I := ColorIntensity(ColorToRGB(clBtnFace)); + R2 := R; + if not TBXLoColor and (I in [64..250]) then + begin + FrameRectEx(DC, R, clBtnFace, True); + FrameRectEx(DC, R, EffectiveColor, False); + with R do + begin + C := GetSysColor(COLOR_BTNFACE); + SetPixelV(DC, Left, Top, C); + if IsVertical then SetPixelV(DC, Right - 1, Top, C) + else SetPixelV(DC, Left, Bottom - 1, C); + end; + end + else + begin + FrameRectEx(DC, R, EffectiveColor, True); + + if I < 64 then B := CreateDitheredBrush(EffectiveColor, clWhite) + else B := CreateDitheredBrush(EffectiveColor, clBtnShadow); + Windows.FrameRect(DC, R, B); + DeleteObject(B); + + with R do + begin + SetPixelV(DC, Left, Top, EffectiveColor); + if IsVertical then SetPixelV(DC, Right - 1, Top, EffectiveColor) + else SetPixelV(DC, Left, Bottom - 1, EffectiveColor); + end; + InflateRect(R, -1, -1); + FrameRectEx(DC, R, EffectiveColor, False); + end; + R := R2; + InflateRect(R, -BorderSize.X, -BorderSize.Y); + Sz := GetSystemMetrics(SM_CYSMCAPTION); + if IsVertical then + begin + R.Bottom := R.Top + Sz - 1; + DrawLineEx(DC, R.Left, R.Bottom, R.Right, R.Bottom, EffectiveColor); + end + else + begin + R.Right := R.Left + Sz - 1; + DrawLineEx(DC, R.Right, R.Top, R.Right, R.Bottom, EffectiveColor); + end; + HeaderColor := clBtnFace; + FillRectEx(DC, R, HeaderColor); + + if (CDBS_VISIBLE and CloseButtonState) <> 0 then + begin + R2 := R; + if IsVertical then + begin + R2.Left := R2.Right - Sz + 1; + R.Right := R2.Left; + end + else + begin + R2.Top := R2.Bottom - Sz + 1; + R.Bottom := R2.Top; + end; + + BtnItemState := GetBtnItemState(CloseButtonState); + FrameRectEx(DC, R2, BtnItemColors[BtnItemState, ipFrame], True); + FillRectEx(DC, R2, BtnItemColors[BtnItemState, ipBody]); + DrawButtonBitmap(DC, R2, BtnItemColors[BtnItemState, ipText]); + end; + + + if IsVertical then InflateRect(R, -4, 0) + else InflateRect(R, 0, -4); + + OldFont := SelectObject(DC, SmCaptionFont.Handle); + OldBkMode := SetBkMode(DC, TRANSPARENT); + OldTextColor := SetTextColor(DC, ColorToRGB(SmCaptionFont.Color)); + Flags := DT_SINGLELINE or DT_VCENTER or DT_END_ELLIPSIS or DT_NOPREFIX; + if IsVertical then DrawText(DC, Caption, -1, R, Flags) + else DrawRotatedText(DC, string(Caption), R, Flags); + SetTextColor(DC, OldTextColor); + SetBkMode(DC, OldBkMode); + SelectObject(DC, OldFont); + end; +end; + +procedure TTBXOfficeXPTheme.SetupColorCache; +var + DC: HDC; + HotBtnFace, DisabledText: TColor; + + procedure Undither(var C: TColor); + begin + if C <> clNone then C := GetNearestColor(DC, ColorToRGB(C)); + end; + +begin + DC := StockCompatibleBitmap.Canvas.Handle; + + if TBXLoColor then + begin + { View/Window Colors } + MenubarColor := clBtnFace; + ToolbarColor := clBtnFace; + PopupColor := clWindow; + DockPanelColor := clWindow; + StatusPanelFrameColor := clBtnShadow; + + PopupFrameColor := clBtnText; + WinFrameColors[wfsActive, wfpBorder] := clBtnShadow; + WinFrameColors[wfsActive, wfpCaption] := clBtnShadow; + WinFrameColors[wfsActive, wfpCaptionText] := clBtnHighlight; + WinFrameColors[wfsInactive, wfpBorder] := clBtnShadow; + WinFrameColors[wfsInactive, wfpCaption] := clBtnShadow; + WinFrameColors[wfsInactive, wfpCaptionText] := clBtnHighlight; + + PnlFrameColors[wfsActive, wfpBorder] := clBtnShadow; + PnlFrameColors[wfsActive, wfpCaption] := clBtnFace; + PnlFrameColors[wfsActive, wfpCaptionText] := clBtnText; + PnlFrameColors[wfsInactive, wfpBorder] := clBtnShadow; + PnlFrameColors[wfsInactive, wfpCaption] := clBtnFace; + PnlFrameColors[wfsInactive, wfpCaptionText] := clBtnText; + + MenuItemColors[misNormal, ipBody] := clNone; + MenuItemColors[misNormal, ipText] := clWindowText; + MenuItemColors[misNormal, ipFrame] := clNone; + MenuItemColors[misDisabled, ipBody] := clNone; + MenuItemColors[misDisabled, ipText] := clGrayText; + MenuItemColors[misDisabled, ipFrame] := clNone; + MenuItemColors[misHot, ipBody] := clWindow; + MenuItemColors[misHot, ipText] := clWindowtext; + MenuItemColors[misHot, ipFrame] := clHighlight; + MenuItemColors[misDisabledHot, ipBody] := clWindow; + MenuItemColors[misDisabledHot, ipText] := clGrayText; + MenuItemColors[misDisabledHot, ipFrame] := clHighlight; + + BtnItemColors[bisNormal, ipBody] := clNone; + BtnItemColors[bisNormal, ipText] := clBtnText; + BtnItemColors[bisNormal, ipFrame] := clNone; + BtnItemColors[bisDisabled, ipBody] := clNone; + BtnItemColors[bisDisabled, ipText] := clBtnShadow; + BtnItemColors[bisDisabled, ipFrame] := clNone; + BtnItemColors[bisSelected, ipBody] := clWindow; + BtnItemColors[bisSelected, ipText] := clWindowText; + BtnItemColors[bisSelected, ipFrame] := clHighlight; + BtnItemColors[bisPressed, ipBody] := clHighlight; + BtnItemColors[bisPressed, ipText] := clHighlightText; + BtnItemColors[bisPressed, ipFrame] := clHighlight; + BtnItemColors[bisHot, ipBody] := clWindow; + BtnItemColors[bisHot, ipText] := clWindowText; + BtnItemColors[bisHot, ipFrame] := clHighlight; + BtnItemColors[bisDisabledHot, ipBody] := clWindow; + BtnItemColors[bisDisabledHot, ipText] := clBtnShadow; + BtnItemColors[bisDisabledHot, ipFrame] := clHighlight; + BtnItemColors[bisSelectedHot, ipBody] := clHighlight; + BtnItemColors[bisSelectedHot, ipText] := clHighlightText; + BtnItemColors[bisSelectedHot, ipFrame] := clHighlight; + BtnItemColors[bisPopupParent, ipBody] := clBtnFace; + BtnItemColors[bisPopupParent, ipText] := clBtnText; + BtnItemColors[bisPopupParent, ipFrame] := PopupFrameColor; + + { Other Colors } + DragHandleColor := clBtnText; + IconShadowColor := clBtnFace; + PopupSeparatorColor := clBtnShadow; + ToolbarSeparatorColor := clBtnShadow; + end + else + begin + { View/Window Colors } + MenubarColor := clBtnFace; + ToolbarColor := Blend(clWindow, clBtnFace, 165); + PopupColor := Blend(clBtnFace, clWindow, 143); + DockPanelColor := PopupColor; + PopupFrameColor := Blend(clBtnText, clBtnShadow, 20); + SetContrast(PopupFrameColor, PopupColor, 100); + + HotBtnFace := Blend(clHighlight, clWindow, 30); + SetContrast(HotBtnFace, ToolbarColor, 50); + DisabledText := Blend(clBtnshadow, clWindow, 90); + + WinFrameColors[wfsActive, wfpBorder] := Blend(clBtnText, clBtnShadow, 15); + SetContrast(WinFrameColors[wfsActive, wfpBorder], ToolbarColor, 120); + WinFrameColors[wfsActive, wfpCaption] := clBtnShadow; + WinFrameColors[wfsActive, wfpCaptionText] := clBtnHighlight; + SetContrast(WinFrameColors[wfsActive, wfpCaptionText], clBtnShadow, 180); + WinFrameColors[wfsInactive, wfpBorder] := WinFrameColors[wfsActive, wfpBorder]; + WinFrameColors[wfsInactive, wfpCaption] := clBtnFace; + WinFrameColors[wfsInactive, wfpCaptionText] := DisabledText; + SetContrast(WinFrameColors[wfsInactive, wfpCaptionText], clBtnFace, 120); + + PnlFrameColors[wfsActive, wfpBorder] := clBtnShadow; + PnlFrameColors[wfsActive, wfpCaption] := clBtnFace; + PnlFrameColors[wfsActive, wfpCaptionText] := clBtnText; + PnlFrameColors[wfsInactive, wfpBorder] := clBtnShadow; + PnlFrameColors[wfsInactive, wfpCaption] := clBtnFace; + PnlFrameColors[wfsInactive, wfpCaptionText] := DisabledText; + SetContrast(PnlFrameColors[wfsInactive, wfpCaptionText], clBtnFace, 120); + + BtnItemColors[bisNormal, ipBody] := clNone; + BtnItemColors[bisNormal, ipText] := clBtnText; + SetContrast(BtnItemColors[bisNormal, ipText], ToolbarColor, 180); + BtnItemColors[bisNormal, ipFrame] := clNone; + BtnItemColors[bisDisabled, ipBody] := clNone; + BtnItemColors[bisDisabled, ipText] := DisabledText; + SetContrast(BtnItemColors[bisDisabled, ipText], ToolbarColor, 80); + BtnItemColors[bisDisabled, ipFrame] := clNone; + BtnItemColors[bisSelected, ipBody] := Blend(clHighlight, Blend(clBtnFace, clWindow, 50), 10); + SetContrast(BtnItemColors[bisSelected, ipBody], ToolbarColor, 5); + BtnItemColors[bisSelected, ipText] := BtnItemColors[bisNormal, ipText]; + BtnItemColors[bisSelected, ipFrame] := clHighlight; + BtnItemColors[bisPressed, ipBody] := Blend(clHighlight, clWindow, 50); + BtnItemColors[bisPressed, ipText] := clHighlightText; + BtnItemColors[bisPressed, ipFrame] := clHighlight; + BtnItemColors[bisHot, ipBody] := HotBtnFace; + BtnItemColors[bisHot, ipText] := clMenuText; + SetContrast(BtnItemColors[bisHot, ipText], BtnItemColors[bisHot, ipBody], 180); + BtnItemColors[bisHot, ipFrame] := clHighlight; + SetContrast(BtnItemColors[bisHot, ipFrame], ToolbarColor, 100); + BtnItemColors[bisDisabledHot, ipBody] := HotBtnFace; + BtnItemColors[bisDisabledHot, ipText] := DisabledText; + BtnItemColors[bisDisabledHot, ipFrame] := clHighlight; + BtnItemColors[bisSelectedHot, ipBody] := Blend(clHighlight, clWindow, 50); + SetContrast(BtnItemColors[bisSelectedHot, ipBody], ToolbarColor, 30); + BtnItemColors[bisSelectedHot, ipText] := clHighlightText; + SetContrast(BtnItemColors[bisSelectedHot, ipText], BtnItemColors[bisSelectedHot, ipBody], 180); + BtnItemColors[bisSelectedHot, ipFrame] := clHighlight; + SetContrast(BtnItemColors[bisSelectedHot, ipFrame], BtnItemColors[bisSelectedHot, ipBody], 100); + BtnItemColors[bisPopupParent, ipBody] := ToolbarColor; + BtnItemColors[bisPopupParent, ipText] := BtnItemColors[bisNormal, ipText]; + BtnItemColors[bisPopupParent, ipFrame] := PopupFrameColor; + + MenuItemColors[misNormal, ipBody] := clNone; + MenuItemColors[misNormal, ipText] := clWindowText; + SetContrast(MenuItemColors[misNormal, ipText], PopupColor, 180); + MenuItemColors[misNormal, ipFrame] := clNone; + MenuItemColors[misDisabled, ipBody] := clNone; + MenuItemColors[misDisabled, ipText] := Blend(clGrayText, clWindow, 70); + SetContrast(MenuItemColors[misDisabled, ipText], PopupColor, 80); // 145? + MenuItemColors[misDisabled, ipFrame] := clNone; + MenuItemColors[misHot, ipBody] := BtnItemColors[bisHot, ipBody]; + MenuItemColors[misHot, ipText] := BtnItemColors[bisHot, ipText]; + MenuItemColors[misHot, ipFrame] := BtnItemColors[bisHot, ipFrame]; + MenuItemColors[misDisabledHot, ipBody] := PopupColor; + MenuItemColors[misDisabledHot, ipText] := Blend(clGrayText, clWindow, 70); + MenuItemColors[misDisabledHot, ipFrame] := clHighlight; + + { Other Colors } + DragHandleColor := Blend(clBtnShadow, clWindow, 75); + SetContrast(DragHandleColor, ToolbarColor, 85); + IconShadowColor := Blend(clBlack, HotBtnFace, 25); + ToolbarSeparatorColor := Blend(clBtnShadow, clWindow, 70); + SetContrast(ToolbarSeparatorColor, ToolbarColor, 50); + PopupSeparatorColor := ToolbarSeparatorColor; + StatusPanelFrameColor := Blend(clWindow, clBtnFace, 30); + SetContrast(StatusPanelFrameColor, clBtnFace, 30); + + Undither(MenubarColor); + Undither(ToolbarColor); + Undither(PopupColor); + Undither(DockPanelColor); + Undither(PopupFrameColor); + Undither(WinFrameColors[wfsActive, wfpBorder]); + Undither(WinFrameColors[wfsActive, wfpCaption]); + Undither(WinFrameColors[wfsActive, wfpCaptionText]); + Undither(WinFrameColors[wfsInactive, wfpBorder]); + Undither(WinFrameColors[wfsInactive, wfpCaption]); + Undither(WinFrameColors[wfsInactive, wfpCaptionText]); + Undither(PnlFrameColors[wfsActive, wfpBorder]); + Undither(PnlFrameColors[wfsActive, wfpCaption]); + Undither(PnlFrameColors[wfsActive, wfpCaptionText]); + Undither(PnlFrameColors[wfsInactive, wfpBorder]); + Undither(PnlFrameColors[wfsInactive, wfpCaption]); + Undither(PnlFrameColors[wfsInactive, wfpCaptionText]); + Undither(BtnItemColors[bisNormal, ipBody]); + Undither(BtnItemColors[bisNormal, ipText]); + Undither(BtnItemColors[bisNormal, ipFrame]); + Undither(BtnItemColors[bisDisabled, ipBody]); + Undither(BtnItemColors[bisDisabled, ipText]); + Undither(BtnItemColors[bisDisabled, ipFrame]); + Undither(BtnItemColors[bisSelected, ipBody]); + Undither(BtnItemColors[bisSelected, ipText]); + Undither(BtnItemColors[bisSelected, ipFrame]); + Undither(BtnItemColors[bisPressed, ipBody]); + Undither(BtnItemColors[bisPressed, ipText]); + Undither(BtnItemColors[bisPressed, ipFrame]); + Undither(BtnItemColors[bisHot, ipBody]); + Undither(BtnItemColors[bisHot, ipText]); + Undither(BtnItemColors[bisHot, ipFrame]); + Undither(BtnItemColors[bisDisabledHot, ipBody]); + Undither(BtnItemColors[bisDisabledHot, ipText]); + Undither(BtnItemColors[bisDisabledHot, ipFrame]); + Undither(BtnItemColors[bisSelectedHot, ipBody]); + Undither(BtnItemColors[bisSelectedHot, ipText]); + Undither(BtnItemColors[bisSelectedHot, ipFrame]); + Undither(BtnItemColors[bisPopupParent, ipBody]); + Undither(BtnItemColors[bisPopupParent, ipText]); + Undither(BtnItemColors[bisPopupParent, ipFrame]); + Undither(MenuItemColors[misNormal, ipBody]); + Undither(MenuItemColors[misNormal, ipText]); + Undither(MenuItemColors[misNormal, ipFrame]); + Undither(MenuItemColors[misDisabled, ipBody]); + Undither(MenuItemColors[misDisabled, ipText]); + Undither(MenuItemColors[misDisabled, ipFrame]); + Undither(MenuItemColors[misHot, ipBody]); + Undither(MenuItemColors[misHot, ipText]); + Undither(MenuItemColors[misHot, ipFrame]); + Undither(MenuItemColors[misDisabledHot, ipBody]); + Undither(MenuItemColors[misDisabledHot, ipText]); + Undither(MenuItemColors[misDisabledHot, ipFrame]); + Undither(DragHandleColor); + Undither(IconShadowColor); + Undither(ToolbarSeparatorColor); + Undither(PopupSeparatorColor); + Undither(StatusPanelFrameColor); + end; +end; + +function TTBXOfficeXPTheme.GetPopupShadowType: Integer; +begin + Result := PST_OFFICEXP; +end; + +constructor TTBXOfficeXPTheme.Create(const AName: string); +begin + inherited; + if CounterLock = 0 then InitializeStock; + Inc(CounterLock); + AddTBXSysChangeNotification(Self); + SetupColorCache; +end; + +destructor TTBXOfficeXPTheme.Destroy; +begin + RemoveTBXSysChangeNotification(Self); + Dec(CounterLock); + if CounterLock = 0 then FinalizeStock; + inherited; +end; + +procedure TTBXOfficeXPTheme.GetViewMargins(ViewType: Integer; out Margins: TTBXMargins); +begin + Margins.LeftWidth := 0; + Margins.TopHeight := 0; + Margins.RightWidth := 0; + Margins.BottomHeight := 0; +end; + +procedure TTBXOfficeXPTheme.PaintPageScrollButton(Canvas: TCanvas; + const ARect: TRect; ButtonType: Integer; Hot: Boolean); +var + DC: HDC; + R: TRect; + X, Y, Sz: Integer; + C: TColor; +begin + DC := Canvas.Handle; + R := ARect; + if Hot then C := BtnItemColors[bisHot, ipFrame] + else C := clBtnShadow; + FrameRectEx(DC, R, C, False); + InflateRect(R, -1, -1); + if Hot then C := BtnItemColors[bisHot, ipBody] + else C := clBtnFace; + FillRectEx(DC, R, C); + X := (R.Left + R.Right) div 2; + Y := (R.Top + R.Bottom) div 2; + Sz := Min(X - R.Left, Y - R.Top) * 3 div 4; + + if Hot then C := BtnItemColors[bisHot, ipText] + else C := BtnItemColors[bisNormal, ipText]; + + case ButtonType of + PSBT_UP: + begin + Inc(Y, Sz div 2); + PolygonEx(DC, [Point(X + Sz, Y), Point(X, Y - Sz), Point(X - Sz, Y)], C, C); + end; + PSBT_DOWN: + begin + Y := (R.Top + R.Bottom - 1) div 2; + Dec(Y, Sz div 2); + PolygonEx(DC, [Point(X + Sz, Y), Point(X, Y + Sz), Point(X - Sz, Y)], C, C); + end; + PSBT_LEFT: + begin + Inc(X, Sz div 2); + PolygonEx(DC, [Point(X, Y + Sz), Point(X - Sz, Y), Point(X, Y - Sz)], C, C); + end; + PSBT_RIGHT: + begin + X := (R.Left + R.Right - 1) div 2; + Dec(X, Sz div 2); + PolygonEx(DC, [Point(X, Y + Sz), Point(X + Sz, Y), Point(X, Y - Sz)], C, C); + end; + end; +end; + +procedure TTBXOfficeXPTheme.PaintFrameControl(Canvas: TCanvas; R: TRect; Kind, State: Integer; Params: Pointer); +var + DC: HDC; + X, Y: Integer; + Pen, OldPen: HPen; + Brush, OldBrush: HBrush; + C: TColor; + + function GetPenColor: TColor; + begin + if Boolean(State and PFS_DISABLED) then Result := clBtnShadow + else if Boolean(State and PFS_PUSHED) then Result := BtnItemColors[bisPressed, ipFrame] + else if Boolean(State and PFS_HOT) then Result := BtnItemColors[bisHot, ipFrame] + else Result := clBtnShadow; + end; + + function GetBrush: HBrush; + begin + if Boolean(State and PFS_DISABLED) then Result := CreateBrushEx(clNone) + else if Boolean(State and PFS_PUSHED) then Result := CreateBrushEx(BtnItemColors[bisPressed, ipBody]) + else if Boolean(State and PFS_HOT) then Result := CreateBrushEx(BtnItemColors[bisHot, ipBody]) + else if Boolean(State and PFS_MIXED) then Result := CreateDitheredBrush(clWindow, clBtnFace) + else Result := CreateBrushEx(clNone); + end; + + function GetTextColor: TColor; + begin + if Boolean(State and PFS_DISABLED) then Result := BtnItemColors[bisDisabled, ipText] + else if Boolean(State and PFS_PUSHED) then Result := BtnItemColors[bisPressed, ipText] + else if Boolean(State and PFS_MIXED) then Result := clBtnShadow + else if Boolean(State and PFS_HOT) then Result := BtnItemColors[bisHot, ipText] + else Result := BtnItemColors[bisNormal, ipText]; + end; + +begin + DC := Canvas.Handle; + case Kind of + PFC_CHECKBOX: + begin + InflateRect(R, -1, -1); + FrameRectEx(DC, R, GetPenColor, True); + Brush := GetBrush; + Windows.FillRect(DC, R, Brush); + DeleteObject(Brush); + InflateRect(R, 1, 1); + + if Boolean(State and (PFS_CHECKED or PFS_MIXED)) then + begin + X := (R.Left + R.Right) div 2 - 1; + Y := (R.Top + R.Bottom) div 2 + 1; + C := GetTextColor; + PolygonEx(DC, [Point(X-2, Y), Point(X, Y+2), Point(X+4, Y-2), + Point(X+4, Y-4), Point(X, Y), Point(X-2, Y-2), Point(X-2, Y)], C, C); + end; + end; + PFC_RADIOBUTTON: + begin + InflateRect(R, -1, -1); + + with R do + begin + Brush := GetBrush; + OldBrush := SelectObject(DC, Brush); + Pen := CreatePenEx(GetPenColor); + OldPen := SelectObject(DC, Pen); + Windows.Ellipse(DC, Left, Top, Right, Bottom); + SelectObject(DC, OldPen); + DeleteObject(Pen); + SelectObject(DC, OldBrush); + DeleteObject(Brush); + end; + + if Boolean(State and PFS_CHECKED) then + begin + InflateRect(R, -3, -3); + C := GetTextColor; + Brush := CreateBrushEx(C); + OldBrush := SelectObject(DC, Brush); + Pen := CreatePenEx(C); + OldPen := SelectObject(DC, Pen); + with R do Windows.Ellipse(DC, Left, Top, Right, Bottom); + SelectObject(DC, OldPen); + DeleteObject(Pen); + SelectObject(DC, OldBrush); + DeleteObject(Brush); + end; + end; + end; +end; + +procedure TTBXOfficeXPTheme.PaintStatusBar(Canvas: TCanvas; R: TRect; Part: Integer); +var + D, Sz, I: Integer; + DC: HDC; + + procedure DiagLine(C: TColor); + begin + with R do + DrawLineEx(DC, Right - 1 - D, Bottom - 1, Right, Bottom - D - 2, C); + Inc(D); + end; + +begin + DC := Canvas.Handle; + case Part of + SBP_BODY: + begin + FillRectEx(DC, R, clBtnFace); + end; + SBP_PANE, SBP_LASTPANE: + begin + if Part = SBP_PANE then Dec(R.Right, 2); + FrameRectEx(DC, R, StatusPanelFrameColor, False); + end; + SBP_GRIPPER: + begin + D := 0; + Sz := Min(R.Right - R.Left, R.Bottom - R.Top); + for I := 1 to 3 do + case Sz of + 0..8: + begin + DiagLine(clBtnShadow); + DiagLine(clBtnHighlight); + end; + 9..11: + begin + DiagLine(clBtnFace); + DiagLine(clBtnShadow); + DiagLine(clBtnHighlight); + end; + 12..14: + begin + DiagLine(clBtnShadow); + DiagLine(clBtnShadow); + DiagLine(clBtnHighlight); + end; + else + DiagLine(clBtnFace); + DiagLine(clBtnShadow); + DiagLine(clBtnShadow); + DiagLine(clBtnHighlight); + end; + end; + end; +end; + +procedure TTBXOfficeXPTheme.TBXSysCommand(var Message: TMessage); +begin + if Message.WParam = TSC_VIEWCHANGE then SetupColorCache; +end; + +initialization + RegisterTBXTheme('OfficeXP', TTBXOfficeXPTheme); + +end. diff --git a/official/2.1.6+2.1.beta1/TBX/TBXOfficeXPTheme.pas.orig b/official/2.1.6+2.1.beta1/TBX/TBXOfficeXPTheme.pas.orig new file mode 100644 index 0000000..92284c1 --- /dev/null +++ b/official/2.1.6+2.1.beta1/TBX/TBXOfficeXPTheme.pas.orig @@ -0,0 +1,1688 @@ +unit TBXOfficeXPTheme; + +// TBX Package +// Copyright 2001-2004 Alex A. Denisov. All Rights Reserved +// See TBX.chm for license and installation instructions +// +// $Id: TBXOfficeXPTheme.pas 16 2004-05-26 02:02:55Z Alex@ZEISS $ + +interface + +{$I TB2Ver.inc} +{$I TBX.inc} + +uses + Windows, Messages, Graphics, TBXThemes, TBXDefaultTheme, ImgList; + +type + TItemPart = (ipBody, ipText, ipFrame); + TBtnItemState = (bisNormal, bisDisabled, bisSelected, bisPressed, bisHot, + bisDisabledHot, bisSelectedHot, bisPopupParent); + TMenuItemState = (misNormal, misDisabled, misHot, misDisabledHot); + TWinFramePart = (wfpBorder, wfpCaption, wfpCaptionText); + TWinFrameState = (wfsActive, wfsInactive); + + TTBXOfficeXPTheme = class(TTBXTheme) + private + procedure TBXSysCommand(var Message: TMessage); message TBX_SYSCOMMAND; + protected + { View/Window Colors } + MenubarColor: TColor; + ToolbarColor: TColor; + PopupColor: TColor; + DockPanelColor: TColor; + PopupFrameColor: TColor; + WinFrameColors: array [TWinFrameState, TWinFramePart] of TColor; + PnlFrameColors: array [TWinFrameState, TWinFramePart] of TColor; + MenuItemColors: array [TMenuItemState, TItemPart] of TColor; + BtnItemColors: array [TBtnItemState, TItemPart] of TColor; + + { Other Colors } + DragHandleColor: TColor; + PopupSeparatorColor: TColor; + ToolbarSeparatorColor: TColor; + IconShadowColor: TColor; + StatusPanelFrameColor: TColor; + + procedure SetupColorCache; virtual; + protected + { Internal Methods } + function GetPartColor(const ItemInfo: TTBXItemInfo; ItemPart: TItemPart): TColor; + function GetBtnColor(const ItemInfo: TTBXItemInfo; ItemPart: TItemPart): TColor; + public + constructor Create(const AName: string); override; + destructor Destroy; override; + + { Metrics access} + function GetBooleanMetrics(Index: Integer): Boolean; override; + function GetIntegerMetrics(Index: Integer): Integer; override; + procedure GetMargins(MarginID: Integer; out Margins: TTBXMargins); override; + function GetImageOffset(Canvas: TCanvas; const ItemInfo: TTBXItemInfo; ImageList: TCustomImageList): TPoint; override; + function GetItemColor(const ItemInfo: TTBXItemInfo): TColor; override; + function GetItemTextColor(const ItemInfo: TTBXItemInfo): TColor; override; + function GetItemImageBackground(const ItemInfo: TTBXItemInfo): TColor; override; + function GetPopupShadowType: Integer; override; + procedure GetViewBorder(ViewType: Integer; out Border: TPoint); override; + function GetViewColor(AViewType: Integer): TColor; override; + procedure GetViewMargins(ViewType: Integer; out Margins: TTBXMargins); override; + + { Painting routines } + procedure PaintBackgnd(Canvas: TCanvas; const ADockRect, ARect, AClipRect: TRect; AColor: TColor; Transparent: Boolean; AViewType: Integer); override; + procedure PaintButton(Canvas: TCanvas; const ARect: TRect; const ItemInfo: TTBXItemInfo); override; + procedure PaintCaption(Canvas: TCanvas; const ARect: TRect; const ItemInfo: TTBXItemInfo; const ACaption: string; AFormat: Cardinal; Rotated: Boolean); override; + procedure PaintCheckMark(Canvas: TCanvas; ARect: TRect; const ItemInfo: TTBXItemInfo); override; + procedure PaintChevron(Canvas: TCanvas; ARect: TRect; const ItemInfo: TTBXItemInfo); override; + procedure PaintDock(Canvas: TCanvas; const ClientRect, DockRect: TRect; DockPosition: Integer); override; + procedure PaintDockPanelNCArea(Canvas: TCanvas; R: TRect; const DockPanelInfo: TTBXDockPanelInfo); override; + procedure PaintDropDownArrow(Canvas: TCanvas; const ARect: TRect; const ItemInfo: TTBXItemInfo); override; + procedure PaintEditButton(Canvas: TCanvas; const ARect: TRect; var ItemInfo: TTBXItemInfo; ButtonInfo: TTBXEditBtnInfo); override; + procedure PaintEditFrame(Canvas: TCanvas; const ARect: TRect; var ItemInfo: TTBXItemInfo; const EditInfo: TTBXEditInfo); override; + procedure PaintFloatingBorder(Canvas: TCanvas; const ARect: TRect; const WindowInfo: TTBXWindowInfo); override; + procedure PaintFrame(Canvas: TCanvas; const ARect: TRect; const ItemInfo: TTBXItemInfo); override; + procedure PaintImage(Canvas: TCanvas; ARect: TRect; const ItemInfo: TTBXItemInfo; ImageList: TCustomImageList; ImageIndex: Integer); override; + procedure PaintMDIButton(Canvas: TCanvas; ARect: TRect; const ItemInfo: TTBXItemInfo; ButtonKind: Cardinal); override; + procedure PaintMenuItem(Canvas: TCanvas; const ARect: TRect; var ItemInfo: TTBXItemInfo); override; + procedure PaintMenuItemFrame(Canvas: TCanvas; const ARect: TRect; const ItemInfo: TTBXItemInfo); override; + procedure PaintPageScrollButton(Canvas: TCanvas; const ARect: TRect; ButtonType: Integer; Hot: Boolean); override; + procedure PaintPopupNCArea(Canvas: TCanvas; R: TRect; const PopupInfo: TTBXPopupInfo); override; + procedure PaintSeparator(Canvas: TCanvas; ARect: TRect; ItemInfo: TTBXItemInfo; Horizontal, LineSeparator: Boolean); override; + procedure PaintToolbarNCArea(Canvas: TCanvas; R: TRect; const ToolbarInfo: TTBXToolbarInfo); override; + procedure PaintFrameControl(Canvas: TCanvas; R: TRect; Kind, State: Integer; Params: Pointer); override; + procedure PaintStatusBar(Canvas: TCanvas; R: TRect; Part: Integer); override; + end; + +implementation + +uses TBXUtils, TB2Common, TB2Item, Classes, Controls, Commctrl, Forms; + +var + StockImgList: TImageList; + CounterLock: Integer; + +procedure InitializeStock; +begin + StockImgList := TImageList.Create(nil); + StockImgList.Handle := ImageList_LoadBitmap(HInstance, 'TBXGLYPHS', 16, 0, clWhite); +end; + +procedure FinalizeStock; +begin + StockImgList.Free; +end; + +{ TTBXOfficeXPTheme } + +function TTBXOfficeXPTheme.GetBooleanMetrics(Index: Integer): Boolean; +begin + case Index of + TMB_OFFICEXPPOPUPALIGNMENT: Result := True; + TMB_EDITMENUFULLSELECT: Result := True; + TMB_EDITHEIGHTEVEN: Result := False; + TMB_SOLIDTOOLBARNCAREA: Result := False; + TMB_SOLIDTOOLBARCLIENTAREA: Result := True; + else + Result := False; + end; +end; + +function TTBXOfficeXPTheme.GetIntegerMetrics(Index: Integer): Integer; +const + DEFAULT = -1; +begin + case Index of + TMI_SPLITBTN_ARROWWIDTH: Result := 12; + + TMI_DROPDOWN_ARROWWIDTH: Result := 8; + TMI_DROPDOWN_ARROWMARGIN: Result := 3; + + TMI_MENU_IMGTEXTSPACE: Result := 5; + TMI_MENU_LCAPTIONMARGIN: Result := 3; + TMI_MENU_RCAPTIONMARGIN: Result := 3; + TMI_MENU_SEPARATORSIZE: Result := 3; + TMI_MENU_MDI_DW: Result := 2; + TMI_MENU_MDI_DH: Result := 2; + + TMI_TLBR_SEPARATORSIZE: Result := 6; + + TMI_EDIT_FRAMEWIDTH: Result := 1; + TMI_EDIT_TEXTMARGINHORZ: Result := 2; + TMI_EDIT_TEXTMARGINVERT: Result := 2; + TMI_EDIT_BTNWIDTH: Result := 14; + TMI_EDIT_MENURIGHTINDENT: Result := 1; + else + Result := DEFAULT; + end; +end; + +function TTBXOfficeXPTheme.GetViewColor(AViewType: Integer): TColor; +begin + Result := clBtnFace; + if (AViewType and VT_TOOLBAR) = VT_TOOLBAR then + begin + if (AViewType and TVT_MENUBAR) = TVT_MENUBAR then Result := MenubarColor + else Result := ToolbarColor; + end + else if (AViewType and VT_POPUP) = VT_POPUP then + begin + if (AViewType and PVT_LISTBOX) = PVT_LISTBOX then Result := clWindow + else Result := PopupColor; + end + else if (AViewType and VT_DOCKPANEL) = VT_DOCKPANEL then Result := DockPanelColor; +end; + +function TTBXOfficeXPTheme.GetBtnColor(const ItemInfo: TTBXItemInfo; ItemPart: TItemPart): TColor; +const + BFlags1: array [Boolean] of TBtnItemState = (bisDisabled, bisDisabledHot); + BFlags2: array [Boolean] of TBtnItemState = (bisSelected, bisSelectedHot); + BFlags3: array [Boolean] of TBtnItemState = (bisNormal, bisHot); +var + B: TBtnItemState; + Embedded: Boolean; +begin + with ItemInfo do + begin + Embedded := (ViewType and VT_TOOLBAR = VT_TOOLBAR) and + (ViewType and TVT_EMBEDDED = TVT_EMBEDDED); + if not Enabled then B := BFlags1[HoverKind = hkKeyboardHover] + else if ItemInfo.IsPopupParent then B := bisPopupParent + else if Pushed then B := bisPressed + else if Selected then B := BFlags2[HoverKind <> hkNone] + else B := BFlags3[HoverKind <> hkNone]; + Result := BtnItemColors[B, ItemPart]; + if Embedded then + begin + if (ItemPart = ipBody) and (Result = clNone) then Result := ToolbarColor; + if ItemPart = ipFrame then + begin + if Selected then Result := clWindowFrame + else if (Result = clNone) then Result := clBtnShadow; + end; + end; + end; +end; + +function TTBXOfficeXPTheme.GetPartColor(const ItemInfo: TTBXItemInfo; ItemPart: TItemPart): TColor; +const + MFlags1: array [Boolean] of TMenuItemState = (misDisabled, misDisabledHot); + MFlags2: array [Boolean] of TMenuItemState = (misNormal, misHot); + BFlags1: array [Boolean] of TBtnItemState = (bisDisabled, bisDisabledHot); + BFlags2: array [Boolean] of TBtnItemState = (bisSelected, bisSelectedHot); + BFlags3: array [Boolean] of TBtnItemState = (bisNormal, bisHot); +var + IsMenuItem, Embedded: Boolean; + M: TMenuItemState; + B: TBtnItemState; +begin + with ItemInfo do + begin + IsMenuItem := ((ViewType and PVT_POPUPMENU) = PVT_POPUPMENU) and + ((ItemOptions and IO_TOOLBARSTYLE) = 0); + Embedded := ((ViewType and VT_TOOLBAR) = VT_TOOLBAR) and + ((ViewType and TVT_EMBEDDED) = TVT_EMBEDDED); + if IsMenuItem then + begin + if not Enabled then M := MFlags1[HoverKind = hkKeyboardHover] + else M := MFlags2[HoverKind <> hkNone]; + Result := MenuItemColors[M, ItemPart]; + end + else + begin + if not Enabled then B := BFlags1[HoverKind = hkKeyboardHover] + else if ItemInfo.IsPopupParent then B := bisPopupParent + else if Pushed then B := bisPressed + else if Selected then B := BFlags2[HoverKind <> hkNone] + else B := BFlags3[HoverKind <> hkNone]; + Result := BtnItemColors[B, ItemPart]; + if Embedded and (Result = clNone) then + begin + if ItemPart = ipBody then Result := ToolbarColor; + if ItemPart = ipFrame then Result := clBtnShadow; + end; + end; + end; +end; + +function TTBXOfficeXPTheme.GetItemColor(const ItemInfo: TTBXItemInfo): TColor; +begin + Result := GetPartColor(ItemInfo, ipBody); + if Result = clNone then Result := GetViewColor(ItemInfo.ViewType); +end; + +function TTBXOfficeXPTheme.GetItemTextColor(const ItemInfo: TTBXItemInfo): TColor; +begin + Result := GetPartColor(ItemInfo, ipText); +end; + +function TTBXOfficeXPTheme.GetItemImageBackground(const ItemInfo: TTBXItemInfo): TColor; +begin + Result := GetBtnColor(ItemInfo, ipBody); + if Result = clNone then Result := GetViewColor(ItemInfo.ViewType); +end; + +procedure TTBXOfficeXPTheme.GetViewBorder(ViewType: Integer; out Border: TPoint); +const + XMetrics: array [Boolean] of Integer = (SM_CXDLGFRAME, SM_CXFRAME); + YMetrics: array [Boolean] of Integer = (SM_CYDLGFRAME, SM_CYFRAME); +var + Resizable: Boolean; + + procedure SetBorder(X, Y: Integer); + begin + Border.X := X; + Border.Y := Y; + end; + +begin + if (ViewType and VT_TOOLBAR) = VT_TOOLBAR then + begin + if (ViewType and TVT_FLOATING) = TVT_FLOATING then + begin + Resizable := (ViewType and TVT_RESIZABLE) = TVT_RESIZABLE; + Border.X := GetSystemMetrics(XMetrics[Resizable]) - 1; + Border.Y := GetSystemMetrics(YMetrics[Resizable]) - 1; + end + else SetBorder(2, 2); + end + else if (ViewType and VT_POPUP) = VT_POPUP then + begin + if (ViewType and PVT_POPUPMENU) = PVT_POPUPMENU then Border.X := 1 + else Border.X := 2; + Border.Y := 2; + end + else if (ViewType and VT_DOCKPANEL) = VT_DOCKPANEL then + begin + if (ViewType and DPVT_FLOATING) = DPVT_FLOATING then + begin + Resizable := (ViewType and DPVT_RESIZABLE) = DPVT_RESIZABLE; + Border.X := GetSystemMetrics(XMetrics[Resizable]) - 1; + Border.Y := GetSystemMetrics(YMetrics[Resizable]) - 1; + end + else SetBorder(2, 2); + end + else SetBorder(0, 0); +end; + +procedure TTBXOfficeXPTheme.GetMargins(MarginID: Integer; out Margins: TTBXMargins); +begin + with Margins do + case MarginID of + MID_TOOLBARITEM: + begin + LeftWidth := 2; RightWidth := 2; + TopHeight := 2; BottomHeight := 2; + end; + + MID_MENUITEM: + begin + LeftWidth := 1; RightWidth := 1; + TopHeight := 3; BottomHeight := 3; + end; + + MID_STATUSPANE: + begin + LeftWidth := 1; RightWidth := 3; + TopHeight := 1; BottomHeight := 1; + end; + else + LeftWidth := 0; + RightWidth := 0; + TopHeight := 0; + BottomHeight := 0; + end; +end; + +procedure TTBXOfficeXPTheme.PaintBackgnd(Canvas: TCanvas; const ADockRect, ARect, AClipRect: TRect; + AColor: TColor; Transparent: Boolean; AViewType: Integer); +var + DC: HDC; + R: TRect; +begin + DC := Canvas.Handle; + if not Transparent then + begin + IntersectRect(R, ARect, AClipRect); + FillRectEx(DC, R, AColor); + end; +end; + +procedure TTBXOfficeXPTheme.PaintCaption(Canvas: TCanvas; + const ARect: TRect; const ItemInfo: TTBXItemInfo; const ACaption: string; + AFormat: Cardinal; Rotated: Boolean); +var + R: TRect; +begin + with ItemInfo, Canvas do + begin + R := ARect; + Brush.Style := bsClear; + if Font.Color = clNone then Font.Color := GetPartColor(ItemInfo, ipText); + if not Rotated then Windows.DrawText(Handle, PChar(ACaption), Length(ACaption), R, AFormat) + else DrawRotatedText(Handle, ACaption, R, AFormat); + Brush.Style := bsSolid; + end; +end; + +procedure TTBXOfficeXPTheme.PaintCheckMark(Canvas: TCanvas; ARect: TRect; const ItemInfo: TTBXItemInfo); +var + X, Y: Integer; +begin + X := (ARect.Left + ARect.Right) div 2 - 2; + Y := (ARect.Top + ARect.Bottom) div 2 + 1; + Canvas.Pen.Color := GetBtnColor(ItemInfo, ipText); + Canvas.Polyline([Point(X-2, Y-2), Point(X, Y), Point(X+4, Y-4), + Point(X+4, Y-3), Point(X, Y+1), Point(X-2, Y-1), Point(X-2, Y-2)]); +end; + +procedure TTBXOfficeXPTheme.PaintChevron(Canvas: TCanvas; ARect: TRect; const ItemInfo: TTBXItemInfo); +const + Pattern: array[Boolean, 0..15] of Byte = ( + ($CC, 0, $66, 0, $33, 0, $66, 0, $CC, 0, 0, 0, 0, 0, 0, 0), + ($88, 0, $D8, 0, $70, 0, $20, 0, $88, 0, $D8, 0, $70, 0, $20, 0)); +var + R2: TRect; + W, H: Integer; +begin + R2 := ARect; + PaintButton(Canvas, ARect, ItemInfo); + if not ItemInfo.IsVertical then + begin + Inc(R2.Top, 4); + R2.Bottom := R2.Top + 5; + W := 8; + H := 5; + end + else + begin + R2.Left := R2.Right - 9; + R2.Right := R2.Left + 5; + W := 5; + H := 8; + end; + DrawGlyph(Canvas.Handle, R2, W, H, Pattern[ItemInfo.IsVertical][0], GetPartColor(ItemInfo, ipText)); +end; + +procedure TTBXOfficeXPTheme.PaintEditButton(Canvas: TCanvas; const ARect: TRect; + var ItemInfo: TTBXItemInfo; ButtonInfo: TTBXEditBtnInfo); +var + DC: HDC; + BtnDisabled, BtnHot, BtnPressed, Embedded: Boolean; + R, BR: TRect; + X, Y: Integer; + SaveItemInfoPushed: Boolean; + C: TColor; +begin + DC := Canvas.Handle; + R := ARect; + Embedded := ((ItemInfo.ViewType and VT_TOOLBAR) = VT_TOOLBAR) and + ((ItemInfo.ViewType and TVT_EMBEDDED) = TVT_EMBEDDED); + + InflateRect(R, 1, 1); + Inc(R.Left); + with Canvas do + if ButtonInfo.ButtonType = EBT_DROPDOWN then + begin + BtnDisabled := (ButtonInfo.ButtonState and EBDS_DISABLED) <> 0; + BtnHot := (ButtonInfo.ButtonState and EBDS_HOT) <> 0; + BtnPressed := (ButtonInfo.ButtonState and EBDS_PRESSED) <> 0; + if not BtnDisabled then + begin + if BtnPressed or BtnHot or Embedded then PaintButton(Canvas, R, ItemInfo) + else if (ItemInfo.ViewType and VT_TOOLBAR) = VT_TOOLBAR then + begin + R := ARect; + if not Embedded then + begin + FrameRectEx(DC, R, clWindow, False); + C := clWindow; + end + else C := GetBtnColor(ItemInfo, ipFrame); + DrawLineEx(DC, R.Left - 1, R.Top, R.Left - 1, R.Bottom, C); + end; + end; + PaintDropDownArrow(Canvas, R, ItemInfo); + end + else if ButtonInfo.ButtonType = EBT_SPIN then + begin + BtnDisabled := (ButtonInfo.ButtonState and EBSS_DISABLED) <> 0; + BtnHot := (ButtonInfo.ButtonState and EBSS_HOT) <> 0; + + { Upper button } + BR := R; + BR.Bottom := (R.Top + R.Bottom + 1) div 2; + BtnPressed := (ButtonInfo.ButtonState and EBSS_UP) <> 0; + SaveItemInfoPushed := ItemInfo.Pushed; + ItemInfo.Pushed := BtnPressed; + if not BtnDisabled then + begin + if BtnPressed or BtnHot or Embedded then PaintButton(Canvas, BR, ItemInfo) + else if (ItemInfo.ViewType and VT_TOOLBAR) = VT_TOOLBAR then + begin + BR.Left := ARect.Left; BR.Top := ARect.Top; BR.Right := ARect.Right; + if not Embedded then + begin + FrameRectEx(DC, BR, clWindow, False); + C := clWindow; + end + else C := GetBtnColor(ItemInfo, ipFrame); + DrawLineEx(DC, BR.Left - 1, BR.Top, BR.Left - 1, BR.Bottom, C); + end; + end; + X := (BR.Left + BR.Right) div 2; + Y := (BR.Top + BR.Bottom - 1) div 2; + Pen.Color := GetPartColor(ItemInfo, ipText); + Brush.Color := Pen.Color; + Polygon([Point(X - 2, Y + 1), Point(X + 2, Y + 1), Point(X, Y - 1)]); + + { Lower button } + BR := R; + BR.Top := (R.Top + R.Bottom) div 2; + BtnPressed := (ButtonInfo.ButtonState and EBSS_DOWN) <> 0; + ItemInfo.Pushed := BtnPressed; + if not BtnDisabled then + begin + if BtnPressed or BtnHot or Embedded then PaintButton(Canvas, BR, ItemInfo) + else if (ItemInfo.ViewType and VT_TOOLBAR) = VT_TOOLBAR then + begin + BR.Left := ARect.Left; BR.Bottom := ARect.Bottom; BR.Right := ARect.Right; + if not Embedded then + begin + FrameRectEx(DC, BR, clWindow, False); + C := clWindow; + end + else C := GetBtnColor(ItemInfo, ipFrame); + DrawLineEx(DC, BR.Left - 1, BR.Top, BR.Left - 1, BR.Bottom, C); + end; + end; + X := (BR.Left + BR.Right) div 2; + Y := (BR.Top + BR.Bottom) div 2; + C := GetPartColor(ItemInfo, ipText); + PolygonEx(DC, [Point(X - 2, Y - 1), Point(X + 2, Y - 1), Point(X, Y + 1)], C, C); + + ItemInfo.Pushed := SaveItemInfoPushed; + end; +end; + +procedure TTBXOfficeXPTheme.PaintEditFrame(Canvas: TCanvas; + const ARect: TRect; var ItemInfo: TTBXItemInfo; const EditInfo: TTBXEditInfo); +var + DC: HDC; + R: TRect; + W: Integer; + Embedded: Boolean; +begin + DC := Canvas.Handle; + R := ARect; + PaintFrame(Canvas, R, ItemInfo); + W := EditFrameWidth; + InflateRect(R, -W, -W); + Embedded := ((ItemInfo.ViewType and VT_TOOLBAR) = VT_TOOLBAR) and + ((ItemInfo.ViewType and TVT_EMBEDDED) = TVT_EMBEDDED); + if not (ItemInfo.Enabled or Embedded) then + FrameRectEx(DC, R, BtnItemColors[bisDisabled, ipText], False); + + with EditInfo do if RightBtnWidth > 0 then Dec(R.Right, RightBtnWidth - 2); + + if ItemInfo.Enabled then + begin + if ((ItemInfo.ViewType and VT_TOOLBAR) <> VT_TOOLBAR) and (GetPartColor(ItemInfo, ipFrame) = clNone) then + FrameRectEx(DC, R, ToolbarColor, False) + else + FrameRectEx(DC, R, clWindow, False); + + InflateRect(R, -1, -1); + FillRectEx(DC, R, clWindow); + if ((ItemInfo.ViewType and VT_TOOLBAR) <> VT_TOOLBAR) and (GetPartColor(ItemInfo, ipFrame) = clNone) then + begin + R := ARect; + InflateRect(R, -1, -1); + FrameRectEx(DC, R, ToolbarColor, False); + end; + end + else InflateRect(R, -1, -1); + + with EditInfo do if LeftBtnWidth > 0 then Inc(R.Left, LeftBtnWidth - 2); + + if EditInfo.RightBtnWidth > 0 then + begin + R := ARect; + InflateRect(R, -W, -W); + R.Left := R.Right - EditInfo.RightBtnWidth; + PaintEditButton(Canvas, R, ItemInfo, EditInfo.RightBtnInfo); + end; +end; + +procedure TTBXOfficeXPTheme.PaintDropDownArrow(Canvas: TCanvas; + const ARect: TRect; const ItemInfo: TTBXItemInfo); +var + X, Y: Integer; +begin + with ARect, Canvas do + begin + X := (Left + Right) div 2; + Y := (Top + Bottom) div 2 - 1; + Pen.Color := GetPartColor(ItemInfo, ipText); + Brush.Color := Pen.Color; + if ItemInfo.IsVertical then Polygon([Point(X, Y + 2), Point(X, Y - 2), Point(X - 2, Y)]) + else Polygon([Point(X - 2, Y), Point(X + 2, Y), Point(X, Y + 2)]); + end; +end; + +procedure TTBXOfficeXPTheme.PaintButton(Canvas: TCanvas; const ARect: TRect; const ItemInfo: TTBXItemInfo); +var + DC: HDC; + R: TRect; +begin + DC := Canvas.Handle; + with ItemInfo do + begin + R := ARect; + if ((ItemOptions and IO_DESIGNING) <> 0) and not Selected then + begin + if ComboPart = cpSplitRight then Dec(R.Left); + FrameRectEx(DC, R, GetNearestColor(DC, MixColors(clBtnShadow, clBtnFace, 100)), False); + end + else + begin + FrameRectEx(DC, R, GetBtnColor(ItemInfo, ipFrame), True); + if (ComboPart = cpSplitLeft) and IsPopupParent then Inc(R.Right); + if ComboPart = cpSplitRight then Dec(R.Left); + FillRectEx(DC, R, GetBtnColor(ItemInfo, ipBody)); + end; + if ComboPart = cpSplitRight then PaintDropDownArrow(Canvas, R, ItemInfo); + end; +end; + +procedure TTBXOfficeXPTheme.PaintFloatingBorder(Canvas: TCanvas; const ARect: TRect; + const WindowInfo: TTBXWindowInfo); +const + WinStates: array [Boolean] of TWinFramestate = (wfsInactive, wfsActive); + + function GetBtnItemState(BtnState: Integer): TBtnItemState; + begin + if not WindowInfo.Active then Result := bisDisabled + else if (BtnState and CDBS_PRESSED) <> 0 then Result := bisPressed + else if (BtnState and CDBS_HOT) <> 0 then Result := bisHot + else Result := bisNormal; + end; + +var + WinState: TWinFrameState; + BtnItemState: TBtnItemState; + SaveIndex, X, Y: Integer; + Sz: TPoint; + R: TRect; + BodyColor, CaptionColor, CaptionText: TColor; + IsDockPanel: Boolean; +begin + with Canvas do + begin + WinState := WinStates[WindowInfo.Active]; + IsDockPanel := (WindowInfo.ViewType and VT_DOCKPANEL) = VT_DOCKPANEL; + BodyColor := Brush.Color; + + if (WRP_BORDER and WindowInfo.RedrawPart) <> 0 then + begin + R := ARect; + + if not IsDockPanel then Brush.Color := WinFrameColors[WinState, wfpBorder] + else Brush.Color := PnlFrameColors[WinState, wfpBorder]; + + SaveIndex := SaveDC(Canvas.Handle); + Sz := WindowInfo.FloatingBorderSize; + with R, Sz do ExcludeClipRect(Canvas.Handle, Left + X, Top + Y, Right - X, Bottom - Y); + FillRect(R); + RestoreDC(Canvas.Handle, SaveIndex); + InflateRect(R, -Sz.X, -Sz.Y); + Pen.Color := BodyColor; + with R do + if not IsDockPanel then + Canvas.Polyline([ + Point(Left, Top - 1), Point(Right - 1, Top - 1), + Point(Right, Top), Point(Right, Bottom - 1), + Point(Right - 1, Bottom), + Point(Left, Bottom), Point(Left - 1, Bottom - 1), + Point(Left - 1, Top), Point(Left, Top - 1) + ]) + else + Canvas.Polyline([ + Point(Left, Top - 1), Point(Right - 1, Top - 1), + Point(Right, Top), Point(Right, Bottom), + Point(Left - 1, Bottom), + Point(Left - 1, Top), Point(Left, Top - 1) + ]); + end; + + if not WindowInfo.ShowCaption then Exit; + + if (WindowInfo.ViewType and VT_TOOLBAR) = VT_TOOLBAR then + begin + CaptionColor := WinFrameColors[WinState, wfpCaption]; + CaptionText := WinFrameColors[WinState, wfpCaptionText]; + end + else + begin + CaptionColor := PnlFrameColors[WinState, wfpCaption]; + CaptionText := PnlFrameColors[WinState, wfpCaptionText]; + end; + + { Caption } + if (WRP_CAPTION and WindowInfo.RedrawPart) <> 0 then + begin + R := Rect(0, 0, WindowInfo.ClientWidth, GetSystemMetrics(SM_CYSMCAPTION) - 1); + with WindowInfo.FloatingBorderSize do OffsetRect(R, X, Y); + DrawLineEx(Canvas.Handle, R.Left, R.Bottom, R.Right, R.Bottom, BodyColor); + + if ((CDBS_VISIBLE and WindowInfo.CloseButtonState) <> 0) and + ((WRP_CLOSEBTN and WindowInfo.RedrawPart) <> 0) then + Dec(R.Right, GetSystemMetrics(SM_CYSMCAPTION) - 1); + + Brush.Color := CaptionColor; + FillRect(R); + InflateRect(R, -2, 0); + Font.Assign(SmCaptionFont); + Font.Color := CaptionText; + DrawText(Canvas.Handle, WindowInfo.Caption, -1, R, + DT_SINGLELINE or DT_VCENTER or DT_END_ELLIPSIS or DT_NOPREFIX); + end; + + { Close button } + if (CDBS_VISIBLE and WindowInfo.CloseButtonState) <> 0 then + begin + R := Rect(0, 0, WindowInfo.ClientWidth, GetSystemMetrics(SM_CYSMCAPTION) - 1); + with WindowInfo.FloatingBorderSize do OffsetRect(R, X, Y); + R.Left := R.Right - (R.Bottom - R.Top); + DrawLineEx(Canvas.Handle, R.Left - 1, R.Bottom, R.Right, R.Bottom, BodyColor); + Brush.Color := CaptionColor; + FillRect(R); + with R do + begin + X := (Left + Right - StockImgList.Width + 1) div 2; + Y := (Top + Bottom - StockImgList.Height) div 2; + end; + BtnItemState := GetBtnItemState(WindowInfo.CloseButtonState); + FrameRectEx(Canvas.Handle, R, BtnItemColors[BtnItemState, ipFrame], True); + if FillRectEx(Canvas.Handle, R, BtnItemColors[BtnItemState, ipBody]) then + DrawGlyph(Canvas.Handle, X, Y, StockImgList, 0, BtnItemColors[BtnItemState, ipText]) + else + DrawGlyph(Canvas.Handle, X, Y, StockImgList, 0, CaptionText); + end; + end; +end; + +procedure TTBXOfficeXPTheme.PaintFrame(Canvas: TCanvas; const ARect: TRect; + const ItemInfo: TTBXItemInfo); +var + DC: HDC; + R: TRect; +begin + DC := Canvas.Handle; + R := ARect; + FrameRectEx(DC, R, GetPartColor(ItemInfo, ipFrame), True); + FillRectEx(DC, R, GetPartColor(ItemInfo, ipBody)); +end; + +function TTBXOfficeXPTheme.GetImageOffset(Canvas: TCanvas; + const ItemInfo: TTBXItemInfo; ImageList: TCustomImageList): TPoint; +begin + Result.X := 0; + if not (ImageList is TTBCustomImageList) then + with ItemInfo do + if Enabled and (HoverKind <> hkNone) and + not (Selected or Pushed and not IsPopupParent) then + Result.X := -1; + Result.Y := Result.X +end; + +procedure TTBXOfficeXPTheme.PaintImage(Canvas: TCanvas; ARect: TRect; + const ItemInfo: TTBXItemInfo; ImageList: TCustomImageList; ImageIndex: Integer); +var + HiContrast: Boolean; +begin + with ItemInfo do + begin + if ImageList is TTBCustomImageList then + begin + TTBCustomImageList(ImageList).DrawState(Canvas, ARect.Left, ARect.Top, + ImageIndex, Enabled, (HoverKind <> hkNone), Selected); + Exit; + end; + +{$IFNDEF ALTERNATIVE_DISABLED_STYLE} + HiContrast := IsDarkColor(GetItemImageBackground(ItemInfo), 64); + + if not Enabled then + begin + DrawTBXIconFlatShadow(Canvas, ARect, ImageList, ImageIndex, + BtnItemColors[bisDisabled, ipText]); + end + else if Selected or Pushed or (HoverKind <> hkNone) then + begin + if not (Selected or Pushed and not IsPopupParent) then + begin + OffsetRect(ARect, 1, 1); + DrawTBXIconFullShadow(Canvas, ARect, ImageList, ImageIndex, IconShadowColor); + OffsetRect(ARect, -2, -2); + end; + DrawTBXIcon(Canvas, ARect, ImageList, ImageIndex, HiContrast); + end + else if HiContrast or TBXHiContrast or TBXLoColor then + DrawTBXIcon(Canvas, ARect, ImageList, ImageIndex, HiContrast) + else + HighlightTBXIcon(Canvas, ARect, ImageList, ImageIndex, clWindow, 178); +{$ELSE} + HiContrast := ColorIntensity(GetItemImageBackground(ItemInfo)) < 80; + if not Enabled then + begin + if not HiContrast then + DrawTBXIconShadow(Canvas, ARect, ImageList, ImageIndex, 0) + else + DrawTBXIconFlatShadow(Canvas, ARect, ImageList, ImageIndex, clBtnShadow); + end + else if Selected or Pushed or (HoverKind <> hkNone) then + begin + if not (Selected or Pushed and not IsPopupParent) then + begin + DrawTBXIconShadow(Canvas, ARect, ImageList, ImageIndex, 1); + OffsetRect(ARect, 1, 1); + DrawTBXIconShadow(Canvas, ARect, ImageList, ImageIndex, 1); + OffsetRect(ARect, -2, -2); + end; + DrawTBXIcon(Canvas, ARect, ImageList, ImageIndex, HiContrast); + end + else if HiContrast or TBXHiContrast or TBXLoColor then + DrawTBXIcon(Canvas, ARect, ImageList, ImageIndex, HiContrast) + else + HighlightTBXIcon(Canvas, ARect, ImageList, ImageIndex, clWindow, 178); +{$ENDIF} + end; +end; + +procedure TTBXOfficeXPTheme.PaintMDIButton(Canvas: TCanvas; ARect: TRect; + const ItemInfo: TTBXItemInfo; ButtonKind: Cardinal); +var + Index: Integer; +begin + PaintButton(Canvas, ARect, ItemInfo); + Dec(ARect.Bottom); + case ButtonKind of + DFCS_CAPTIONMIN: Index := 2; + DFCS_CAPTIONRESTORE: Index := 3; + DFCS_CAPTIONCLOSE: Index := 0; + else + Exit; + end; + DrawGlyph(Canvas.Handle, ARect, StockImgList, Index, GetPartColor(ItemInfo, ipText)); +end; + +procedure TTBXOfficeXPTheme.PaintMenuItemFrame(Canvas: TCanvas; + const ARect: TRect; const ItemInfo: TTBXItemInfo); +var + R: TRect; +begin + R := ARect; + if (ItemInfo.ViewType and PVT_TOOLBOX) <> PVT_TOOLBOX then with Canvas do + begin + R.Right := R.Left + ItemInfo.PopupMargin + 2; + Brush.Color := ToolbarColor; + FillRect(R); + Inc(R.Left); + R.Right := ARect.Right - 1; + end; + PaintFrame(Canvas, R, ItemInfo); +end; + +procedure TTBXOfficeXPTheme.PaintMenuItem(Canvas: TCanvas; const ARect: TRect; var ItemInfo: TTBXItemInfo); +var + DC: HDC; + R: TRect; + X, Y: Integer; + ArrowWidth: Integer; + C, ClrText: TColor; +begin + DC := Canvas.Handle; + with ItemInfo do + begin + ArrowWidth := GetSystemMetrics(SM_CXMENUCHECK); + PaintMenuItemFrame(Canvas, ARect, ItemInfo); + ClrText := GetPartColor(ItemInfo, ipText); + R := ARect; + + if (ItemOptions and IO_COMBO) <> 0 then + begin + X := R.Right - ArrowWidth - 1; + if not ItemInfo.Enabled then C := ClrText + else if HoverKind = hkMouseHover then C := GetPartColor(ItemInfo, ipFrame) + else C := PopupSeparatorColor; + DrawLineEx(DC, X, R.Top + 1, X, R.Bottom - 1, C); + end; + + if (ItemOptions and IO_SUBMENUITEM) <> 0 then + begin + Y := ARect.Bottom div 2; + X := ARect.Right - ArrowWidth * 2 div 3 - 1; + PolygonEx(DC, [Point(X, Y - 3), Point(X, Y + 3), Point(X + 3, Y)], ClrText, ClrText); + end; + + if Selected and Enabled then + begin + R := ARect; + R.Left := ARect.Left + 1; + R.Right := R.Left + ItemInfo.PopupMargin; + InflateRect(R, -1, -1); + FrameRectEx(DC, R, GetBtnColor(ItemInfo, ipFrame), True); + FillRectEx(DC, R, GetBtnColor(ItemInfo, ipBody)); + end; + end; +end; + +procedure TTBXOfficeXPTheme.PaintPopupNCArea(Canvas: TCanvas; R: TRect; const PopupInfo: TTBXPopupInfo); +var + PR: TRect; +begin + with Canvas do + begin + Brush.Color := PopupFrameColor; + FrameRect(R); + InflateRect(R, -1, -1); + Brush.Color := PopupColor; + FillRect(R); + + if not IsRectEmpty(PopupInfo.ParentRect) then + begin + PR := PopupInfo.ParentRect; + if not IsRectEmpty(PR) then with PR do + begin + Pen.Color := ToolbarColor; + if Bottom = R.Top then + begin + if Left <= R.Left then Left := R.Left - 1; + if Right >= R.Right then Right := R.Right + 1; + MoveTo(Left + 1, Bottom - 1); LineTo(Right - 1, Bottom- 1); + end + else if Top = R.Bottom then + begin + if Left <= R.Left then Left := R.Left - 1; + if Right >= R.Right then Right := R.Right + 1; + MoveTo(Left + 1, Top); LineTo(Right - 1, Top); + end; + if Right = R.Left then + begin + if Top <= R.Top then Top := R.Top - 1; + if Bottom >= R.Bottom then Bottom := R.Bottom + 1; + MoveTo(Right - 1, Top + 1); LineTo(Right - 1, Bottom - 1); + end + else if Left = R.Right then + begin + if Top <= R.Top then Top := R.Top - 1; + if Bottom >= R.Bottom then Bottom := R.Bottom + 1; + MoveTo(Left, Top + 1); LineTo(Left, Bottom - 1); + end; + end; + end; + end; +end; + +procedure TTBXOfficeXPTheme.PaintSeparator(Canvas: TCanvas; ARect: TRect; + ItemInfo: TTBXItemInfo; Horizontal, LineSeparator: Boolean); +var + DC: HDC; + IsToolbox: Boolean; + R: TRect; + C: TColor; +begin + { Note: for blank separators, Enabled = False } + DC := Canvas.Handle; + with ItemInfo, ARect do + begin + if Horizontal then + begin + IsToolbox := (ViewType and PVT_TOOLBOX) = PVT_TOOLBOX; + if ((ItemOptions and IO_TOOLBARSTYLE) = 0) and not IsToolBox then + begin + R := ARect; + R.Right := ItemInfo.PopupMargin + 2; + FillRectEx(DC, R, ToolbarColor); + Inc(Left, ItemInfo.PopupMargin + 9); + C := PopupSeparatorColor; + end + else + C := ToolbarSeparatorColor; + Top := (Top + Bottom) div 2; + if Enabled then DrawLineEx(DC, Left, Top, Right, Top, C); + end + else if Enabled then + begin + Left := (Left + Right) div 2; + DrawLineEx(DC, Left, Top, Left, Bottom, ToolbarSeparatorColor); + end; + end; +end; + +procedure DrawButtonBitmap(DC: HDC; R: TRect; Color: TColor); +const +{$IFNDEF SMALL_CLOSE_BUTTON} + Pattern: array [0..15] of Byte = + ($C3, 0, $66, 0, $3C, 0, $18, 0, $3C, 0, $66, 0, $C3, 0, 0, 0); +{$ELSE} + Pattern: array [0..15] of Byte = + (0, 0, $63, 0, $36, 0, $1C, 0, $1C, 0, $36, 0, $63, 0, 0, 0); +{$ENDIF} +begin + DrawGlyph(DC, R, 8, 7, Pattern[0], Color); +end; + +procedure TTBXOfficeXPTheme.PaintToolbarNCArea(Canvas: TCanvas; R: TRect; const ToolbarInfo: TTBXToolbarInfo); +const + DragHandleOffsets: array [Boolean, DHS_DOUBLE..DHS_SINGLE] of Integer = ((2, 0, 1), (5, 0, 5)); + + function GetBtnItemState(BtnState: Integer): TBtnItemState; + begin + if (BtnState and CDBS_PRESSED) <> 0 then Result := bisPressed + else if (BtnState and CDBS_HOT) <> 0 then Result := bisHot + else Result := bisNormal; + end; + +var + DC: HDC; + Sz: Integer; + R2: TRect; + SaveColor: TColor; + SaveStyle: TBrushStyle; + I: Integer; + BtnVisible, Horz: Boolean; + BtnItemState: TBtnItemState; +begin + DC := Canvas.Handle; + with Canvas do + begin + SaveColor := Brush.Color; + SaveStyle := Brush.Style; + if ToolbarInfo.BorderStyle = bsSingle then + begin + I := ColorIntensity(clBtnFace); + if not (TBXLoColor or not (I in [50..254])) or + ((ToolbarInfo.ViewType and TVT_MENUBAR) = TVT_MENUBAR) then + begin + InflateRect(R, -1, -1); + Dec(R.Right); Dec(R.Bottom); + Pen.Color := SaveColor; + Pen.Style := psSolid; + Brush.Color := SaveColor; + Brush.Style := SaveStyle; // should be either bsSolid or bsClear + with R do + Polygon([Point(Left + 1, Top), Point(Right - 1, Top), Point(Right, Top + 1), + Point(Right, Bottom - 1), Point(Right - 1, Bottom), Point(Left + 1, Bottom), + Point(Left, Bottom - 1), Point(Left, Top + 1)]); + Brush.Style := bsSolid; + Inc(R.Left); + Inc(R.Top); + end + else + begin + Brush.Bitmap := AllocPatternBitmap(ToolbarColor, BtnItemColors[bisDisabled, ipText]); + with R do + begin + FillRect(Rect(Left + 1, Top, Right - 1, Top + 1)); + FillRect(Rect(Left + 1, Bottom - 1, Right - 1, Bottom)); + FillRect(Rect(Left, Top + 1, Left + 1, Bottom - 1)); + FillRect(Rect(Right - 1, Top + 1, Right, Bottom - 1)); + end; + InflateRect(R, -1, -1); + Brush.Color := SaveColor; + FillRect(R); + end; + end + else + InflateRect(R, -1, -1); + InflateRect(R, -1, -1); + + if not ToolbarInfo.AllowDrag then Exit; + + BtnVisible := (ToolbarInfo.CloseButtonState and CDBS_VISIBLE) <> 0; + Sz := GetTBXDragHandleSize(ToolbarInfo); + Horz := not ToolbarInfo.IsVertical; + if Horz then R.Right := R.Left + Sz + else R.Bottom := R.Top + Sz; + + { Drag Handle } + if ToolbarInfo.DragHandleStyle <> DHS_NONE then + begin + R2 := R; + if Horz then + begin + Inc(R2.Left, DragHandleOffsets[BtnVisible, ToolbarInfo.DragHandleStyle]); + if BtnVisible then Inc(R2.Top, Sz - 2); + R2.Right := R2.Left + 3; + end + else + begin + Inc(R2.Top, DragHandleOffsets[BtnVisible, ToolbarInfo.DragHandleStyle]); + if BtnVisible then Dec(R2.Right, Sz - 2); + R2.Bottom := R2.Top + 3; + end; + + Pen.Color := DragHandleColor; + if Horz then + begin + I := R2.Top + 3; + while I < R2.Bottom - 3 do + begin + MoveTo(R2.Left, I); LineTo(R2.Right, I); + Inc(I, 2); + end; + end + else + begin + I := R2.Left + 3; + while I < R2.Right - 3 do + begin + MoveTo(I, R2.Top); LineTo(I, R2.Bottom); + Inc(I, 2); + end; + end; + end; + + { Close button } + if BtnVisible then + begin + R2 := R; + if Horz then + begin + Dec(R2.Right); + R2.Bottom := R2.Top + R2.Right - R2.Left; + end + else + begin + Dec(R2.Bottom); + R2.Left := R2.Right - R2.Bottom + R2.Top; + end; + + BtnItemState := GetBtnItemState(ToolbarInfo.CloseButtonState); + FrameRectEx(DC, R2, BtnItemColors[BtnItemState, ipFrame], True); + FillRectEx(DC, R2, BtnItemColors[BtnItemState, ipBody]); + DrawButtonBitmap(DC, R2, BtnItemColors[BtnItemState, ipText]); + end; + end; +end; + +procedure TTBXOfficeXPTheme.PaintDock(Canvas: TCanvas; const ClientRect, + DockRect: TRect; DockPosition: Integer); +begin + // this theme does not support dock painting +end; + +procedure TTBXOfficeXPTheme.PaintDockPanelNCArea(Canvas: TCanvas; R: TRect; const DockPanelInfo: TTBXDockPanelInfo); + + function GetBtnItemState(BtnState: Integer): TBtnItemState; + begin + if (BtnState and CDBS_PRESSED) <> 0 then Result := bisPressed + else if (BtnState and CDBS_HOT) <> 0 then Result := bisHot + else Result := bisNormal; + end; + +var + DC: HDC; + C, HeaderColor: TColor; + I, Sz, Flags: Integer; + R2: TRect; + BtnItemState: TBtnItemState; + B: HBrush; + OldBkMode: Cardinal; + OldFont: HFont; + OldTextColor: TColorRef; +begin + DC := Canvas.Handle; + with DockPanelInfo do + begin + I := ColorIntensity(ColorToRGB(clBtnFace)); + R2 := R; + if not TBXLoColor and (I in [64..250]) then + begin + FrameRectEx(DC, R, clBtnFace, True); + FrameRectEx(DC, R, EffectiveColor, False); + with R do + begin + C := GetSysColor(COLOR_BTNFACE); + SetPixelV(DC, Left, Top, C); + if IsVertical then SetPixelV(DC, Right - 1, Top, C) + else SetPixelV(DC, Left, Bottom - 1, C); + end; + end + else + begin + FrameRectEx(DC, R, EffectiveColor, True); + + if I < 64 then B := CreateDitheredBrush(EffectiveColor, clWhite) + else B := CreateDitheredBrush(EffectiveColor, clBtnShadow); + Windows.FrameRect(DC, R, B); + DeleteObject(B); + + with R do + begin + SetPixelV(DC, Left, Top, EffectiveColor); + if IsVertical then SetPixelV(DC, Right - 1, Top, EffectiveColor) + else SetPixelV(DC, Left, Bottom - 1, EffectiveColor); + end; + InflateRect(R, -1, -1); + FrameRectEx(DC, R, EffectiveColor, False); + end; + R := R2; + InflateRect(R, -BorderSize.X, -BorderSize.Y); + Sz := GetSystemMetrics(SM_CYSMCAPTION); + if IsVertical then + begin + R.Bottom := R.Top + Sz - 1; + DrawLineEx(DC, R.Left, R.Bottom, R.Right, R.Bottom, EffectiveColor); + end + else + begin + R.Right := R.Left + Sz - 1; + DrawLineEx(DC, R.Right, R.Top, R.Right, R.Bottom, EffectiveColor); + end; + HeaderColor := clBtnFace; + FillRectEx(DC, R, HeaderColor); + + if (CDBS_VISIBLE and CloseButtonState) <> 0 then + begin + R2 := R; + if IsVertical then + begin + R2.Left := R2.Right - Sz + 1; + R.Right := R2.Left; + end + else + begin + R2.Top := R2.Bottom - Sz + 1; + R.Bottom := R2.Top; + end; + + BtnItemState := GetBtnItemState(CloseButtonState); + FrameRectEx(DC, R2, BtnItemColors[BtnItemState, ipFrame], True); + FillRectEx(DC, R2, BtnItemColors[BtnItemState, ipBody]); + DrawButtonBitmap(DC, R2, BtnItemColors[BtnItemState, ipText]); + end; + + + if IsVertical then InflateRect(R, -4, 0) + else InflateRect(R, 0, -4); + + OldFont := SelectObject(DC, SmCaptionFont.Handle); + OldBkMode := SetBkMode(DC, TRANSPARENT); + OldTextColor := SetTextColor(DC, ColorToRGB(SmCaptionFont.Color)); + Flags := DT_SINGLELINE or DT_VCENTER or DT_END_ELLIPSIS or DT_NOPREFIX; + if IsVertical then DrawText(DC, Caption, -1, R, Flags) + else DrawRotatedText(DC, string(Caption), R, Flags); + SetTextColor(DC, OldTextColor); + SetBkMode(DC, OldBkMode); + SelectObject(DC, OldFont); + end; +end; + +procedure TTBXOfficeXPTheme.SetupColorCache; +var + DC: HDC; + HotBtnFace, DisabledText: TColor; + + procedure Undither(var C: TColor); + begin + if C <> clNone then C := GetNearestColor(DC, ColorToRGB(C)); + end; + +begin + DC := StockCompatibleBitmap.Canvas.Handle; + + if TBXLoColor then + begin + { View/Window Colors } + MenubarColor := clBtnFace; + ToolbarColor := clBtnFace; + PopupColor := clWindow; + DockPanelColor := clWindow; + StatusPanelFrameColor := clBtnShadow; + + PopupFrameColor := clBtnText; + WinFrameColors[wfsActive, wfpBorder] := clBtnShadow; + WinFrameColors[wfsActive, wfpCaption] := clBtnShadow; + WinFrameColors[wfsActive, wfpCaptionText] := clBtnHighlight; + WinFrameColors[wfsInactive, wfpBorder] := clBtnShadow; + WinFrameColors[wfsInactive, wfpCaption] := clBtnShadow; + WinFrameColors[wfsInactive, wfpCaptionText] := clBtnHighlight; + + PnlFrameColors[wfsActive, wfpBorder] := clBtnShadow; + PnlFrameColors[wfsActive, wfpCaption] := clBtnFace; + PnlFrameColors[wfsActive, wfpCaptionText] := clBtnText; + PnlFrameColors[wfsInactive, wfpBorder] := clBtnShadow; + PnlFrameColors[wfsInactive, wfpCaption] := clBtnFace; + PnlFrameColors[wfsInactive, wfpCaptionText] := clBtnText; + + MenuItemColors[misNormal, ipBody] := clNone; + MenuItemColors[misNormal, ipText] := clWindowText; + MenuItemColors[misNormal, ipFrame] := clNone; + MenuItemColors[misDisabled, ipBody] := clNone; + MenuItemColors[misDisabled, ipText] := clGrayText; + MenuItemColors[misDisabled, ipFrame] := clNone; + MenuItemColors[misHot, ipBody] := clWindow; + MenuItemColors[misHot, ipText] := clWindowtext; + MenuItemColors[misHot, ipFrame] := clHighlight; + MenuItemColors[misDisabledHot, ipBody] := clWindow; + MenuItemColors[misDisabledHot, ipText] := clGrayText; + MenuItemColors[misDisabledHot, ipFrame] := clHighlight; + + BtnItemColors[bisNormal, ipBody] := clNone; + BtnItemColors[bisNormal, ipText] := clBtnText; + BtnItemColors[bisNormal, ipFrame] := clNone; + BtnItemColors[bisDisabled, ipBody] := clNone; + BtnItemColors[bisDisabled, ipText] := clBtnShadow; + BtnItemColors[bisDisabled, ipFrame] := clNone; + BtnItemColors[bisSelected, ipBody] := clWindow; + BtnItemColors[bisSelected, ipText] := clWindowText; + BtnItemColors[bisSelected, ipFrame] := clHighlight; + BtnItemColors[bisPressed, ipBody] := clHighlight; + BtnItemColors[bisPressed, ipText] := clHighlightText; + BtnItemColors[bisPressed, ipFrame] := clHighlight; + BtnItemColors[bisHot, ipBody] := clWindow; + BtnItemColors[bisHot, ipText] := clWindowText; + BtnItemColors[bisHot, ipFrame] := clHighlight; + BtnItemColors[bisDisabledHot, ipBody] := clWindow; + BtnItemColors[bisDisabledHot, ipText] := clBtnShadow; + BtnItemColors[bisDisabledHot, ipFrame] := clHighlight; + BtnItemColors[bisSelectedHot, ipBody] := clHighlight; + BtnItemColors[bisSelectedHot, ipText] := clHighlightText; + BtnItemColors[bisSelectedHot, ipFrame] := clHighlight; + BtnItemColors[bisPopupParent, ipBody] := clBtnFace; + BtnItemColors[bisPopupParent, ipText] := clBtnText; + BtnItemColors[bisPopupParent, ipFrame] := PopupFrameColor; + + { Other Colors } + DragHandleColor := clBtnText; + IconShadowColor := clBtnFace; + PopupSeparatorColor := clBtnShadow; + ToolbarSeparatorColor := clBtnShadow; + end + else + begin + { View/Window Colors } + MenubarColor := clBtnFace; + ToolbarColor := Blend(clWindow, clBtnFace, 165); + PopupColor := Blend(clBtnFace, clWindow, 143); + DockPanelColor := PopupColor; + PopupFrameColor := Blend(clBtnText, clBtnShadow, 20); + SetContrast(PopupFrameColor, PopupColor, 100); + + HotBtnFace := Blend(clHighlight, clWindow, 30); + SetContrast(HotBtnFace, ToolbarColor, 50); + DisabledText := Blend(clBtnshadow, clWindow, 90); + + WinFrameColors[wfsActive, wfpBorder] := Blend(clBtnText, clBtnShadow, 15); + SetContrast(WinFrameColors[wfsActive, wfpBorder], ToolbarColor, 120); + WinFrameColors[wfsActive, wfpCaption] := clBtnShadow; + WinFrameColors[wfsActive, wfpCaptionText] := clBtnHighlight; + SetContrast(WinFrameColors[wfsActive, wfpCaptionText], clBtnShadow, 180); + WinFrameColors[wfsInactive, wfpBorder] := WinFrameColors[wfsActive, wfpBorder]; + WinFrameColors[wfsInactive, wfpCaption] := clBtnFace; + WinFrameColors[wfsInactive, wfpCaptionText] := DisabledText; + SetContrast(WinFrameColors[wfsInactive, wfpCaptionText], clBtnFace, 120); + + PnlFrameColors[wfsActive, wfpBorder] := clBtnShadow; + PnlFrameColors[wfsActive, wfpCaption] := clBtnFace; + PnlFrameColors[wfsActive, wfpCaptionText] := clBtnText; + PnlFrameColors[wfsInactive, wfpBorder] := clBtnShadow; + PnlFrameColors[wfsInactive, wfpCaption] := clBtnFace; + PnlFrameColors[wfsInactive, wfpCaptionText] := DisabledText; + SetContrast(PnlFrameColors[wfsInactive, wfpCaptionText], clBtnFace, 120); + + BtnItemColors[bisNormal, ipBody] := clNone; + BtnItemColors[bisNormal, ipText] := clBtnText; + SetContrast(BtnItemColors[bisNormal, ipText], ToolbarColor, 180); + BtnItemColors[bisNormal, ipFrame] := clNone; + BtnItemColors[bisDisabled, ipBody] := clNone; + BtnItemColors[bisDisabled, ipText] := DisabledText; + SetContrast(BtnItemColors[bisDisabled, ipText], ToolbarColor, 80); + BtnItemColors[bisDisabled, ipFrame] := clNone; + BtnItemColors[bisSelected, ipBody] := Blend(clHighlight, Blend(clBtnFace, clWindow, 50), 10); + SetContrast(BtnItemColors[bisSelected, ipBody], ToolbarColor, 5); + BtnItemColors[bisSelected, ipText] := BtnItemColors[bisNormal, ipText]; + BtnItemColors[bisSelected, ipFrame] := clHighlight; + BtnItemColors[bisPressed, ipBody] := Blend(clHighlight, clWindow, 50); + BtnItemColors[bisPressed, ipText] := clHighlightText; + BtnItemColors[bisPressed, ipFrame] := clHighlight; + BtnItemColors[bisHot, ipBody] := HotBtnFace; + BtnItemColors[bisHot, ipText] := clMenuText; + SetContrast(BtnItemColors[bisHot, ipText], BtnItemColors[bisHot, ipBody], 180); + BtnItemColors[bisHot, ipFrame] := clHighlight; + SetContrast(BtnItemColors[bisHot, ipFrame], ToolbarColor, 100); + BtnItemColors[bisDisabledHot, ipBody] := HotBtnFace; + BtnItemColors[bisDisabledHot, ipText] := DisabledText; + BtnItemColors[bisDisabledHot, ipFrame] := clHighlight; + BtnItemColors[bisSelectedHot, ipBody] := Blend(clHighlight, clWindow, 50); + SetContrast(BtnItemColors[bisSelectedHot, ipBody], ToolbarColor, 30); + BtnItemColors[bisSelectedHot, ipText] := clHighlightText; + SetContrast(BtnItemColors[bisSelectedHot, ipText], BtnItemColors[bisSelectedHot, ipBody], 180); + BtnItemColors[bisSelectedHot, ipFrame] := clHighlight; + SetContrast(BtnItemColors[bisSelectedHot, ipFrame], BtnItemColors[bisSelectedHot, ipBody], 100); + BtnItemColors[bisPopupParent, ipBody] := ToolbarColor; + BtnItemColors[bisPopupParent, ipText] := BtnItemColors[bisNormal, ipText]; + BtnItemColors[bisPopupParent, ipFrame] := PopupFrameColor; + + MenuItemColors[misNormal, ipBody] := clNone; + MenuItemColors[misNormal, ipText] := clWindowText; + SetContrast(MenuItemColors[misNormal, ipText], PopupColor, 180); + MenuItemColors[misNormal, ipFrame] := clNone; + MenuItemColors[misDisabled, ipBody] := clNone; + MenuItemColors[misDisabled, ipText] := Blend(clGrayText, clWindow, 70); + SetContrast(MenuItemColors[misDisabled, ipText], PopupColor, 80); // 145? + MenuItemColors[misDisabled, ipFrame] := clNone; + MenuItemColors[misHot, ipBody] := BtnItemColors[bisHot, ipBody]; + MenuItemColors[misHot, ipText] := BtnItemColors[bisHot, ipText]; + MenuItemColors[misHot, ipFrame] := BtnItemColors[bisHot, ipFrame]; + MenuItemColors[misDisabledHot, ipBody] := PopupColor; + MenuItemColors[misDisabledHot, ipText] := Blend(clGrayText, clWindow, 70); + MenuItemColors[misDisabledHot, ipFrame] := clHighlight; + + { Other Colors } + DragHandleColor := Blend(clBtnShadow, clWindow, 75); + SetContrast(DragHandleColor, ToolbarColor, 85); + IconShadowColor := Blend(clBlack, HotBtnFace, 25); + ToolbarSeparatorColor := Blend(clBtnShadow, clWindow, 70); + SetContrast(ToolbarSeparatorColor, ToolbarColor, 50); + PopupSeparatorColor := ToolbarSeparatorColor; + StatusPanelFrameColor := Blend(clWindow, clBtnFace, 30); + SetContrast(StatusPanelFrameColor, clBtnFace, 30); + + Undither(MenubarColor); + Undither(ToolbarColor); + Undither(PopupColor); + Undither(DockPanelColor); + Undither(PopupFrameColor); + Undither(WinFrameColors[wfsActive, wfpBorder]); + Undither(WinFrameColors[wfsActive, wfpCaption]); + Undither(WinFrameColors[wfsActive, wfpCaptionText]); + Undither(WinFrameColors[wfsInactive, wfpBorder]); + Undither(WinFrameColors[wfsInactive, wfpCaption]); + Undither(WinFrameColors[wfsInactive, wfpCaptionText]); + Undither(PnlFrameColors[wfsActive, wfpBorder]); + Undither(PnlFrameColors[wfsActive, wfpCaption]); + Undither(PnlFrameColors[wfsActive, wfpCaptionText]); + Undither(PnlFrameColors[wfsInactive, wfpBorder]); + Undither(PnlFrameColors[wfsInactive, wfpCaption]); + Undither(PnlFrameColors[wfsInactive, wfpCaptionText]); + Undither(BtnItemColors[bisNormal, ipBody]); + Undither(BtnItemColors[bisNormal, ipText]); + Undither(BtnItemColors[bisNormal, ipFrame]); + Undither(BtnItemColors[bisDisabled, ipBody]); + Undither(BtnItemColors[bisDisabled, ipText]); + Undither(BtnItemColors[bisDisabled, ipFrame]); + Undither(BtnItemColors[bisSelected, ipBody]); + Undither(BtnItemColors[bisSelected, ipText]); + Undither(BtnItemColors[bisSelected, ipFrame]); + Undither(BtnItemColors[bisPressed, ipBody]); + Undither(BtnItemColors[bisPressed, ipText]); + Undither(BtnItemColors[bisPressed, ipFrame]); + Undither(BtnItemColors[bisHot, ipBody]); + Undither(BtnItemColors[bisHot, ipText]); + Undither(BtnItemColors[bisHot, ipFrame]); + Undither(BtnItemColors[bisDisabledHot, ipBody]); + Undither(BtnItemColors[bisDisabledHot, ipText]); + Undither(BtnItemColors[bisDisabledHot, ipFrame]); + Undither(BtnItemColors[bisSelectedHot, ipBody]); + Undither(BtnItemColors[bisSelectedHot, ipText]); + Undither(BtnItemColors[bisSelectedHot, ipFrame]); + Undither(BtnItemColors[bisPopupParent, ipBody]); + Undither(BtnItemColors[bisPopupParent, ipText]); + Undither(BtnItemColors[bisPopupParent, ipFrame]); + Undither(MenuItemColors[misNormal, ipBody]); + Undither(MenuItemColors[misNormal, ipText]); + Undither(MenuItemColors[misNormal, ipFrame]); + Undither(MenuItemColors[misDisabled, ipBody]); + Undither(MenuItemColors[misDisabled, ipText]); + Undither(MenuItemColors[misDisabled, ipFrame]); + Undither(MenuItemColors[misHot, ipBody]); + Undither(MenuItemColors[misHot, ipText]); + Undither(MenuItemColors[misHot, ipFrame]); + Undither(MenuItemColors[misDisabledHot, ipBody]); + Undither(MenuItemColors[misDisabledHot, ipText]); + Undither(MenuItemColors[misDisabledHot, ipFrame]); + Undither(DragHandleColor); + Undither(IconShadowColor); + Undither(ToolbarSeparatorColor); + Undither(PopupSeparatorColor); + Undither(StatusPanelFrameColor); + end; +end; + +function TTBXOfficeXPTheme.GetPopupShadowType: Integer; +begin + Result := PST_OFFICEXP; +end; + +constructor TTBXOfficeXPTheme.Create(const AName: string); +begin + inherited; + if CounterLock = 0 then InitializeStock; + Inc(CounterLock); + AddTBXSysChangeNotification(Self); + SetupColorCache; +end; + +destructor TTBXOfficeXPTheme.Destroy; +begin + RemoveTBXSysChangeNotification(Self); + Dec(CounterLock); + if CounterLock = 0 then FinalizeStock; + inherited; +end; + +procedure TTBXOfficeXPTheme.GetViewMargins(ViewType: Integer; out Margins: TTBXMargins); +begin + Margins.LeftWidth := 0; + Margins.TopHeight := 0; + Margins.RightWidth := 0; + Margins.BottomHeight := 0; +end; + +procedure TTBXOfficeXPTheme.PaintPageScrollButton(Canvas: TCanvas; + const ARect: TRect; ButtonType: Integer; Hot: Boolean); +var + DC: HDC; + R: TRect; + X, Y, Sz: Integer; + C: TColor; +begin + DC := Canvas.Handle; + R := ARect; + if Hot then C := BtnItemColors[bisHot, ipFrame] + else C := clBtnShadow; + FrameRectEx(DC, R, C, False); + InflateRect(R, -1, -1); + if Hot then C := BtnItemColors[bisHot, ipBody] + else C := clBtnFace; + FillRectEx(DC, R, C); + X := (R.Left + R.Right) div 2; + Y := (R.Top + R.Bottom) div 2; + Sz := Min(X - R.Left, Y - R.Top) * 3 div 4; + + if Hot then C := BtnItemColors[bisHot, ipText] + else C := BtnItemColors[bisNormal, ipText]; + + case ButtonType of + PSBT_UP: + begin + Inc(Y, Sz div 2); + PolygonEx(DC, [Point(X + Sz, Y), Point(X, Y - Sz), Point(X - Sz, Y)], C, C); + end; + PSBT_DOWN: + begin + Y := (R.Top + R.Bottom - 1) div 2; + Dec(Y, Sz div 2); + PolygonEx(DC, [Point(X + Sz, Y), Point(X, Y + Sz), Point(X - Sz, Y)], C, C); + end; + PSBT_LEFT: + begin + Inc(X, Sz div 2); + PolygonEx(DC, [Point(X, Y + Sz), Point(X - Sz, Y), Point(X, Y - Sz)], C, C); + end; + PSBT_RIGHT: + begin + X := (R.Left + R.Right - 1) div 2; + Dec(X, Sz div 2); + PolygonEx(DC, [Point(X, Y + Sz), Point(X + Sz, Y), Point(X, Y - Sz)], C, C); + end; + end; +end; + +procedure TTBXOfficeXPTheme.PaintFrameControl(Canvas: TCanvas; R: TRect; Kind, State: Integer; Params: Pointer); +var + DC: HDC; + X, Y: Integer; + Pen, OldPen: HPen; + Brush, OldBrush: HBrush; + C: TColor; + + function GetPenColor: TColor; + begin + if Boolean(State and PFS_DISABLED) then Result := clBtnShadow + else if Boolean(State and PFS_PUSHED) then Result := BtnItemColors[bisPressed, ipFrame] + else if Boolean(State and PFS_HOT) then Result := BtnItemColors[bisHot, ipFrame] + else Result := clBtnShadow; + end; + + function GetBrush: HBrush; + begin + if Boolean(State and PFS_DISABLED) then Result := CreateBrushEx(clNone) + else if Boolean(State and PFS_PUSHED) then Result := CreateBrushEx(BtnItemColors[bisPressed, ipBody]) + else if Boolean(State and PFS_HOT) then Result := CreateBrushEx(BtnItemColors[bisHot, ipBody]) + else if Boolean(State and PFS_MIXED) then Result := CreateDitheredBrush(clWindow, clBtnFace) + else Result := CreateBrushEx(clNone); + end; + + function GetTextColor: TColor; + begin + if Boolean(State and PFS_DISABLED) then Result := BtnItemColors[bisDisabled, ipText] + else if Boolean(State and PFS_PUSHED) then Result := BtnItemColors[bisPressed, ipText] + else if Boolean(State and PFS_MIXED) then Result := clBtnShadow + else if Boolean(State and PFS_HOT) then Result := BtnItemColors[bisHot, ipText] + else Result := BtnItemColors[bisNormal, ipText]; + end; + +begin + DC := Canvas.Handle; + case Kind of + PFC_CHECKBOX: + begin + InflateRect(R, -1, -1); + FrameRectEx(DC, R, GetPenColor, True); + Brush := GetBrush; + Windows.FillRect(DC, R, Brush); + DeleteObject(Brush); + InflateRect(R, 1, 1); + + if Boolean(State and (PFS_CHECKED or PFS_MIXED)) then + begin + X := (R.Left + R.Right) div 2 - 1; + Y := (R.Top + R.Bottom) div 2 + 1; + C := GetTextColor; + PolygonEx(DC, [Point(X-2, Y), Point(X, Y+2), Point(X+4, Y-2), + Point(X+4, Y-4), Point(X, Y), Point(X-2, Y-2), Point(X-2, Y)], C, C); + end; + end; + PFC_RADIOBUTTON: + begin + InflateRect(R, -1, -1); + + with R do + begin + Brush := GetBrush; + OldBrush := SelectObject(DC, Brush); + Pen := CreatePenEx(GetPenColor); + OldPen := SelectObject(DC, Pen); + Windows.Ellipse(DC, Left, Top, Right, Bottom); + SelectObject(DC, OldPen); + DeleteObject(Pen); + SelectObject(DC, OldBrush); + DeleteObject(Brush); + end; + + if Boolean(State and PFS_CHECKED) then + begin + InflateRect(R, -3, -3); + C := GetTextColor; + Brush := CreateBrushEx(C); + OldBrush := SelectObject(DC, Brush); + Pen := CreatePenEx(C); + OldPen := SelectObject(DC, Pen); + with R do Windows.Ellipse(DC, Left, Top, Right, Bottom); + SelectObject(DC, OldPen); + DeleteObject(Pen); + SelectObject(DC, OldBrush); + DeleteObject(Brush); + end; + end; + end; +end; + +procedure TTBXOfficeXPTheme.PaintStatusBar(Canvas: TCanvas; R: TRect; Part: Integer); +var + D, Sz, I: Integer; + DC: HDC; + + procedure DiagLine(C: TColor); + begin + with R do + DrawLineEx(DC, Right - 1 - D, Bottom - 1, Right, Bottom - D - 2, C); + Inc(D); + end; + +begin + DC := Canvas.Handle; + case Part of + SBP_BODY: + begin + FillRectEx(DC, R, clBtnFace); + end; + SBP_PANE, SBP_LASTPANE: + begin + if Part = SBP_PANE then Dec(R.Right, 2); + FrameRectEx(DC, R, StatusPanelFrameColor, False); + end; + SBP_GRIPPER: + begin + D := 0; + Sz := Min(R.Right - R.Left, R.Bottom - R.Top); + for I := 1 to 3 do + case Sz of + 0..8: + begin + DiagLine(clBtnShadow); + DiagLine(clBtnHighlight); + end; + 9..11: + begin + DiagLine(clBtnFace); + DiagLine(clBtnShadow); + DiagLine(clBtnHighlight); + end; + 12..14: + begin + DiagLine(clBtnShadow); + DiagLine(clBtnShadow); + DiagLine(clBtnHighlight); + end; + else + DiagLine(clBtnFace); + DiagLine(clBtnShadow); + DiagLine(clBtnShadow); + DiagLine(clBtnHighlight); + end; + end; + end; +end; + +procedure TTBXOfficeXPTheme.TBXSysCommand(var Message: TMessage); +begin + if Message.WParam = TSC_VIEWCHANGE then SetupColorCache; +end; + +initialization + RegisterTBXTheme('OfficeXP', TTBXOfficeXPTheme); + +end. diff --git a/official/2.1.6+2.1.beta1/TBX/TBXReg.dcr b/official/2.1.6+2.1.beta1/TBX/TBXReg.dcr new file mode 100644 index 0000000..d1a6555 Binary files /dev/null and b/official/2.1.6+2.1.beta1/TBX/TBXReg.dcr differ diff --git a/official/2.1.6+2.1.beta1/TBX/TBXReg.pas b/official/2.1.6+2.1.beta1/TBX/TBXReg.pas new file mode 100644 index 0000000..3599254 --- /dev/null +++ b/official/2.1.6+2.1.beta1/TBX/TBXReg.pas @@ -0,0 +1,486 @@ +unit TBXReg; + +// TBX Package +// Copyright 2001-2004 Alex A. Denisov. All Rights Reserved +// See TBX.chm for license and installation instructions +// +// $Id: TBXReg.pas 16 2004-05-26 02:02:55Z Alex@ZEISS $ + +interface + +{$I ..\..\Source\TB2Ver.inc} +{$I TBX.inc} + +uses + Windows, Classes, Controls, SysUtils, Graphics, ImgList, Dialogs, + {$IFDEF JR_D6} DesignIntf, DesignEditors, VCLEditors, {$ELSE} DsgnIntf, {$ENDIF} + TB2Reg, TB2Toolbar, TB2Item, TBX, TBXMDI, TBXSwitcher, TB2DsgnItemEditor, + TBXExtItems, TBXLists, TBXDkPanels, TBXToolPals, TBXStatusBars; + +procedure Register; + +type + TThemeProperty = class(TStringProperty) + function GetAttributes: TPropertyAttributes; override; + procedure GetValues(Proc: TGetStrProc); override; + end; + + TMLStringProperty = class(TCaptionProperty) + function GetAttributes: TPropertyAttributes; override; + procedure Edit; override; + end; + +{$IFDEF JR_D5} + TTBXLinkImageIndexPropertyEditor = class(TTBImageIndexPropertyEditor) + public + function GetImageListAt(Index: Integer): TCustomImageList; override; + end; +{$ENDIF} + + TTBXColorProperty = class(TColorProperty) + public + function GetValue: string; override; + procedure GetValues(Proc: TGetStrProc); override; + procedure SetValue(const Value: string); override; +{$IFDEF JR_D5} + procedure ListDrawValue(const Value: string; ACanvas: TCanvas; + const ARect: TRect; ASelected: Boolean);{$IFNDEF JR_D6} override;{$ENDIF} +{$ENDIF} + end; + + TTBXStatusBarEditor = class(TDefaultEditor) + protected +{$IFDEF JR_D6} + procedure GetPanelsProp(const Prop: IProperty); +{$ELSE} + procedure GetPanelsProp(Prop: TPropertyEditor); +{$ENDIF} + public + procedure Edit; override; + procedure ExecuteVerb(Index: Integer); override; + function GetVerb(Index: Integer): string; override; + function GetVerbCount: Integer; override; + end; + + TTBXItemsEditor = class(TTBItemsEditor) + public + procedure ExecuteVerb(Index: Integer); override; + end; + +implementation + +uses + Forms, TBXThemes, TBXStrEdit, TBXUtils, TypInfo, TB2Version; + +type + TTBXLinkAccess = class(TTBXCustomLink); + TTBXButtonAccess = class(TTBXCustomButton); + + +{ TThemeProperty } + +function TThemeProperty.GetAttributes: TPropertyAttributes; +begin + Result := [paMultiSelect, paValueList, paSortList, paRevertable]; +end; + +procedure TThemeProperty.GetValues(Proc: TGetStrProc); +var + SL: TStringList; + I: Integer; +begin + SL := TStringList.Create; + GetAvailableTBXThemes(SL); + for I := 0 to SL.Count - 1 do Proc(SL[I]); + SL.Free; +end; + +{ TMLStringProperty } + +function WordCount(const S: string; const Delims: TSysCharSet): Integer; +var + L, I: Cardinal; +begin + Result := 0; + I := 1; + L := Length(S); + while I <= L do + begin + while (I <= L) and (S[I] in Delims) do Inc(I); + if I <= L then Inc(Result); + while (I <= L) and not(S[I] in Delims) do Inc(I); + end; +end; + +function WordPosition(const N: Integer; const S: string; + const WordDelims: TSysCharSet): Integer; +var + Count, I: Integer; +begin + Count := 0; + I := 1; + Result := 0; + while (I <= Length(S)) and (Count <> N) do begin + { skip over delimiters } + while (I <= Length(S)) and (S[I] in WordDelims) do Inc(I); + { if we're not beyond end of S, we're at the start of a word } + if I <= Length(S) then Inc(Count); + { if not finished, find the end of the current word } + if Count <> N then + while (I <= Length(S)) and not (S[I] in WordDelims) do Inc(I) + else Result := I; + end; +end; + +function ExtractWord(N: Integer; const S: string; + const WordDelims: TSysCharSet): string; +var + I: Integer; + Len: Integer; +begin + Len := 0; + I := WordPosition(N, S, WordDelims); + if I <> 0 then + { find the end of the current word } + while (I <= Length(S)) and not(S[I] in WordDelims) do begin + { add the I'th character to result } + Inc(Len); + SetLength(Result, Len); + Result[Len] := S[I]; + Inc(I); + end; + SetLength(Result, Len); +end; + +procedure TMLStringProperty.Edit; +var + Temp: string; + Component: TPersistent; + I, N: Integer; +begin + with TStrEditDlg.Create(Application) do + try + Component := GetComponent(0); + if Component is TComponent then Caption := TComponent(Component).Name + '.' + GetName + else Caption := GetName; + + Temp := GetStrValue; + N := WordCount(Temp, [#13, #10]); + for I := 1 to N do Memo.Lines.Add(ExtractWord(I, Temp, [#13, #10])); + + Memo.MaxLength := GetEditLimit; + if ShowModal = mrOk then + begin + Temp := Memo.Text; + while (Length(Temp) > 0) and (Temp[Length(Temp)] < ' ') do + System.Delete(Temp, Length(Temp), 1); + SetStrValue(Temp); + end; + finally + Free; + end; +end; + +function TMLStringProperty.GetAttributes: TPropertyAttributes; +begin + Result := inherited GetAttributes + [paDialog]; +end; + +{$IFDEF JR_D5} +{ TTBXLinkImageIndexPropertyEditor } + +function TTBXLinkImageIndexPropertyEditor.GetImageListAt(Index: Integer): TCustomImageList; +var + C: TPersistent; +begin + Result := nil; + C := GetComponent(Index); + if C is TTBXCustomLink then + Result := TTBXLinkAccess(C).Images + else if C is TTBXCustomButton then + Result := TTBXButtonAccess(C).Images; +end; +{$ENDIF} + +{ TTBXColorProperty } + +function TTBXColorProperty.GetValue: string; +begin + Result := TBXColorToString(TColor(GetOrdValue)); +end; + +procedure TTBXColorProperty.GetValues(Proc: TGetStrProc); +begin + TBXGetColorValues(Proc); +end; + +procedure TTBXColorProperty.SetValue(const Value: string); +begin + SetOrdValue(TBXStringToColor(Value)); +end; + +{$IFDEF JR_D5} +procedure TTBXColorProperty.ListDrawValue(const Value: string; ACanvas: TCanvas; + const ARect: TRect; ASelected: Boolean); + + function ColorToBorderColor(AColor: TColor): TColor; + begin + if IsDarkColor(AColor) then + begin + Result := AColor; + SetContrast(Result, AColor, 40); + end + else Result := clBlack; + end; + +var + R: TRect; + C: TColor; + OldPenColor, OldBrushColor: TColor; +begin + R := ARect; + with ACanvas do + try + OldPenColor := Pen.Color; + OldBrushColor := Brush.Color; + Pen.Color := Brush.Color; + Rectangle(R); + R.Right := (ARect.Bottom - ARect.Top) + ARect.Left; + InflateRect(R, -1, -1); + C := TBXStringToColor(Value); + if C <> clNone then + begin + Brush.Color := C; + Pen.Color := ColorToBorderColor(ColorToRGB(C)); + Rectangle(R); + end + else + begin + Brush.Color := clWindow; + Pen.Color := clBtnShadow; + Rectangle(R); + MoveTo(R.Left, R.Bottom - 1); + LineTo(R.Right - 1, R.Top); + MoveTo(R.Left, R.Top); + LineTo(R.Right, R.Bottom); + end; + Brush.Color := OldBrushColor; + Pen.Color := OldPenColor; + finally + R.Left := R.Right; + R.Right := ARect.Right; + ACanvas.TextRect(R, R.Left + 1, R.Top + 1, Value); + end; +end; +{$ENDIF} + +{ TTBXStatusBarEditor } + +procedure TTBXStatusBarEditor.Edit; +var +{$IFDEF JR_D6} + Components: IDesignerSelections; +{$ELSE} + {$IFDEF JR_D5} + Components: TDesignerSelectionList; + {$ELSE} + Components: TComponentList; + {$ENDIF} +{$ENDIF} +begin +{$IFDEF JR_D6} + Components := CreateSelectionList; +{$ELSE} + {$IFDEF JR_D5} + Components := TDesignerSelectionList.Create; + {$ELSE} + Components := TComponentList.Create; + {$ENDIF} +{$ENDIF} + try + Components.Add(Component); + GetComponentProperties(Components, [tkClass], Designer, GetPanelsProp); + finally +{$IFNDEF JR_D6} + Components.Free; +{$ENDIF} + end; +end; + +procedure TTBXStatusBarEditor.ExecuteVerb(Index: Integer); +begin + if Index = 0 then Edit; +end; + +function TTBXStatusBarEditor.GetVerb(Index: Integer): string; +begin + if Index = 0 then Result := '&Panels Editor...'; +end; + +function TTBXStatusBarEditor.GetVerbCount: Integer; +begin + Result := 1; +end; + +{$IFDEF JR_D6} +procedure TTBXStatusBarEditor.GetPanelsProp(const Prop: IProperty); +begin + if SameText(Prop.GetName, 'Panels') then Prop.Edit; +end; +{$ELSE} +procedure TTBXStatusBarEditor.GetPanelsProp(Prop: TPropertyEditor); +begin + if CompareText(Prop.GetName, 'Panels') = 0 then Prop.Edit; +end; +{$ENDIF} + +{ TTBXItemsEditor } + +procedure TTBXItemsEditor.ExecuteVerb(Index: Integer); +const + AboutText = + '%s'#13#10 + + '20012004 Alex A. Denisov'#13#10 + + 'For conditions of distribution and use, see TBX documentation.'#13#10 + + 'Visit http://g32.org/tbx/ for the latest versions of TBX'#13#10 + + #13#10 + + 'Running on'#13#10 + + '%s'#13#10 + + '1998-2004 by Jordan Russell'#13#10 + + 'For conditions of distribution and use, see Toolbar2000 documentation.'#13#10 + + #13#10 + + 'Visit http://www.jrsoftware.org/ for the latest versions of Toolbar2000'#13#10 + + ''; +begin + case Index of + 0: Edit; + 1: + begin + MessageDlg( + Format(AboutText, + [TBXVersionText, Toolbar2000VersionPropText]), + mtInformation, [mbOK], 0); + end; + end; +end; + + +{ THookObj } + +type + THookObj = class + procedure HookProc(Sender: TTBItemEditForm); + end; + +var O: THookObj; + +procedure THookObj.HookProc(Sender: TTBItemEditForm); +var + TB: TTBToolbar; + Item: TTBCustomItem; + NewItem: TTBItem; + S: string; + I: Integer; +begin + TB := TTBToolbar.Create(Sender); + TB.Top := Sender.Height; + TB.Parent := Sender; + TB.Align := alTop; + TB.Images := Sender.ToolbarItems.SubMenuImages; + TB.ShowHint := True; + + for I := 0 to Sender.MoreMenu.Count - 1 do + begin + Item := Sender.MoreMenu.Items[I]; + if Item is TTBCustomItem then + begin + S := TTBCustomItemClass(Item.Tag).ClassName; + if StrLComp(PChar(S), 'TTBX', 4) = 0 then + begin + NewItem := TTBItem.Create(TB); + TB.Items.Add(NewItem); + NewItem.Caption := Item.Caption; + NewItem.ImageIndex := Item.ImageIndex; + NewItem.Tag := Item.Tag; + NewItem.Hint := S; + NewItem.OnClick := Item.OnClick; + end; + end; + end; +end; + +procedure Register; +begin + RegisterComponents('Toolbar2000', [TTBXDock, TTBXMultiDock, TTBXToolbar, + TTBXToolWindow, TTBXDockablePanel, TTBXPopupMenu, TTBXSwitcher, TTBXMRUList, + TTBXMDIHandler, TTBXPageScroller, TTBXColorSet, TTBXAlignmentPanel, + TTBXLabel, TTBXLink, TTBXButton, TTBXCheckBox, TTBXRadioButton, TTBXStatusBar]); + RegisterNoIcon([TTBXItem, TTBXSubMenuItem, TTBXSeparatorItem, + TTBXVisibilityToggleItem, TTBXLabelItem, TTBXMRUListItem, TTBXColorItem, + TTBXMDIWindowItem, TTBXEditItem, TTBXSpinEditItem, TTBXDropDownItem, + TTBXComboBoxItem, TTBXStringList, TTBXUndoList, TTBXToolPalette, TTBXColorPalette]); +{$IFDEF COMPATIBLE_CTL} + RegisterNoIcon([TTBXList, TTBXComboItem, TTBXComboList]); +{$ENDIF} + + RegisterClasses([TTBXItem, TTBXSubMenuItem, TTBXSeparatorItem, + TTBXVisibilityToggleItem, TTBXLabelItem, TTBXMRUListItem, TTBXColorItem, + TTBXMDIWindowItem, TTBXEditItem, TTBXSpinEditItem, TTBXDropDownItem, + TTBXComboBoxItem, TTBXStringList, TTBXUndoList, TTBXToolPalette, TTBXColorPalette]); +{$IFDEF COMPATIBLE_CTL} + RegisterClasses([TTBXList, TTBXComboItem, TTBXComboList]); +{$ENDIF} + + + RegisterComponentEditor(TTBXToolbar, TTBXItemsEditor); + RegisterComponentEditor(TTBXPopupMenu, TTBXItemsEditor); + RegisterPropertyEditor(TypeInfo(string), TTBXCustomItem, 'Caption', TMLStringProperty); + RegisterPropertyEditor(TypeInfo(string), TTBXCustomItem, 'Hint', TMLStringProperty); + RegisterPropertyEditor(TypeInfo(string), TTBXLabelItem, 'Caption', TCaptionProperty); + RegisterPropertyEditor(TypeInfo(string), TTBToolbar, 'ChevronHint', TMLStringProperty); + RegisterPropertyEditor(TypeInfo(string), TTBXToolbar, 'ChevronHint', TMLStringProperty); + RegisterPropertyEditor(TypeInfo(string), TTBXSwitcher, 'Theme', TThemeProperty); +{$IFDEF JR_D5} + RegisterPropertyEditor(TypeInfo(TImageIndex), TTBXCustomLink, 'ImageIndex', TTBXLinkImageIndexPropertyEditor); + RegisterPropertyEditor(TypeInfo(TImageIndex), TTBXCustomButton, 'ImageIndex', TTBXLinkImageIndexPropertyEditor); +{$ENDIF} +{$IFDEF NEWCOLORPROPERTY} + RegisterPropertyEditor(TypeInfo(TColor), TPersistent, '', TTBXColorProperty); +{$ENDIF} + + RegisterComponentEditor(TTBXStatusBar, TTBXStatusBarEditor); + + TBRegisterItemClass(TTBXItem, 'New &TBX Item', HInstance); + TBRegisterItemClass(TTBXSubMenuItem, 'New TBX Submenu Item', HInstance); + TBRegisterItemClass(TTBXSeparatorItem, 'New TBX Separator Item', HInstance); + TBRegisterItemClass(TTBXVisibilityToggleItem, 'New TBX Visibility Toggle Item', HInstance); + TBRegisterItemClass(TTBXLabelItem, 'New TBX Label Item', HInstance); + TBRegisterItemClass(TTBXMRUListItem, 'New TBX MRU List Item', HInstance); + TBRegisterItemClass(TTBXColorItem, 'New TBX Color Item', HInstance); + TBRegisterItemClass(TTBXMDIWindowItem, 'New TBX MDI Window Item', HInstance); + TBRegisterItemClass(TTBXEditItem, 'New TBX Edit Item', HInstance); + TBRegisterItemClass(TTBXSpinEditItem, 'New TBX Spin Edit Item', HInstance); + TBRegisterItemClass(TTBXDropDownItem, 'New TBX Drop Down Item', HInstance); + TBRegisterItemClass(TTBXComboBoxItem, 'New TBX Combo Box Item', HInstance); + TBRegisterItemClass(TTBXStringList, 'New TBX String List', HInstance); + TBRegisterItemClass(TTBXUndoList, 'New TBX Undo List', HInstance); + TBRegisterItemClass(TTBXToolPalette, 'New TBX Tool Palette', HInstance); + TBRegisterItemClass(TTBXColorPalette, 'New TBX Color Palette', HInstance); +{$IFDEF COMPATIBLE_CTL} + TBRegisterItemClass(TTBXComboItem, 'New TBX Combo Item (use TBX DropDown instead)', HInstance); + TBRegisterItemClass(TTBXList, 'New TBX List (use TBX String List instead)', HInstance); + TBRegisterItemClass(TTBXComboList, 'New TBX Combo List (use TBX Combo Box Instead)', HInstance); +{$ENDIF} + +end; + +initialization + O := THookObj.Create; + TBUnregisterDsgnEditorHook(O.HookProc); + TBRegisterDsgnEditorHook(O.HookProc); + +finalization + TBUnregisterDsgnEditorHook(O.HookProc); + O.Free; + +end. diff --git a/official/2.1.6+2.1.beta1/TBX/TBXReg.pas.orig b/official/2.1.6+2.1.beta1/TBX/TBXReg.pas.orig new file mode 100644 index 0000000..ddb2468 --- /dev/null +++ b/official/2.1.6+2.1.beta1/TBX/TBXReg.pas.orig @@ -0,0 +1,485 @@ +unit TBXReg; + +// TBX Package +// Copyright 2001-2004 Alex A. Denisov. All Rights Reserved +// See TBX.chm for license and installation instructions +// +// $Id: TBXReg.pas 16 2004-05-26 02:02:55Z Alex@ZEISS $ + +interface + +{$I TB2Ver.inc} +{$I TBX.inc} + +uses + Windows, Classes, Controls, SysUtils, Graphics, ImgList, Dialogs, + {$IFDEF JR_D6} DesignIntf, DesignEditors, VCLEditors, {$ELSE} DsgnIntf, {$ENDIF} + TB2Reg, TB2Toolbar, TB2Item, TBX, TBXMDI, TBXSwitcher, TB2DsgnItemEditor, + TBXExtItems, TBXLists, TBXDkPanels, TBXToolPals, TBXStatusBars; + +procedure Register; + +type + TThemeProperty = class(TStringProperty) + function GetAttributes: TPropertyAttributes; override; + procedure GetValues(Proc: TGetStrProc); override; + end; + + TMLStringProperty = class(TCaptionProperty) + function GetAttributes: TPropertyAttributes; override; + procedure Edit; override; + end; + +{$IFDEF JR_D5} + TTBXLinkImageIndexPropertyEditor = class(TTBImageIndexPropertyEditor) + public + function GetImageListAt(Index: Integer): TCustomImageList; override; + end; +{$ENDIF} + + TTBXColorProperty = class(TColorProperty) + public + function GetValue: string; override; + procedure GetValues(Proc: TGetStrProc); override; + procedure SetValue(const Value: string); override; +{$IFDEF JR_D5} + procedure ListDrawValue(const Value: string; ACanvas: TCanvas; + const ARect: TRect; ASelected: Boolean);{$IFNDEF JR_D6} override;{$ENDIF} +{$ENDIF} + end; + + TTBXStatusBarEditor = class(TDefaultEditor) + protected +{$IFDEF JR_D6} + procedure GetPanelsProp(const Prop: IProperty); +{$ELSE} + procedure GetPanelsProp(Prop: TPropertyEditor); +{$ENDIF} + public + procedure Edit; override; + procedure ExecuteVerb(Index: Integer); override; + function GetVerb(Index: Integer): string; override; + function GetVerbCount: Integer; override; + end; + + TTBXItemsEditor = class(TTBItemsEditor) + public + procedure ExecuteVerb(Index: Integer); override; + end; + +implementation + +uses + Forms, TBXThemes, TBXStrEdit, TBXUtils, TypInfo, TB2Version; + +type + TTBXLinkAccess = class(TTBXCustomLink); + TTBXButtonAccess = class(TTBXCustomButton); + + +{ TThemeProperty } + +function TThemeProperty.GetAttributes: TPropertyAttributes; +begin + Result := [paMultiSelect, paValueList, paSortList, paRevertable]; +end; + +procedure TThemeProperty.GetValues(Proc: TGetStrProc); +var + SL: TStringList; + I: Integer; +begin + SL := TStringList.Create; + GetAvailableTBXThemes(SL); + for I := 0 to SL.Count - 1 do Proc(SL[I]); + SL.Free; +end; + +{ TMLStringProperty } + +function WordCount(const S: string; const Delims: TSysCharSet): Integer; +var + L, I: Cardinal; +begin + Result := 0; + I := 1; + L := Length(S); + while I <= L do + begin + while (I <= L) and (S[I] in Delims) do Inc(I); + if I <= L then Inc(Result); + while (I <= L) and not(S[I] in Delims) do Inc(I); + end; +end; + +function WordPosition(const N: Integer; const S: string; + const WordDelims: TSysCharSet): Integer; +var + Count, I: Integer; +begin + Count := 0; + I := 1; + Result := 0; + while (I <= Length(S)) and (Count <> N) do begin + { skip over delimiters } + while (I <= Length(S)) and (S[I] in WordDelims) do Inc(I); + { if we're not beyond end of S, we're at the start of a word } + if I <= Length(S) then Inc(Count); + { if not finished, find the end of the current word } + if Count <> N then + while (I <= Length(S)) and not (S[I] in WordDelims) do Inc(I) + else Result := I; + end; +end; + +function ExtractWord(N: Integer; const S: string; + const WordDelims: TSysCharSet): string; +var + I: Integer; + Len: Integer; +begin + Len := 0; + I := WordPosition(N, S, WordDelims); + if I <> 0 then + { find the end of the current word } + while (I <= Length(S)) and not(S[I] in WordDelims) do begin + { add the I'th character to result } + Inc(Len); + SetLength(Result, Len); + Result[Len] := S[I]; + Inc(I); + end; + SetLength(Result, Len); +end; + +procedure TMLStringProperty.Edit; +var + Temp: string; + Component: TPersistent; + I, N: Integer; +begin + with TStrEditDlg.Create(Application) do + try + Component := GetComponent(0); + if Component is TComponent then Caption := TComponent(Component).Name + '.' + GetName + else Caption := GetName; + + Temp := GetStrValue; + N := WordCount(Temp, [#13, #10]); + for I := 1 to N do Memo.Lines.Add(ExtractWord(I, Temp, [#13, #10])); + + Memo.MaxLength := GetEditLimit; + if ShowModal = mrOk then + begin + Temp := Memo.Text; + while (Length(Temp) > 0) and (Temp[Length(Temp)] < ' ') do + System.Delete(Temp, Length(Temp), 1); + SetStrValue(Temp); + end; + finally + Free; + end; +end; + +function TMLStringProperty.GetAttributes: TPropertyAttributes; +begin + Result := inherited GetAttributes + [paDialog]; +end; + +{$IFDEF JR_D5} +{ TTBXLinkImageIndexPropertyEditor } + +function TTBXLinkImageIndexPropertyEditor.GetImageListAt(Index: Integer): TCustomImageList; +var + C: TPersistent; +begin + Result := nil; + C := GetComponent(Index); + if C is TTBXCustomLink then + Result := TTBXLinkAccess(C).Images + else if C is TTBXCustomButton then + Result := TTBXButtonAccess(C).Images; +end; +{$ENDIF} + +{ TTBXColorProperty } + +function TTBXColorProperty.GetValue: string; +begin + Result := TBXColorToString(TColor(GetOrdValue)); +end; + +procedure TTBXColorProperty.GetValues(Proc: TGetStrProc); +begin + TBXGetColorValues(Proc); +end; + +procedure TTBXColorProperty.SetValue(const Value: string); +begin + SetOrdValue(TBXStringToColor(Value)); +end; + +{$IFDEF JR_D5} +procedure TTBXColorProperty.ListDrawValue(const Value: string; ACanvas: TCanvas; + const ARect: TRect; ASelected: Boolean); + + function ColorToBorderColor(AColor: TColor): TColor; + begin + if IsDarkColor(AColor) then + begin + Result := AColor; + SetContrast(Result, AColor, 40); + end + else Result := clBlack; + end; + +var + R: TRect; + C: TColor; + OldPenColor, OldBrushColor: TColor; +begin + R := ARect; + with ACanvas do + try + OldPenColor := Pen.Color; + OldBrushColor := Brush.Color; + Pen.Color := Brush.Color; + Rectangle(R); + R.Right := (ARect.Bottom - ARect.Top) + ARect.Left; + InflateRect(R, -1, -1); + C := TBXStringToColor(Value); + if C <> clNone then + begin + Brush.Color := C; + Pen.Color := ColorToBorderColor(ColorToRGB(C)); + Rectangle(R); + end + else + begin + Brush.Color := clWindow; + Pen.Color := clBtnShadow; + Rectangle(R); + MoveTo(R.Left, R.Bottom - 1); + LineTo(R.Right - 1, R.Top); + MoveTo(R.Left, R.Top); + LineTo(R.Right, R.Bottom); + end; + Brush.Color := OldBrushColor; + Pen.Color := OldPenColor; + finally + R.Left := R.Right; + R.Right := ARect.Right; + ACanvas.TextRect(R, R.Left + 1, R.Top + 1, Value); + end; +end; +{$ENDIF} + +{ TTBXStatusBarEditor } + +procedure TTBXStatusBarEditor.Edit; +var +{$IFDEF JR_D6} + Components: IDesignerSelections; +{$ELSE} + {$IFDEF JR_D5} + Components: TDesignerSelectionList; + {$ELSE} + Components: TComponentList; + {$ENDIF} +{$ENDIF} +begin +{$IFDEF JR_D6} + Components := CreateSelectionList; +{$ELSE} + {$IFDEF JR_D5} + Components := TDesignerSelectionList.Create; + {$ELSE} + Components := TComponentList.Create; + {$ENDIF} +{$ENDIF} + try + Components.Add(Component); + GetComponentProperties(Components, [tkClass], Designer, GetPanelsProp); + finally +{$IFNDEF JR_D6} + Components.Free; +{$ENDIF} + end; +end; + +procedure TTBXStatusBarEditor.ExecuteVerb(Index: Integer); +begin + if Index = 0 then Edit; +end; + +function TTBXStatusBarEditor.GetVerb(Index: Integer): string; +begin + if Index = 0 then Result := '&Panels Editor...'; +end; + +function TTBXStatusBarEditor.GetVerbCount: Integer; +begin + Result := 1; +end; + +{$IFDEF JR_D6} +procedure TTBXStatusBarEditor.GetPanelsProp(const Prop: IProperty); +begin + if SameText(Prop.GetName, 'Panels') then Prop.Edit; +end; +{$ELSE} +procedure TTBXStatusBarEditor.GetPanelsProp(Prop: TPropertyEditor); +begin + if CompareText(Prop.GetName, 'Panels') = 0 then Prop.Edit; +end; +{$ENDIF} + +{ TTBXItemsEditor } + +procedure TTBXItemsEditor.ExecuteVerb(Index: Integer); +const + AboutText = + '%s'#13#10 + + '20012004 Alex A. Denisov'#13#10 + + 'For conditions of distribution and use, see TBX documentation.'#13#10 + + 'Visit http://g32.org/tbx/ for the latest versions of TBX'#13#10 + + #13#10 + + 'Running on'#13#10 + + '%s'#13#10 + + '1998-2004 by Jordan Russell'#13#10 + + 'For conditions of distribution and use, see Toolbar2000 documentation.'#13#10 + + #13#10 + + 'Visit http://www.jrsoftware.org/ for the latest versions of Toolbar2000'#13#10 + + ''; +begin + case Index of + 0: Edit; + 1: + begin + MessageDlg( + Format(AboutText, + [TBXVersionText, Toolbar2000VersionPropText]), + mtInformation, [mbOK], 0); + end; + end; +end; + + +{ THookObj } + +type + THookObj = class + procedure HookProc(Sender: TTBItemEditForm); + end; + +var O: THookObj; + +procedure THookObj.HookProc(Sender: TTBItemEditForm); +var + TB: TTBToolbar; + Item: TTBCustomItem; + NewItem: TTBItem; + S: string; + I: Integer; +begin + TB := TTBToolbar.Create(Sender); + TB.Top := Sender.Height; + TB.Parent := Sender; + TB.Align := alTop; + TB.Images := Sender.ToolbarItems.SubMenuImages; + TB.ShowHint := True; + + for I := 0 to Sender.MoreMenu.Count - 1 do + begin + Item := Sender.MoreMenu.Items[I]; + if Item is TTBCustomItem then + begin + S := TTBCustomItemClass(Item.Tag).ClassName; + if StrLComp(PChar(S), 'TTBX', 4) = 0 then + begin + NewItem := TTBItem.Create(TB); + TB.Items.Add(NewItem); + NewItem.Caption := Item.Caption; + NewItem.ImageIndex := Item.ImageIndex; + NewItem.Tag := Item.Tag; + NewItem.Hint := S; + NewItem.OnClick := Item.OnClick; + end; + end; + end; +end; + +procedure Register; +begin + RegisterComponents('Toolbar2000', [TTBXDock, TTBXMultiDock, TTBXToolbar, + TTBXToolWindow, TTBXDockablePanel, TTBXPopupMenu, TTBXSwitcher, TTBXMRUList, + TTBXMDIHandler, TTBXPageScroller, TTBXColorSet, TTBXAlignmentPanel, + TTBXLabel, TTBXLink, TTBXButton, TTBXCheckBox, TTBXRadioButton, TTBXStatusBar]); + RegisterNoIcon([TTBXItem, TTBXSubMenuItem, TTBXSeparatorItem, + TTBXVisibilityToggleItem, TTBXLabelItem, TTBXMRUListItem, TTBXColorItem, + TTBXMDIWindowItem, TTBXEditItem, TTBXSpinEditItem, TTBXDropDownItem, + TTBXComboBoxItem, TTBXStringList, TTBXUndoList, TTBXToolPalette, TTBXColorPalette]); +{$IFDEF COMPATIBLE_CTL} + RegisterNoIcon([TTBXList, TTBXComboItem, TTBXComboList]); +{$ENDIF} + + RegisterClasses([TTBXItem, TTBXSubMenuItem, TTBXSeparatorItem, + TTBXVisibilityToggleItem, TTBXLabelItem, TTBXMRUListItem, TTBXColorItem, + TTBXMDIWindowItem, TTBXEditItem, TTBXSpinEditItem, TTBXDropDownItem, + TTBXComboBoxItem, TTBXStringList, TTBXUndoList, TTBXToolPalette, TTBXColorPalette]); +{$IFDEF COMPATIBLE_CTL} + RegisterClasses([TTBXList, TTBXComboItem, TTBXComboList]); +{$ENDIF} + + + RegisterComponentEditor(TTBXToolbar, TTBXItemsEditor); + RegisterComponentEditor(TTBXPopupMenu, TTBXItemsEditor); + RegisterPropertyEditor(TypeInfo(string), TTBXCustomItem, 'Caption', TMLStringProperty); + RegisterPropertyEditor(TypeInfo(string), TTBXLabelItem, 'Caption', TCaptionProperty); + RegisterPropertyEditor(TypeInfo(string), TTBToolbar, 'ChevronHint', TMLStringProperty); + RegisterPropertyEditor(TypeInfo(string), TTBXToolbar, 'ChevronHint', TMLStringProperty); + RegisterPropertyEditor(TypeInfo(string), TTBXSwitcher, 'Theme', TThemeProperty); +{$IFDEF JR_D5} + RegisterPropertyEditor(TypeInfo(TImageIndex), TTBXCustomLink, 'ImageIndex', TTBXLinkImageIndexPropertyEditor); + RegisterPropertyEditor(TypeInfo(TImageIndex), TTBXCustomButton, 'ImageIndex', TTBXLinkImageIndexPropertyEditor); +{$ENDIF} +{$IFDEF NEWCOLORPROPERTY} + RegisterPropertyEditor(TypeInfo(TColor), TPersistent, '', TTBXColorProperty); +{$ENDIF} + + RegisterComponentEditor(TTBXStatusBar, TTBXStatusBarEditor); + + TBRegisterItemClass(TTBXItem, 'New &TBX Item', HInstance); + TBRegisterItemClass(TTBXSubMenuItem, 'New TBX Submenu Item', HInstance); + TBRegisterItemClass(TTBXSeparatorItem, 'New TBX Separator Item', HInstance); + TBRegisterItemClass(TTBXVisibilityToggleItem, 'New TBX Visibility Toggle Item', HInstance); + TBRegisterItemClass(TTBXLabelItem, 'New TBX Label Item', HInstance); + TBRegisterItemClass(TTBXMRUListItem, 'New TBX MRU List Item', HInstance); + TBRegisterItemClass(TTBXColorItem, 'New TBX Color Item', HInstance); + TBRegisterItemClass(TTBXMDIWindowItem, 'New TBX MDI Window Item', HInstance); + TBRegisterItemClass(TTBXEditItem, 'New TBX Edit Item', HInstance); + TBRegisterItemClass(TTBXSpinEditItem, 'New TBX Spin Edit Item', HInstance); + TBRegisterItemClass(TTBXDropDownItem, 'New TBX Drop Down Item', HInstance); + TBRegisterItemClass(TTBXComboBoxItem, 'New TBX Combo Box Item', HInstance); + TBRegisterItemClass(TTBXStringList, 'New TBX String List', HInstance); + TBRegisterItemClass(TTBXUndoList, 'New TBX Undo List', HInstance); + TBRegisterItemClass(TTBXToolPalette, 'New TBX Tool Palette', HInstance); + TBRegisterItemClass(TTBXColorPalette, 'New TBX Color Palette', HInstance); +{$IFDEF COMPATIBLE_CTL} + TBRegisterItemClass(TTBXComboItem, 'New TBX Combo Item (use TBX DropDown instead)', HInstance); + TBRegisterItemClass(TTBXList, 'New TBX List (use TBX String List instead)', HInstance); + TBRegisterItemClass(TTBXComboList, 'New TBX Combo List (use TBX Combo Box Instead)', HInstance); +{$ENDIF} + +end; + +initialization + O := THookObj.Create; + TBUnregisterDsgnEditorHook(O.HookProc); + TBRegisterDsgnEditorHook(O.HookProc); + +finalization + TBUnregisterDsgnEditorHook(O.HookProc); + O.Free; + +end. diff --git a/official/2.1.6+2.1.beta1/TBX/TBXStatusBars.pas b/official/2.1.6+2.1.beta1/TBX/TBXStatusBars.pas new file mode 100644 index 0000000..abb7c00 --- /dev/null +++ b/official/2.1.6+2.1.beta1/TBX/TBXStatusBars.pas @@ -0,0 +1,1030 @@ +unit TBXStatusBars; + +// TBX Package +// Copyright 2001-2004 Alex A. Denisov. All Rights Reserved +// See TBX.chm for license and installation instructions +// +// $Id: TBXStatusBars.pas 15 2004-05-15 04:45:26Z Alex@ZEISS $ + +interface + +{$I ..\..\Source\TB2Ver.inc} +{$I TBX.inc} + +uses + Windows, Messages, Classes, SysUtils, Controls, Forms, Graphics, TBX, + TBXThemes, TB2ITem, ImgList; + +type + TTBXCustomStatusBar = class; + + TPercent = 0..100; + + TTBXStatusPanel = class(TCollectionItem) + private + FAlignment: TAlignment; + FCaption: TCaption; + FControl: TControl; + FEnabled: Boolean; + FFramed: Boolean; + FFontSettings: TFontSettings; + FHint: string; + FImageIndex: TImageIndex; + FMaxSize: Integer; + FSize: Integer; + FStretchPriority: TPercent; + FTag: Integer; + FTextTruncation: TTextTruncation; + FViewPriority: TPercent; + procedure FontSettingsChanged(Sender: TObject); + procedure SetAlignment(Value: TAlignment); + procedure SetCaption(const Value: TCaption); + procedure SetControl(Value: TControl); + procedure SetEnabled(Value: Boolean); + procedure SetFramed(Value: Boolean); + procedure SetImageIndex(Value: TImageIndex); + procedure SetMaxSize(Value: Integer); + procedure SetSize(Value: Integer); + procedure SetStretchPriority(Value: TPercent); + procedure SetTextTruncation(Value: TTextTruncation); + procedure SetViewPriority(Value: TPercent); + procedure SetFontSettings(const Value: TFontSettings); + protected + CachedBounds: TRect; + CachedSize: Integer; + CachedVisible: Boolean; + CachedGripper: Boolean; + function StatusBar: TTBXCustomStatusBar; + function GetDisplayName: string; override; + public + constructor Create(Collection: TCollection); override; + destructor Destroy; override; + procedure Assign(Source: TPersistent); override; + property BoundsRect: TRect read CachedBounds; + property Visible: Boolean read CachedVisible; + published + property Alignment: TAlignment read FAlignment write SetAlignment default taLeftJustify; + property Caption: TCaption read FCaption write SetCaption; + property Control: TControl read FControl write SetControl; + property Enabled: Boolean read FEnabled write SetEnabled default True; + property Framed: Boolean read FFramed write SetFramed default True; + property FontSettings: TFontSettings read FFontSettings write SetFontSettings; + property Hint: string read FHint write FHint; + property ImageIndex: TImageIndex read FImageIndex write SetImageIndex default -1; + property MaxSize: Integer read FMaxSize write SetMaxSize default 0; + property ViewPriority: TPercent read FViewPriority write SetViewPriority default 100; + property Size: Integer read FSize write SetSize default 50; + property StretchPriority: TPercent read FStretchPriority write SetStretchPriority default 0; + property Tag: Integer read FTag write FTag; + property TextTruncation: TTextTruncation read FTextTruncation write SetTextTruncation default twNone; + end; + + TTBXStatusPanels = class(TCollection) + private + FStatusBar: TTBXCustomStatusBar; + function GetItem(Index: Integer): TTBXStatusPanel; + procedure SetItem(Index: Integer; Value: TTBXStatusPanel); + protected + function GetOwner: TPersistent; override; + procedure Update(Item: TCollectionItem); override; + public + constructor Create(AStatusBar: TTBXCustomStatusBar); + function Add: TTBXStatusPanel; + function FindPanel(AControl: TControl): TTBXStatusPanel; + property StatusBar: TTBXCustomStatusBar read FStatusBar; + property Items[Index: Integer]: TTBXStatusPanel read GetItem write SetItem; default; + end; + + TSBAdjustContentRect = procedure(Sender: TTBXCustomStatusBar; Panel: TTBXStatusPanel; var ARect: TRect) of object; + TSBAdjustFont = procedure(Sender: TTBXCustomStatusBar; Panel: TTBXStatusPanel; AFont: TFont) of object; + TSBPanelEvent = procedure(Sender: TTBXCustomStatusBar; Panel: TTBXStatusPanel) of object; + + TTBXCustomStatusBar = class(TCustomControl) + private + FPanels: TTBXStatusPanels; + FImageChangeLink: TChangeLink; + FImages: TCustomImageList; + FSimplePanel: Boolean; + FSimpleText: TCaption; + FSizeGrip: Boolean; + FUpdateCount: Integer; + FUseSystemFont: Boolean; + FOnAdjustContentRect: TSBAdjustContentRect; + FOnAdjustFont: TSBAdjustFont; + FOnPanelClick: TSBPanelEvent; + FOnPanelDblClick: TSBPanelEvent; + FFixAlign: Boolean; + procedure CMControlChange(var Message: TCMControlChange); message CM_CONTROLCHANGE; + procedure CMFontChanged(var Message: TMessage); message CM_FONTCHANGED; + procedure CMHintShow(var Message: TCMHintShow); message CM_HINTSHOW; + procedure CMVisibleChanged(var Message: TMessage); message CM_VISIBLECHANGED; + procedure ImageListChange(Sender: TObject); + procedure SetImages(Value: TCustomImageList); + procedure SetPanels(Value: TTBXStatusPanels); + procedure SetSimplePanel(Value: Boolean); + procedure SetSimpleText(const Value: TCaption); + procedure SetSizeGrip(Value: Boolean); + procedure SetUseSystemFont(Value: Boolean); + procedure TBMThemeChange(var Message); message TBM_THEMECHANGE; + procedure WMEraseBkgnd(var Message: TWMEraseBkgnd); message WM_ERASEBKGND; + procedure WMNCHitTest(var Message: TWMNCHitTest); message WM_NCHITTEST; + protected + CachedPanelMargins: TTBXMargins; + procedure AdjustPanelContentRect(APanel: TTBXStatusPanel; var ARect: TRect); virtual; + procedure AlignControls(AControl: TControl; var Rect: TRect); override; + procedure BeginUpdate; + procedure Change; dynamic; + procedure ChangeScale(M, D: Integer); override; + procedure Click; override; + procedure CreateParams(var Params: TCreateParams); override; + procedure CreateWnd; override; + procedure DblClick; override; + procedure DoAdjustFont(APanel: TTBXStatusPanel; AFont: TFont); virtual; + procedure DoPanelClick(APanel: TTBXStatusPanel); virtual; + procedure DoPanelDblClick(APanel: TTBXStatusPanel); virtual; + procedure EndUpdate; + function GetGripperRect: TRect; + procedure Loaded; override; + function IsSizeGripVisible: Boolean; + procedure Notification(AComponent: TComponent; Operation: TOperation); override; + procedure Paint; override; + procedure PaintPanel(ARect: TRect; APanel: TTBXStatusPanel; IsLast: Boolean); virtual; + procedure Resize; override; + procedure UpdateCache; virtual; + procedure UpdatePanels; virtual; + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + function GetPanelAt(const Pt: TPoint): TTBXStatusPanel; overload; + function GetPanelAt(X, Y: Integer): TTBXStatusPanel; overload; + function GetPanelRect(APanel: TTBXStatusPanel): TRect; + procedure FlipChildren(AllLevels: Boolean); override; + property Align default alBottom; + property FixAlign: Boolean read FFixAlign write FFixAlign default False; + property DoubleBuffered default True; + property Images: TCustomImageList read FImages write SetImages; + property Panels: TTBXStatusPanels read FPanels write SetPanels; + property SimplePanel: Boolean read FSimplePanel write SetSimplePanel default False; + property SimpleText: TCaption read FSimpleText write SetSimpleText; + property SizeGrip: Boolean read FSizeGrip write SetSizeGrip default True; + property UseSystemFont: Boolean read FUseSystemFont write SetUseSystemFont; + property OnAdjustContentRect: TSBAdjustContentRect read FOnAdjustContentRect write FOnAdjustContentRect; + property OnAdjustFont: TSBAdjustFont read FOnAdjustFont write FOnAdjustFont; + property OnPanelClick: TSBPanelEvent read FOnPanelClick write FOnPanelClick; + property OnPanelDblClick: TSBPanelEvent read FOnPanelDblClick write FOnPanelDblClick; + published + property Height default 22; + end; + + TTBXStatusBar = class(TTBXCustomStatusBar) + published + property Action; + property Align; + property Anchors; + property Constraints; + property Ctl3D; + property DoubleBuffered; + property DragCursor; + property DragKind; + property DragMode; + property Enabled; + property FixAlign; + property Font; + property Images; + property Panels; + property ParentFont; + property ParentShowHint; + property PopupMenu; + property SimplePanel; + property SimpleText; + property SizeGrip; + property ShowHint; + property UseSystemFont; + property Visible; + property OnAdjustContentRect; + property OnClick; +{$IFDEF JR_D5} + property OnContextPopup; +{$ENDIF} + property OnDblClick; + property OnDragDrop; + property OnDragOver; + property OnEndDock; + property OnEndDrag; + property OnMouseDown; + property OnMouseMove; + property OnMouseUp; + property OnPanelClick; + property OnPanelDblClick; + property OnResize; + property OnStartDock; + property OnStartDrag; + end; + +implementation + +uses TBXUtils; + +type TFontSettingsAccess = class(TFontSettings); + +function CompareViewPriorities(Item1, Item2: Pointer): Integer; +var + P1, P2: TTBXStatusPanel; +begin + P1 := TTBXStatusPanel(Item1); + P2 := TTBXStatusPanel(Item2); + Result := P2.ViewPriority - P1.ViewPriority; +end; + +function CompareStretchPriorities(Item1, Item2: Pointer): Integer; +var + P1, P2: TTBXStatusPanel; +begin + P1 := TTBXStatusPanel(Item1); + P2 := TTBXStatusPanel(Item2); + Result := P1.StretchPriority - P2.StretchPriority; +end; + +{ TTBXStatusPanel } + +procedure TTBXStatusPanel.Assign(Source: TPersistent); + + function FindControl(AControl: TControl): TControl; + begin + if AControl <> nil then + Result := StatusBar.Owner.FindComponent(AControl.Name) as TControl + else + Result := nil; + end; + +begin + if Source is TTBXStatusPanel then + begin + ViewPriority := TTBXStatusPanel(Source).ViewPriority; + Control := FindControl(TTBXStatusPanel(Source).Control); + end + else inherited Assign(Source); +end; + +constructor TTBXStatusPanel.Create(Collection: TCollection); +begin + inherited Create(Collection); + FSize := 50; + FEnabled := True; + FFramed := True; + FImageIndex := -1; + FViewPriority := 100; + FFontSettings := TFontSettings.Create; + TFontSettingsAccess(FFontSettings).OnChange := FontSettingsChanged; +end; + +destructor TTBXStatusPanel.Destroy; +var + AControl: TControl; +begin + AControl := Control; + FControl := nil; + FFontSettings.Free; + inherited Destroy; + if (AControl <> nil) and not (csDestroying in AControl.ComponentState) and + ((AControl is TWinControl) and TWinControl(AControl).HandleAllocated) then + begin + AControl.BringToFront; + AControl.Perform(CM_SHOWINGCHANGED, 0, 0); + end; +end; + +function TTBXStatusPanel.GetDisplayName: string; +begin + Result := Caption; + if (Result = '') and (Control <> nil) then Result := '[ ' + Control.Name + ' ]'; + if Result = '' then Result := inherited GetDisplayName; +end; + +procedure TTBXStatusPanel.SetAlignment(Value: TAlignment); +begin + FAlignment := Value; + Changed(False); +end; + +procedure TTBXStatusPanel.SetCaption(const Value: TCaption); +begin + if Value <> FCaption then + begin + FCaption := Value; + Changed(False); + end; +end; + +procedure TTBXStatusPanel.SetControl(Value: TControl); +var + Panel: TTBXStatusPanel; + PrevControl: TControl; + P: TControl; +begin + if FControl <> Value then + begin + if Value <> nil then + begin + P := StatusBar; + while P <> nil do + if P = Value then raise EInvalidOperation.Create('Can''t insert own parent') + else P := P.Parent; + + Panel := TTBXStatusPanels(Collection).FindPanel(Value); + if (Panel <> nil) and (Panel <> Self) then Panel.SetControl(nil); + end; + PrevControl := FControl; + FControl := Value; + FControl.Parent := StatusBar; + if Value <> nil then Value.FreeNotification(StatusBar); + Changed(True); + if PrevControl <> nil then PrevControl.Perform(CM_SHOWINGCHANGED, 0, 0); + end; +end; + +procedure TTBXStatusPanel.SetEnabled(Value: Boolean); +begin + if Value <> FEnabled then + begin + FEnabled := Value; + Changed(False); + end; +end; + +procedure TTBXStatusPanel.SetFramed(Value: Boolean); +begin + if Value <> FFramed then + begin + FFramed := Value; + Changed(False); + end; +end; + +procedure TTBXStatusPanel.SetMaxSize(Value: Integer); +begin + if Value <> FMaxSize then + begin + FMaxSize := Value; + Changed(True); + end; +end; + +procedure TTBXStatusPanel.SetViewPriority(Value: TPercent); +begin + if Value <> FViewPriority then + begin + FViewPriority := Value; + Changed(True); + end; +end; + +procedure TTBXStatusPanel.SetSize(Value: Integer); +begin + if Value <> FSize then + begin + FSize := Value; + Changed(True); + end; +end; + +procedure TTBXStatusPanel.SetStretchPriority(Value: TPercent); +begin + if Value <> FStretchPriority then + begin + FStretchPriority := Value; + Changed(True); + end; +end; + +procedure TTBXStatusPanel.SetTextTruncation(Value: TTextTruncation); +begin + FTextTruncation := Value; + Changed(False); +end; + +function TTBXStatusPanel.StatusBar: TTBXCustomStatusBar; +begin + Result := TTBXStatusPanels(Collection).StatusBar; +end; + +procedure TTBXStatusPanel.SetImageIndex(Value: TImageIndex); +begin + if Value <> FImageIndex then + begin + FImageIndex := Value; + if StatusBar.Images <> nil then Changed(False); + end; +end; + +procedure TTBXStatusPanel.FontSettingsChanged(Sender: TObject); +begin + Changed(False); +end; + +procedure TTBXStatusPanel.SetFontSettings(const Value: TFontSettings); +begin + FFontSettings := Value; +end; + +{ TTBXStatusPanels } + +function TTBXStatusPanels.Add: TTBXStatusPanel; +begin + Result := TTBXStatusPanel(inherited Add); +end; + +constructor TTBXStatusPanels.Create(AStatusBar: TTBXCustomStatusBar); +begin + inherited Create(TTBXStatusPanel); + FStatusBar := AStatusBar; +end; + +function TTBXStatusPanels.FindPanel(AControl: TControl): TTBXStatusPanel; +var + I: Integer; +begin + for I := 0 to Count - 1 do + begin + Result := TTBXStatusPanel(inherited GetItem(I)); + if Result.FControl = AControl then Exit; + end; + Result := nil; +end; + +function TTBXStatusPanels.GetItem(Index: Integer): TTBXStatusPanel; +begin + Result := TTBXStatusPanel(inherited GetItem(Index)); +end; + +function TTBXStatusPanels.GetOwner: TPersistent; +begin + Result := FStatusBar; +end; + +procedure TTBXStatusPanels.SetItem(Index: Integer; Value: TTBXStatusPanel); +begin + inherited SetItem(Index, Value); +end; + +procedure TTBXStatusPanels.Update(Item: TCollectionItem); +begin + FStatusBar.UpdatePanels; +end; + +{ TTBXCustomStatusBar } + +procedure TTBXCustomStatusBar.AdjustPanelContentRect(APanel: TTBXStatusPanel; var ARect: TRect); +begin + if APanel.Framed then + with CachedPanelMargins do + begin + Inc(ARect.Left, LeftWidth); + Inc(ARect.Top, TopHeight); + Dec(ARect.Right, RightWidth); + Dec(ARect.Bottom, BottomHeight); + end; + if Assigned(FOnAdjustContentRect) then FOnAdjustContentRect(Self, APanel, ARect); +end; + +procedure TTBXCustomStatusBar.AlignControls(AControl: TControl; var Rect: TRect); +begin + if not (csDestroying in ComponentState) and (FUpdateCount = 0) and + ((AControl = nil) and (Panels.Count > 0) or (AControl is TWinControl)) then + begin + Invalidate; + UpdatePanels; + end; +end; + +procedure TTBXCustomStatusBar.BeginUpdate; +begin + Inc(FUpdateCount); +end; + +procedure TTBXCustomStatusBar.Change; +var + Form: TCustomForm; +begin + if csDesigning in ComponentState then + begin + Form := GetParentForm(Self); + if (Form <> nil) and (Form.Designer <> nil) then Form.Designer.Modified; + end; +end; + +procedure TTBXCustomStatusBar.ChangeScale(M, D: Integer); +begin + if UseSystemFont then ScalingFlags := [sfTop]; + inherited; +end; + +procedure TTBXCustomStatusBar.Click; +var + Pt: TPoint; + Panel: TTBXStatusPanel; +begin + inherited; + GetCursorPos(Pt); + Panel := GetPanelAt(ScreenToClient(Pt)); + if Panel <> nil then DoPanelClick(Panel); +end; + +procedure TTBXCustomStatusBar.CMControlChange(var Message: TCMControlChange); +var + Panel: TTBXStatusPanel; +begin + if FUpdateCount = 0 then + begin + { Can only accept TWinControl descendants } + if not (csLoading in ComponentState) then + if Message.Inserting and (Message.Control is TWinControl) then + begin + with Panels.Add do SetControl(Message.Control); + end + else + begin + Panel := Panels.FindPanel(Message.Control); + if Panel <> nil then Panel.Free; + end; + end; +end; + +procedure TTBXCustomStatusBar.CMFontChanged(var Message: TMessage); +begin + inherited; + UpdatePanels; + Invalidate; +end; + +procedure TTBXCustomStatusBar.CMHintShow(var Message: TCMHintShow); +var + Panel: TTBXStatusPanel; +begin + Panel := GetPanelAt(Message.HintInfo.CursorPos); + if Panel <> nil then + begin + Message.HintInfo.HintStr := Panel.Hint; + Message.HintInfo.CursorRect := Panel.BoundsRect; + end; +end; + +procedure TTBXCustomStatusBar.CMVisibleChanged(var Message: TMessage); +begin + if FixAlign and (Parent <> nil) then Top := Parent.ClientHeight; + inherited; +end; + +constructor TTBXCustomStatusBar.Create(AOwner: TComponent); +begin + inherited Create(AOwner); + ControlStyle := [csAcceptsControls, csCaptureMouse, csClickEvents, csDoubleClicks]; + if not (csDesigning in ComponentState) then ControlStyle := ControlStyle - [csOpaque]; + Height := 22; + Align := alBottom; + Width := 150; + FImageChangeLink := TChangeLink.Create; + FImageChangeLink.OnChange := ImageListChange; + FPanels := TTBXStatusPanels.Create(Self); + FSizeGrip := True; + DoubleBuffered := True; + AddThemeNotification(Self); +end; + +procedure TTBXCustomStatusBar.CreateParams(var Params: TCreateParams); +begin + inherited CreateParams(Params); + with Params do + WindowClass.style := WindowClass.style and not (CS_HREDRAW or CS_VREDRAW); +end; + +procedure TTBXCustomStatusBar.CreateWnd; +begin + inherited CreateWnd; + if not (csLoading in ComponentState) then UpdatePanels; +end; + +procedure TTBXCustomStatusBar.DblClick; +var + Pt: TPoint; + Panel: TTBXStatusPanel; +begin + inherited; + GetCursorPos(Pt); + Panel := GetPanelAt(ScreenToClient(Pt)); + if Panel <> nil then DoPanelDblClick(Panel); +end; + +destructor TTBXCustomStatusBar.Destroy; +begin + RemoveThemeNotification(Self); + FImageChangeLink.Free; + FPanels.Free; + inherited Destroy; +end; + +procedure TTBXCustomStatusBar.DoAdjustFont(APanel: TTBXStatusPanel; AFont: TFont); +begin + { Changing AFont.Color will do nothing since it is replaced by the theme } + if Assigned(FOnAdjustFont) then FOnAdjustFont(Self, APanel, AFont); +end; + +procedure TTBXCustomStatusBar.DoPanelClick(APanel: TTBXStatusPanel); +begin + if Assigned(FOnPanelClick) then FOnPanelClick(Self, APanel); +end; + +procedure TTBXCustomStatusBar.DoPanelDblClick(APanel: TTBXStatusPanel); +begin + if Assigned(FOnPanelDblClick) then FOnPanelDblClick(Self, APanel); +end; + +procedure TTBXCustomStatusBar.EndUpdate; +begin + Dec(FUpdateCount); +end; + +procedure TTBXCustomStatusBar.FlipChildren(AllLevels: Boolean); +begin + { do not flip controls } +end; + +function TTBXCustomStatusBar.GetGripperRect: TRect; +begin + Result := ClientRect; + with Result do + begin + Inc(Top, 3); + Left := Right - GetSystemMetrics(SM_CXVSCROLL); + end; +end; + +function TTBXCustomStatusBar.GetPanelAt(const Pt: TPoint): TTBXStatusPanel; +var + I: Integer; +begin + for I := 0 to Panels.Count - 1 do + begin + Result := Panels[I]; + if Result.CachedVisible and PtInRect(Panels[I].BoundsRect, Pt) then Exit; + end; + Result := nil; +end; + +function TTBXCustomStatusBar.GetPanelAt(X, Y: Integer): TTBXStatusPanel; +begin + Result := GetPanelAt(Point(X, Y)); +end; + +function TTBXCustomStatusBar.GetPanelRect(APanel: TTBXStatusPanel): TRect; +begin + if (APanel <> nil) and APanel.CachedVisible then Result := APanel.CachedBounds + else Result := Rect(0, 0, 0, 0); +end; + +procedure TTBXCustomStatusBar.ImageListChange(Sender: TObject); +begin + if Sender = Images then Invalidate; +end; + +function TTBXCustomStatusBar.IsSizeGripVisible: Boolean; +var + ParentForm: TCustomForm; + PBR, BR: TPoint; +begin + Result := False; + if SizeGrip then + begin + ParentForm := GetParentForm(Self); + if (ParentForm <> nil) and (ParentForm.WindowState = wsNormal) then + begin + PBR := ParentForm.ClientToScreen(ParentForm.ClientRect.BottomRight); + BR := ClientToScreen(ClientRect.BottomRight); + Result := (PBR.X = BR.X) and (PBR.Y = BR.Y); + end; + end; +end; + +procedure TTBXCustomStatusBar.Loaded; +begin + inherited Loaded; + UpdatePanels; +end; + +procedure TTBXCustomStatusBar.Notification(AComponent: TComponent; Operation: TOperation); +var + Panel: TTBXStatusPanel; +begin + inherited Notification(AComponent, Operation); + if Operation = opRemove then + begin + if not (csDestroying in ComponentState) then + begin + Panel := Panels.FindPanel(TControl(AComponent)); + if Panel <> nil then Panel.FControl := nil; + end + else if AComponent = Images then Images := nil; + end; +end; + +procedure TTBXCustomStatusBar.Paint; +const + CEnabledState: array [Boolean] of Integer = (ISF_DISABLED, 0); +var + CR, R: TRect; + I: Integer; + Panel: TTBXStatusPanel; + PartID: Integer; + Flags: Cardinal; +begin + inherited; + CR := ClientRect; + CurrentTheme.PaintStatusBar(Canvas, CR, SBP_BODY); + Inc(CR.Top, 2); + if SimplePanel then + begin + if Length(SimpleText) > 0 then + begin + if UseSystemFont then Canvas.Font := ToolbarFont + else Canvas.Font := Self.Font; + Canvas.Font.Color := GetTBXTextColor(CEnabledState[Enabled]); + Canvas.Brush.Style := bsClear; + Flags := DT_SINGLELINE or DT_VCENTER; + InflateRect(CR, -4, 0); + DrawTBXCaption(Canvas, CR, SimpleText, Flags, ISF_STATUSCOLOR or CEnabledState[Enabled]); + Canvas.Brush.Style := bsSolid; + end; + end + else + for I := 0 to Panels.Count - 1 do + begin + Panel := Panels[I]; + if Panel.CachedVisible and RectVisible(Canvas.Handle, Panel.CachedBounds) then + begin + R := Panel.CachedBounds; + if Panel.Framed then + begin + if Panel.CachedGripper then PartID := SBP_LASTPANE + else PartID := SBP_PANE; + CurrentTheme.PaintStatusBar(Canvas, R, PartID); + end; + if UseSystemFont then Canvas.Font := ToolbarFont + else Canvas.Font := Self.Font; + Canvas.Font.Color := GetTBXTextColor(CEnabledState[Panel.Enabled]); + Panel.FontSettings.Apply(Canvas.Font); + DoAdjustFont(Panel, Canvas.Font); + AdjustPanelContentRect(Panel, R); + PaintPanel(R, Panel, I = Panels.Count - 1); + end; + end; + if IsSizeGripVisible then + CurrentTheme.PaintStatusBar(Canvas, GetGripperRect, SBP_GRIPPER); +end; + +procedure TTBXCustomStatusBar.PaintPanel(ARect: TRect; APanel: TTBXStatusPanel; IsLast: Boolean); +const + EnabledState: array [Boolean] of Integer = (ISF_DISABLED, 0); + Alignments: array [TAlignment] of Integer = (DT_LEFT, DT_RIGHT, DT_CENTER); + Truncations: array [TTextTruncation] of Integer = (0, DT_END_ELLIPSIS, DT_PATH_ELLIPSIS); +var + Flags: Integer; + R: TRect; +begin + InflateRect(ARect, -1, 0); + if (APanel.ImageIndex >= 0) and (Images <> nil) then + begin + R := ARect; + R.Top := (R.Top + R.Bottom - Images.Height) div 2; + R.Bottom := R.Top + Images.Height; + case APanel.Alignment of + taLeftJustify: + begin + R.Right := R.Left + Images.Width; + ARect.Left := R.Right + 4; + end; + taRightJustify: + begin + R.Left := R.Right - Images.Width; + ARect.Right := R.Left - 4; + end; + taCenter: + begin + R.Left := (R.Left + R.Right - Images.Width) div 2; + R.Right := R.Left + Images.Width; + end; + end; + if APanel.Enabled then Images.Draw(Canvas, R.Left, R.Top, APanel.ImageIndex) + else DrawTBXImage(Canvas, R, Images, APanel.ImageIndex, ISF_DISABLED); + end; + Canvas.Brush.Style := bsClear; + Flags := DT_SINGLELINE or DT_VCENTER or Alignments[APanel.Alignment] or Truncations[APanel.TextTruncation]; + DrawTBXCaption(Canvas, ARect, APanel.Caption, Flags, ISF_STATUSCOLOR or EnabledState[APanel.Enabled]); + Canvas.Brush.Style := bsSolid; +end; + +procedure TTBXCustomStatusBar.Resize; +begin + UpdatePanels; + Invalidate; + inherited; +end; + +procedure TTBXCustomStatusBar.SetImages(Value: TCustomImageList); +begin + if FImages <> nil then FImages.UnRegisterChanges(FImageChangeLink); + FImages := Value; + if FImages <> nil then + begin + FImages.RegisterChanges(FImageChangeLink); + FImages.FreeNotification(Self); + end; + Invalidate; +end; + +procedure TTBXCustomStatusBar.SetPanels(Value: TTBXStatusPanels); +begin + FPanels.Assign(Value); +end; + +procedure TTBXCustomStatusBar.SetSimplePanel(Value: Boolean); +begin + if FSimplePanel <> Value then + begin + FSimplePanel := Value; + Invalidate; + end; +end; + +procedure TTBXCustomStatusBar.SetSimpleText(const Value: TCaption); +begin + if FSimpleText <> Value then + begin + FSimpleText := Value; + Invalidate; + end; +end; + +procedure TTBXCustomStatusBar.SetSizeGrip(Value: Boolean); +begin + FSizeGrip := Value; + Invalidate; +end; + +procedure TTBXCustomStatusBar.SetUseSystemFont(Value: Boolean); +begin + if Value <> FUseSystemFont then + begin + FUseSystemFont := Value; + UpdatePanels; + Invalidate; + end; +end; + +procedure TTBXCustomStatusBar.TBMThemeChange(var Message); +begin + UpdatePanels; + Invalidate; +end; + +procedure TTBXCustomStatusBar.UpdateCache; +var + CR: TRect; + Position, I: Integer; + MaxWidth, WorkWidth: Integer; + TotalSize, Delta, NewSize: Integer; + SortList: TList; + Panel: TTBXStatusPanel; +begin + if Panels.Count = 0 then Exit; + CurrentTheme.GetMargins(MID_STATUSPANE, CachedPanelMargins); + CR := ClientRect; + Inc(CR.Top, 2); + Position := 0; + + MaxWidth := CR.Right - CR.Left; + WorkWidth := MaxWidth; + TotalSize := 0; + + SortList := TList.Create; + try + { First Pass: Gather the panels with non-zero ViewPriority } + for I := 0 to Panels.Count - 1 do + with Panels[I] do + begin + CachedGripper := False; + if ViewPriority > 0 then + begin + CachedSize := Size; + CachedVisible := True; + Inc(TotalSize, Size); + SortList.Add(Panels[I]) + end + else + CachedVisible := False; + end; + + SortList.Sort(CompareViewPriorities); + + { If necessary, hide the panels with low ViewPriority } + if TotalSize > WorkWidth then + begin + while (TotalSize > WorkWidth) and (SortList.Count > 1) and + (TTBXStatusPanel(SortList.Last).ViewPriority < 100) do + begin + TTBXStatusPanel(SortList.Last).CachedVisible := False; + Dec(TotalSize, TTBXStatusPanel(SortList.Last).Size); + SortList.Count := SortList.Count - 1; + end; + end; + + { Stretch to fill the empty space } + Delta := WorkWidth - TotalSize; + if Delta > 0 then + begin + for I := SortList.Count - 1 downto 0 do + if TTBXStatusPanel(SortList[I]).StretchPriority = 0 then SortList.Delete(I); + while (SortList.Count > 0) and (Delta > 0) do + begin + SortList.Sort(CompareStretchPriorities); + + { Start stretching with higher ViewPriority panels} + Panel := TTBXStatusPanel(SortList.Last); + NewSize := Panel.CachedSize + Delta; + if (Panel.MaxSize > Panel.CachedSize) and (NewSize > Panel.MaxSize) then + begin + NewSize := Panel.MaxSize; + Dec(Delta, NewSize - Panel.CachedSize); + end; + Panel.CachedSize := NewSize; + SortList.Count := SortList.Count - 1; + end; + end; + + for I := 0 to Panels.Count - 1 do + with Panels[I] do + begin + if Position >= WorkWidth then CachedVisible := False; + if CachedVisible then + begin + CachedBounds := CR; + CachedBounds.Left := Position; + Inc(Position, CachedSize); + if Position = WorkWidth then CachedGripper := True; + CachedBounds.Right := Position; + end + else CachedBounds := Rect(0, 0, 0, 0); + end; + + finally + SortList.Free; + end; +end; + +procedure TTBXCustomStatusBar.UpdatePanels; +var + I: Integer; + R: TRect; +begin + Invalidate; + UpdateCache; + for I := 0 to Panels.Count - 1 do + begin + with Panels[I] do + if Visible then + begin + if Control <> nil then + begin + R := CachedBounds; + if Framed then + with CachedPanelMargins do + begin + Inc(R.Left, LeftWidth); + Inc(R.Top, TopHeight); + Dec(R.Right, RightWidth); + Dec(R.Bottom, BottomHeight); + end; + Control.BoundsRect := R; + end; + end + else if Control <> nil then Control.BoundsRect := Rect(0, 0, 0, 0); + end; +end; + +procedure TTBXCustomStatusBar.WMEraseBkgnd(var Message: TWMEraseBkgnd); +begin + Message.Result := 1; +end; + +procedure TTBXCustomStatusBar.WMNCHitTest(var Message: TWMNCHitTest); +var + Pt: TPoint; +begin + inherited; + if (Message.Result = HTCLIENT) and IsSizeGripVisible then + begin + Pt := ScreenToClient(SmallPointToPoint(Message.Pos)); + if PtInRect(GetGripperRect, Pt) then Message.Result := HTBOTTOMRIGHT; + end; +end; + +end. diff --git a/official/2.1.6+2.1.beta1/TBX/TBXStrEdit.pas b/official/2.1.6+2.1.beta1/TBX/TBXStrEdit.pas new file mode 100644 index 0000000..8fc0a4a --- /dev/null +++ b/official/2.1.6+2.1.beta1/TBX/TBXStrEdit.pas @@ -0,0 +1,92 @@ +unit TBXStrEdit; + +// TBX Package +// Copyright 2001-2004 Alex A. Denisov. All Rights Reserved +// See TBX.chm for license and installation instructions +// +// $Id: TBXStrEdit.pas 7 2004-02-21 06:07:53Z $ + +interface + +uses + Windows, Messages, SysUtils, Classes, Controls, Forms, Dialogs, StdCtrls; + +type + TStrEditDlg = class(TForm) + Memo: TMemo; + OK: TButton; + Cancel: TButton; + procedure MemoKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); + protected + procedure ArrangeControls; + procedure Resize; override; + public + constructor Create(AOwner: TComponent); override; + end; + +implementation + +procedure TStrEditDlg.ArrangeControls; +var + R, B: TRect; + W, H: Integer; +begin + R := ClientRect; + InflateRect(R, -6, -6); + B := R; + W := 70; H := 23; + B.Left := B.Right - W; + B.Top := B.Bottom - H; + Cancel.BoundsRect := B; + B.Right := B.Left - 4; + B.Left := B.Right - W; + OK.BoundsRect := B; + Dec(R.Bottom, H + 8); + Memo.BoundsRect := R; +end; + +constructor TStrEditDlg.Create(AOwner: TComponent); +begin + inherited CreateNew(AOwner); + AutoScroll := False; + Constraints.MinHeight := 200; + Constraints.MinWidth := 300; + Scaled := False; + Position := poScreenCenter; + Memo := TMemo.Create(Self); + with Memo do + begin + ScrollBars := ssBoth; + OnKeyDown := MemoKeyDown; + Parent := Self; + end; + OK := TButton.Create(Self); + with OK do + begin + Caption := 'OK'; + Default := True; + ModalResult := mrOk; + Parent := Self; + end; + Cancel := TButton.Create(Self); + with Cancel do + begin + Cancel := True; + Caption := 'Cancel'; + ModalResult := mrCancel; + Parent := Self; + end; +end; + +procedure TStrEditDlg.MemoKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); +begin + if Key = VK_ESCAPE then Cancel.Click; +end; + +procedure TStrEditDlg.Resize; +begin + inherited; + ArrangeControls; +end; + +end. diff --git a/official/2.1.6+2.1.beta1/TBX/TBXStrEdit.pas.orig b/official/2.1.6+2.1.beta1/TBX/TBXStrEdit.pas.orig new file mode 100644 index 0000000..44559f1 --- /dev/null +++ b/official/2.1.6+2.1.beta1/TBX/TBXStrEdit.pas.orig @@ -0,0 +1,87 @@ +unit TBXStrEdit; + +// TBX Package +// Copyright 2001-2004 Alex A. Denisov. All Rights Reserved +// See TBX.chm for license and installation instructions +// +// $Id: TBXStrEdit.pas 7 2004-02-21 06:07:53Z $ + +interface + +uses + Windows, Messages, SysUtils, Classes, Controls, Forms, Dialogs, StdCtrls; + +type + TStrEditDlg = class(TForm) + Memo: TMemo; + OK: TButton; + Cancel: TButton; + procedure MemoKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); + protected + procedure ArrangeControls; + procedure Resize; override; + public + constructor Create(AOwner: TComponent); override; + end; + +implementation + +procedure TStrEditDlg.ArrangeControls; +var + R, B: TRect; + W, H: Integer; +begin + R := ClientRect; + InflateRect(R, -16, -16); + B := R; + W := 60; H := 23; + B.Left := B.Right - W; + B.Top := B.Bottom - H; + Cancel.BoundsRect := B; + B.Right := B.Left - 4; + B.Left := B.Right - W; + OK.BoundsRect := B; + Dec(R.Bottom, H + 8); + Memo.BoundsRect := R; +end; + +constructor TStrEditDlg.Create(AOwner: TComponent); +begin + inherited CreateNew(AOwner); + AutoScroll := False; + Scaled := False; + Position := poScreenCenter; + Memo := TMemo.Create(Self); + with Memo do + begin + ScrollBars := ssBoth; + OnKeyDown := MemoKeyDown; + end; + OK := TButton.Create(Self); + with OK do + begin + Caption := 'OK'; + Default := True; + ModalResult := mrOk; + end; + Cancel := TButton.Create(Self); + with Cancel do + begin + Cancel := True; + Caption := 'Cancel'; + ModalResult := mrCancel; + end; +end; + +procedure TStrEditDlg.MemoKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); +begin + if Key = VK_ESCAPE then Cancel.Click; +end; + +procedure TStrEditDlg.Resize; +begin + inherited; + ArrangeControls; +end; + +end. diff --git a/official/2.1.6+2.1.beta1/TBX/TBXSwitcher.pas b/official/2.1.6+2.1.beta1/TBX/TBXSwitcher.pas new file mode 100644 index 0000000..01e1c3a --- /dev/null +++ b/official/2.1.6+2.1.beta1/TBX/TBXSwitcher.pas @@ -0,0 +1,133 @@ +unit TBXSwitcher; + +// TBX Package +// Copyright 2001-2004 Alex A. Denisov. All Rights Reserved +// See TBX.chm for license and installation instructions +// +// $Id: TBXSwitcher.pas 7 2004-02-21 06:07:53Z $ + +interface + +{$I ..\..\Source\TB2Ver.inc} +{$I TBX.inc} + +uses + TBX, TBXThemes, Classes; + +type + TFlatMenuStyle = (fmsAuto, fmsEnable, fmsDisable); + + TTBXSwitcher = class(TComponent) + private + FOnThemeChange: TNotifyEvent; + procedure SetTheme(const Value: string); + function GetTheme: string; + function GetThemeCount: Integer; + function GetThemes(Index: Integer): string; + function GetEnableXPStyles: Boolean; + function GetFlatMenuStyle: TFlatMenuStyle; + procedure SetEnableXPStyles(Value: Boolean); + procedure SetFlatMenuStyle(Value: TFlatMenuStyle); + procedure TBMThemeChange(var Message); message TBM_THEMECHANGE; + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + property ThemeCount: Integer read GetThemeCount; + property Themes[Index: Integer]: string read GetThemes; + published + property Theme: string read GetTheme write SetTheme; + property EnableXPStyles: Boolean read GetEnableXPStyles write SetEnableXPStyles default True; + property FlatMenuStyle: TFlatMenuStyle read GetFlatMenuStyle write SetFlatMenuStyle default fmsAuto; + property OnThemeChange: TNotifyEvent read FOnThemeChange write FOnThemeChange; + end; + +implementation + +var + Counter: Integer = 0; + +{ TTBXSwitcher } + +constructor TTBXSwitcher.Create(AOwner: TComponent); +begin + inherited; + AddThemeNotification(Self); + Inc(Counter); +end; + +destructor TTBXSwitcher.Destroy; +begin + Dec(Counter); + RemoveThemeNotification(Self); + if (csDesigning in ComponentState) and (Counter = 0) then TBXSetTheme('Default'); + inherited; +end; + +function TTBXSwitcher.GetEnableXPStyles: Boolean; +begin + Result := GetTBXSysParam(TSP_XPVISUALSTYLE) = XPVS_AUTOMATIC; +end; + +function TTBXSwitcher.GetFlatMenuStyle: TFlatMenuStyle; +begin + case GetTBXSysParam(TSP_FLATMENUSTYLE) of + FMS_ENABLED: Result := fmsEnable; + FMS_DISABLED: Result := fmsDisable; + else + Result := fmsAuto; + end; +end; + +function TTBXSwitcher.GetTheme: string; +begin + Result := TBXCurrentTheme; +end; + +function TTBXSwitcher.GetThemeCount: Integer; +var + SL: TStringList; +begin + SL := TStringList.Create; + GetAvailableTBXThemes(SL); + Result := SL.Count; + SL.Free; +end; + +function TTBXSwitcher.GetThemes(Index: Integer): string; +var + SL: TStringList; +begin + SL := TStringList.Create; + GetAvailableTBXThemes(SL); + try + Result := SL[Index]; + finally + SL.Free; + end; +end; + +procedure TTBXSwitcher.SetEnableXPStyles(Value: Boolean); +const + XPVStyle: array [Boolean] of Integer = (XPVS_DISABLED, XPVS_AUTOMATIC); +begin + SetTBXSysParam(TSP_XPVISUALSTYLE, XPVStyle[Value]); +end; + +procedure TTBXSwitcher.SetFlatMenuStyle(Value: TFlatMenuStyle); +const + FMStyle: array [TFlatMenuStyle] of Integer = (FMS_AUTOMATIC, FMS_ENABLED, FMS_DISABLED); +begin + SetTBXSysParam(TSP_FLATMENUSTYLE, FMStyle[Value]); +end; + +procedure TTBXSwitcher.SetTheme(const Value: string); +begin + TBXSetTheme(Value); +end; + +procedure TTBXSwitcher.TBMThemeChange(var Message); +begin + if Assigned(FOnThemeChange) then FOnThemeChange(Self); +end; + +end. diff --git a/official/2.1.6+2.1.beta1/TBX/TBXThemes.pas b/official/2.1.6+2.1.beta1/TBX/TBXThemes.pas new file mode 100644 index 0000000..d853bdc --- /dev/null +++ b/official/2.1.6+2.1.beta1/TBX/TBXThemes.pas @@ -0,0 +1,897 @@ +unit TBXThemes; + +// TBX Package +// Copyright 2001-2004 Alex A. Denisov. All Rights Reserved +// See TBX.chm for license and installation instructions +// +// $Id: TBXThemes.pas 16 2004-05-26 02:02:55Z Alex@ZEISS $ + +interface + +{$I ..\..\Source\TB2Ver.inc} +{$I TBX.inc} + +uses + Windows, Messages, Classes, Forms, Graphics, ImgList; + +{ TBX_SYSCOMMAND message } +const + TBX_SYSCOMMAND = WM_USER + 312; + TSC_BEFOREVIEWCHANGE = 1; + TSC_VIEWCHANGE = 2; + TSC_AFTERVIEWCHANGE = 3; + TSC_APPACTIVATE = 4; + TSC_APPDEACTIVATE = 5; + +{ Integer Metric IDs } +const + TMI_SPLITBTN_ARROWWIDTH = 10; + TMI_DROPDOWN_ARROWWIDTH = 20; + TMI_DROPDOWN_ARROWMARGIN = 21; + TMI_MENU_IMGTEXTSPACE = 32; + TMI_MENU_LCAPTIONMARGIN = 33; + TMI_MENU_RCAPTIONMARGIN = 34; + TMI_MENU_SEPARATORSIZE = 35; + TMI_MENU_MDI_DW = 36; + TMI_MENU_MDI_DH = 37; + TMI_TLBR_SEPARATORSIZE = 50; + TMI_EDIT_FRAMEWIDTH = 60; + TMI_EDIT_TEXTMARGINHORZ = 61; + TMI_EDIT_TEXTMARGINVERT = 62; + TMI_EDIT_BTNWIDTH = 65; + TMI_EDIT_MENURIGHTINDENT = 66; + +{ Boolean Metric IDs } +const + TMB_OFFICEXPPOPUPALIGNMENT = 1; + TMB_EDITMENUFULLSELECT = 3; // highlights the full edit item + TMB_EDITHEIGHTEVEN = 4; // forces the height of the edit item to be even number (otherwise it will be odd) + TMB_PAINTDOCKBACKGROUND = 5; // docks are painted by the theme instead of having a uniform color + TMB_SOLIDTOOLBARNCAREA = 6; // no transparency in NC area of toolbars + TMB_SOLIDTOOLBARCLIENTAREA = 7; // no transparency in client area of toolbars + + TMB_SOLIDTOOLBARS = TMB_SOLIDTOOLBARNCAREA; // for compatibility only + +{ Margins Metric IDs} +const + MID_TOOLBARITEM = 1; + MID_MENUITEM = 2; + MID_STATUSPANE = 3; + +{ View types } +const + VT_UNKNOWN = $0; + VT_TOOLBAR = $01000; + VT_POPUP = $02000; + VT_DOCKPANEL = $04000; + VT_DOCKWINDOW = $08000; + VT_STATUSBAR = $10000; // technicaly, this is not a view + + { Toolbar view types } + TVT_FLOATING = $800; + TVT_RESIZABLE = $400; // valid only when floating + TVT_EMBEDDED = $200; // when the toolbar is not floating or docked + TVT_NORMALTOOLBAR = VT_TOOLBAR or $01; + TVT_MENUBAR = VT_TOOLBAR or $02; + TVT_TOOLWINDOW = VT_TOOLBAR or $04; + + { Popup view types } + PVT_POPUPMENU = VT_POPUP or $01; + PVT_LISTBOX = VT_POPUP or $02; + PVT_TOOLBOX = VT_POPUP or $04; + PVT_CHEVRONMENU = VT_POPUP or $08; + + { Dockable panel view types } + DPVT_FLOATING = $800; + DPVT_RESIZABLE = $400; + DPVT_NORMAL = VT_DOCKPANEL or $01; + + { Dockable window view types } + DWVT_FLOATING = $800; + DWVT_RESIZABLE = $400; + DWVT_NORMAL = VT_DOCKWINDOW or $01; + +{ Item types } +const + IT_TOOLBARBUTTON = 1; + IT_MENUITEM = 2; + +{ Item options (bit flags) } +const + IO_TOOLBARSTYLE = $01; + IO_SUBMENUITEM = $04; + IO_COMBO = $08; + IO_DESIGNING = $10; + IO_APPACTIVE = $20; // True when Application.Active = True + IO_RADIO = $40; + +{ Drag handle styles } +const + DHS_DOUBLE = 0; + DHS_NONE = 1; + DHS_SINGLE = 2; + +{ Caption/drag handle button states (bit flags) } +const + CDBS_VISIBLE = $1; + CDBS_HOT = $2; + CDBS_PRESSED = $4; + +{ Window info's RedrawPart (bit flags) } +const + WRP_BORDER = $1; + WRP_CAPTION = $2; + WRP_CLOSEBTN = $4; + +{ Popup shadow types } +const + PST_NONE = 0; // no popup shadows + PST_WINDOWSXP = 1; + PST_OFFICEXP = 2; + PST_WINDOWS2K = 3; + +{ Edit (ComboBox) button types } +const + EBT_DROPDOWN = 1; + EBT_SPIN = 2; + + { Edit (ComboBox) button states for EBT_DROPDOWN type (bit flags) } + EBDS_DISABLED = $1; + EBDS_HOT = $2; + EBDS_PRESSED = $4; + + { Edit (ComboBox) button states for EBT_SPIN type (bit flags) } + EBSS_DISABLED = $1; + EBSS_HOT = $2; + EBSS_UP = $4; + EBSS_DOWN = $8; + +{ Page scroll button types } +const + PSBT_UP = 1; + PSBT_DOWN = 2; + PSBT_LEFT = 3; + PSBT_RIGHT = 4; + +{ PaintFrameControl kinds } +const + PFC_CHECKBOX = 1; + PFC_RADIOBUTTON = 2; + +{ PaintFrameControl states } + PFS_CHECKED = $01; + PFS_MIXED = $02; + PFS_DISABLED = $04; + PFS_HOT = $08; + PFS_PUSHED = $10; + PFS_FOCUSED = $20; + +{ Item state flags } +const + ISF_DISABLED = $001; + ISF_HOT = $002; + ISF_PUSHED = $004; + ISF_SELECTED = $008; + + ISF_LOCATIONMASK = $F00; + ISF_TOOLBARCOLOR = $000; // for text and images painted in toolbars + ISF_MENUCOLOR = $100; // for text and images painted in popups and DkPanels + ISF_STATUSCOLOR = $200; // for text and images painted in status bars + +{ StatusBar parts } +const + SBP_BODY = 0; + SBP_PANE = 1; + SBP_LASTPANE = 2; + SBP_GRIPPER = 3; + +{ Dock positions } +const + DP_TOP = 1; + DP_BOTTOM = 2; + DP_LEFT = 3; + DP_RIGHT = 4; + +type + TTBXItemLayout = (tbxlAuto, tbxlGlyphLeft, tbxlGlyphTop); + TTBXMargins = record + LeftWidth: Integer; + RightWidth: Integer; + TopHeight: Integer; + BottomHeight: Integer; + end; + + TTBXHoverKind = (hkNone, hkKeyboardHover, hkMouseHover); + TTBXComboPart = (cpNone, cpCombo, cpSplitLeft, cpSplitRight); + TTBXItemInfo = record + ViewType: Integer; // VT_*, TVT_*, PVT_*, or DPVT_* constant + ItemOptions: Integer; // IO_* flags + Enabled: Boolean; + Pushed: Boolean; + HoverKind: TTBXHoverKind; + Selected: Boolean; + ImageShown: Boolean; + ImageWidth: Integer; + ImageHeight: Integer; + IsVertical: Boolean; + ComboPart: TTBXComboPart; + IsPopupParent: Boolean; // used in officexp theme + PopupMargin: Integer; + AppFlags: Integer; // reserved for extensions + AppData: Integer; + end; + + TTBXWindowInfo = record + ParentHandle: HWND; // handle of a parent floating window + WindowHandle: HWND; // handle of a toolbar or dockable panel + ViewType: Integer; // TVT_* or DPVT_* view types (loating) + ClientWidth: Integer; + ClientHeight: Integer; + ShowCaption: Boolean; + FloatingBorderSize: TPoint; + CloseButtonState: Integer; // CDBS_* state flags + RedrawPart: Integer; // WRP_ constants + Caption: PChar; + EffectiveColor: TColor; + Active: Boolean; + AppFlags: Integer; // reserved for extensions + AppData: Integer; + end; + + TTBXPopupInfo = record + WindowHandle: HWND; + ViewType: Integer; + ParentRect: TRect; + BorderSize: TPoint; + AppFlags: Integer; // reserved for extensions + AppData: Integer; + end; + + TTBXToolbarInfo = record + WindowHandle: HWND; + ViewType: Integer; // TVT_* view types (docked) + IsVertical: Boolean; + AllowDrag: Boolean; + BorderStyle: TBorderStyle; + BorderSize: TPoint; + ClientWidth: Integer; + ClientHeight: Integer; + DragHandleStyle: Integer; + CloseButtonState: Integer; // CDBS_* state flags + Caption: PChar; + EffectiveColor: TColor; + AppFlags: Integer; // reserved for extensions + AppData: Integer; + end; + + TTBXDockPanelInfo = record + WindowHandle: HWND; + ViewType: Integer; // DPVT_* view types (docked) + IsVertical: Boolean; + AllowDrag: Boolean; + BorderStyle: TBorderStyle; + BorderSize: TPoint; + ClientWidth: Integer; + ClientHeight: Integer; + ShowCaption: Boolean; + CloseButtonState: Integer; + Caption: PChar; + EffectiveColor: TColor; + AppFlags: Integer; // reserved for extensions + AppData: Integer; + end; + + TTBXEditBtnInfo = record + ButtonType: Integer; // EBT_* button type + ButtonState: Integer; + end; + + TTBXEditInfo = record + LeftBtnWidth: Integer; + RightBtnWidth: Integer; + LeftBtnInfo: TTBXEditBtnInfo; // valid only if LeftBtnWidth > 0 + RightBtnInfo: TTBXEditBtnInfo; // valid only if RightBtnWidth > 0 + end; + + TTBXTheme = class + private + FName: string; + FTag: Integer; + public + constructor Create(const AName: string); virtual; + + { Margins, color, etc. } + function GetImageOffset(Canvas: TCanvas; const ItemInfo: TTBXItemInfo; ImageList: TCustomImageList): TPoint; virtual; abstract; + function GetItemColor(const ItemInfo: TTBXItemInfo): TColor; virtual; abstract; + function GetItemTextColor(const ItemInfo: TTBXItemInfo): TColor; virtual; abstract; + function GetItemImageBackground(const ItemInfo: TTBXItemInfo): TColor; virtual; abstract; + procedure GetMargins(MarginID: Integer; out Margins: TTBXMargins); virtual; abstract; + function GetPopupShadowType: Integer; virtual; abstract; // returns one of the PST_ constants + procedure GetViewBorder(ViewType: Integer; out Border: TPoint); virtual; abstract; + function GetViewColor(ViewType: Integer): TColor; virtual; abstract; + procedure GetViewMargins(ViewType: Integer; out Margins: TTBXMargins); virtual; abstract; + + { General painting routines } + procedure PaintBackgnd(Canvas: TCanvas; const ADockRect, ARect, AClipRect: TRect; AColor: TColor; Transparent: Boolean; AViewType: Integer); virtual; abstract; + procedure PaintButton(Canvas: TCanvas; const ARect: TRect; const ItemInfo: TTBXItemInfo); virtual; abstract; + procedure PaintCaption(Canvas: TCanvas; const ARect: TRect; const ItemInfo: TTBXItemInfo; const ACaption: string; AFormat: Cardinal; Rotated: Boolean); virtual; abstract; + procedure PaintCheckMark(Canvas: TCanvas; ARect: TRect; const ItemInfo: TTBXItemInfo); virtual; abstract; + procedure PaintChevron(Canvas: TCanvas; ARect: TRect; const ItemInfo: TTBXItemInfo); virtual; abstract; + procedure PaintEditFrame(Canvas: TCanvas; const ARect: TRect; var ItemInfo: TTBXItemInfo; const EditInfo: TTBXEditInfo); virtual; abstract; + procedure PaintEditButton(Canvas: TCanvas; const ARect: TRect; var ItemInfo: TTBXItemInfo; ButtonInfo: TTBXEditBtnInfo); virtual; abstract; + procedure PaintDock(Canvas: TCanvas; const ClientRect, DockRect: TRect; DockPosition: Integer); virtual; abstract; + procedure PaintDockPanelNCArea(Canvas: TCanvas; R: TRect; const DockPanelInfo: TTBXDockPanelInfo); virtual; abstract; + procedure PaintDropDownArrow(Canvas: TCanvas; const ARect: TRect; const ItemInfo: TTBXItemInfo); virtual; abstract; + procedure PaintFloatingBorder(Canvas: TCanvas; const ARect: TRect; const WindowInfo: TTBXWindowInfo); virtual; abstract; + procedure PaintFrame(Canvas: TCanvas; const ARect: TRect; const ItemInfo: TTBXItemInfo); virtual; abstract; + procedure PaintImage(Canvas: TCanvas; ARect: TRect; const ItemInfo: TTBXItemInfo; ImageList: TCustomImageList; ImageIndex: Integer); virtual; abstract; + procedure PaintMDIButton(Canvas: TCanvas; ARect: TRect; const ItemInfo: TTBXItemInfo; ButtonKind: Cardinal); virtual; abstract; + procedure PaintMenuItem(Canvas: TCanvas; const ARect: TRect; var ItemInfo: TTBXItemInfo); virtual; abstract; + procedure PaintMenuItemFrame(Canvas: TCanvas; const ARect: TRect; const ItemInfo: TTBXItemInfo); virtual; abstract; + procedure PaintPageScrollButton(Canvas: TCanvas; const ARect: TRect; ButtonType: Integer; Hot: Boolean); virtual; abstract; + procedure PaintPopupNCArea(Canvas: TCanvas; R: TRect; const PopupInfo: TTBXPopupInfo); virtual; abstract; + procedure PaintSeparator(Canvas: TCanvas; ARect: TRect; ItemInfo: TTBXItemInfo; Horizontal, LineSeparator: Boolean); virtual; abstract; + procedure PaintToolbarNCArea(Canvas: TCanvas; R: TRect; const WindowInfo: TTBXToolbarInfo); virtual; abstract; + procedure PaintFrameControl(Canvas: TCanvas; R: TRect; Kind, State: Integer; Params: Pointer); virtual; abstract; + procedure PaintStatusBar(Canvas: TCanvas; R: TRect; Part: Integer); virtual; abstract; + + { Integer metrics access } + function GetIntegerMetrics(Index: Integer): Integer; virtual; abstract; + property SplitBtnArrowWidth: Integer index TMI_SPLITBTN_ARROWWIDTH read GetIntegerMetrics; + property DropdownArrowWidth: Integer index TMI_DROPDOWN_ARROWWIDTH read GetIntegerMetrics; + property DropdownArrowMargin: Integer index TMI_DROPDOWN_ARROWMARGIN read GetIntegerMetrics; + property MenuImageTextSpace: Integer index TMI_MENU_IMGTEXTSPACE read GetIntegerMetrics; + property MenuLeftCaptionMargin: Integer index TMI_MENU_LCAPTIONMARGIN read GetIntegerMetrics; + property MenuRightCaptionMargin: Integer index TMI_MENU_RCAPTIONMARGIN read GetIntegerMetrics; + property MenuSeparatorSize: Integer index TMI_MENU_SEPARATORSIZE read GetIntegerMetrics; + property MenuMDIDW: Integer index TMI_MENU_MDI_DW read GetIntegerMetrics; + property MenuMDIDH: Integer index TMI_MENU_MDI_DH read GetIntegerMetrics; + property TlbrSeparatorSize: Integer index TMI_TLBR_SEPARATORSIZE read GetIntegerMetrics; + property EditFrameWidth: Integer index TMI_EDIT_FRAMEWIDTH read GetIntegerMetrics; + property EditTextMarginHorz: Integer index TMI_EDIT_TEXTMARGINHORZ read GetIntegerMetrics; + property EditTextMarginVert: Integer index TMI_EDIT_TEXTMARGINVERT read GetIntegerMetrics; + property EditBtnWidth: Integer index TMI_EDIT_BTNWIDTH read GetIntegerMetrics; + property EditMenuRightIndent: Integer index TMI_EDIT_MENURIGHTINDENT read GetIntegerMetrics; + + { Boolean metrics access } + function GetBooleanMetrics(Index: Integer): Boolean; virtual; abstract; + property OfficeXPPopupAlignment: Boolean index TMB_OFFICEXPPOPUPALIGNMENT read GetBooleanMetrics; + property EditMenuFullSelect: Boolean index TMB_EDITMENUFULLSELECT read GetBooleanMetrics; + property EditHeightEven: Boolean index TMB_EDITHEIGHTEVEN read GetBooleanMetrics; + property PaintDockBackground: Boolean index TMB_PAINTDOCKBACKGROUND read GetBooleanMetrics; + property SolidToolbarNCArea: Boolean index TMB_SOLIDTOOLBARNCAREA read GetBooleanMetrics; + property SolidToolbarClientArea: Boolean index TMB_SOLIDTOOLBARCLIENTAREA read GetBooleanMetrics; + + property Name: string read FName; + property Tag: Integer read FTag write FTag; + end; + + TTBXThemeClass = class of TTBXTheme; + +const +{ TBXSysParam Params } + TSP_FLATMENUSTYLE = 1; + TSP_XPVISUALSTYLE = 2; + +{ Flat menu styles } + FMS_AUTOMATIC = 0; + FMS_DISABLED = 1; + FMS_ENABLED = 2; + +{ XP visual styles} + XPVS_AUTOMATIC = 0; + XPVS_DISABLED = 2; + +procedure SetTBXSysParam(Param: Integer; Value: Integer); +function GetTBXSysParam(Param: Integer): Integer; + +procedure AddTBXSysChangeNotification(AObject: TObject); +procedure RemoveTBXSysChangeNotification(AObject: TObject); + +procedure RegisterTBXTheme(const AName: string; AThemeClass: TTBXThemeClass); +procedure UnregisterTBXTheme(const AName: string); +function IsTBXThemeAvailable(const AName: string): Boolean; +procedure GetAvailableTBXThemes(Strings: TStrings); + +function GetTBXTheme(const AName: string): TTBXTheme; +procedure ReleaseTBXTheme(var ATheme: TTBXTheme); + +{ Additional "system" variables - do not change } + +var + { Additional colors } + clHotLight: TColor; + clPopup: TColor; + clPopupText: TColor; + clToolbar: TColor; + clToolbarText: TColor; + + { Auxiliary flags corresponding to the system color scheme } + TBXLoColor: Boolean; + TBXHiContrast: Boolean; // this can me removed in future + TBXNoBlending: Boolean; // TBXNoColor or TBXHiContrast + + { Handles for Windows XP visual styles } + SCROLLBAR_THEME: THandle; + REBAR_THEME: THandle; + BUTTON_THEME: THandle; + TOOLBAR_THEME: THandle; + WINDOW_THEME: THandle; + COMBO_THEME: THandle; + EXPLORERBAR_THEME: THandle; + STATUSBAR_THEME: THandle; + SPIN_THEME: THandle; + +var + USE_FLATMENUS: Boolean; + USE_THEMES: Boolean; + +{ Misc. Functions } +{ Warning: These functions may be changed or relocated in future versions } + +function GetTBXCaptionRect(const WindowInfo: TTBXWindowInfo; AdjustForBorder, MinusCloseButton: Boolean): TRect; +function GetTBXCloseButtonRect(const WindowInfo: TTBXWindowInfo; AdjustForBorder: Boolean): TRect; +function GetTBXDockedCloseButtonRect(const ToolbarInfo: TTBXToolbarInfo): TRect; +function GetTBXDragHandleSize(const ToolbarInfo: TTBXToolbarInfo): Integer; + +implementation + +uses + SysUtils, TBXUtils, TBXUxThemes; + +const + SPI_GETFLATMENU = $1022; + +type + TThemeInfo = record + Name: ShortString; + ThemeClass: TTBXThemeClass; + ThemeInstance: TTBXTheme; + RefCount: Integer; + end; + +var + Themes: array of TThemeInfo; + +{ TTBXThemeManager } + +type + TTBXThemeManager = class + private + FEnableVisualStyles: Boolean; + FFlatMenuStyle: Integer; + FNotifies: TList; + FWindowHandle: HWND; + procedure SetEnableVisualStyles(Value: Boolean); + procedure SetFlatMenuStyle(Value: Integer); + protected + procedure VisualStylesClose; + procedure VisualStylesOpen; + procedure UpdateVariables; + procedure WndProc(var Message: TMessage); + public + constructor Create; + destructor Destroy; override; + function Broadcast(Msg: Cardinal; Param1, Param2: Integer): Integer; + procedure Notify; + procedure AddNotification(AObject: TObject); + procedure RemoveNotification(AObject: TObject); + property EnableVisualStyles: Boolean read FEnableVisualStyles write SetEnableVisualStyles; + property FlatMenuStyle: Integer read FFlatMenuStyle write SetFlatMenuStyle; + end; + +var + ThemeManager: TTBXThemeManager; + +procedure SetTBXSysParam(Param: Integer; Value: Integer); +begin + case Param of + TSP_FLATMENUSTYLE: ThemeManager.FlatMenuStyle := Value; + TSP_XPVISUALSTYLE: ThemeManager.EnableVisualStyles := (Value = XPVS_AUTOMATIC); + end; +end; + +function GetTBXSysParam(Param: Integer): Integer; +const + CXPVStyles: array [Boolean] of Integer = (XPVS_DISABLED, XPVS_AUTOMATIC); +begin + Assert(ThemeManager <> nil); + case Param of + TSP_FLATMENUSTYLE: Result := ThemeManager.FlatMenuStyle; + TSP_XPVISUALSTYLE: Result := CXPVStyles[ThemeManager.EnableVisualStyles]; + else + Result := -1; + end; +end; + +procedure AddTBXSysChangeNotification(AObject: TObject); +begin + ThemeManager.AddNotification(AObject); +end; + +procedure RemoveTBXSysChangeNotification(AObject: TObject); +begin + ThemeManager.RemoveNotification(AObject); +end; + +function FindTBXTheme(const AName: string): Integer; +begin + for Result := 0 to Length(Themes) - 1 do + if CompareText(Themes[Result].Name, AName) = 0 then Exit; + Result := -1; +end; + +procedure RegisterTBXTheme(const AName: string; AThemeClass: TTBXThemeClass); +var + Index: Integer; +begin + if (Length(AName) = 0) or (AThemeClass = nil) then + raise Exception.Create('Cannot register theme'); + Index := FindTBXTheme(AName); + if Index >= 0 then raise Exception.CreateFmt('Theme %s is already registered', [AName]); + Index := Length(Themes); + SetLength(Themes, Index + 1); + with Themes[Index] do + begin + Name := AName; + ThemeClass := AThemeClass; + ThemeInstance := nil; + RefCount := 0; + end; +end; + +procedure UnregisterTBXTheme(const AName: string); +var + Index, L: Integer; +begin + Index := FindTBXTheme(AName); + if Index < 0 then raise Exception.CreateFmt('Cannot unregister unknown theme %s', [AName]); + L := Length(Themes); + if Index < L - 1 then + Move(Themes[Index + 1], Themes[Index], SizeOf(TThemeInfo) * (L - Index - 1)); + SetLength(Themes, L - 1); +end; + +function IsTBXThemeAvailable(const AName: string): Boolean; +begin + Result := FindTBXTheme(AName) >= 0; +end; + +procedure GetAvailableTBXThemes(Strings: TStrings); +var + I: Integer; +begin + Assert(Strings <> nil); + for I := 0 to Length(Themes) - 1 do + Strings.Add(Themes[I].Name); +end; + +function GetTBXTheme(const AName: string): TTBXTheme; +const + ActiveFlags: array [Boolean] of Integer = (TSC_APPDEACTIVATE, TSC_APPACTIVATE); +var + Index: Integer; + M: TMessage; +begin + Index := FindTBXTheme(AName); + if Index < 0 then raise Exception.Create('Unknown theme ' + AName); + with Themes[Index] do + begin + if RefCount = 0 then + begin + { Create a new instance and increase reference count } + Assert(ThemeInstance = nil); + ThemeInstance := ThemeClass.Create(Name); + M.Msg := TBX_SYSCOMMAND; + M.WParam := Integer(Application.Active); + M.LParam := 0; + M.Result := 0; + ThemeInstance.Dispatch(M); + end; + Inc(RefCount); + Result := ThemeInstance; + end; +end; + +procedure ReleaseTBXTheme(var ATheme: TTBXTheme); +var + Index: Integer; +begin + for Index := 0 to Length(Themes) - 1 do + with Themes[Index] do + if ThemeInstance = ATheme then + begin + if RefCount < 1 then raise Exception.Create('Cannot release theme ' + Themes[Index].Name); + Dec(RefCount); + if RefCount = 0 then + begin + ThemeInstance.Free; + ThemeInstance := nil; + ATheme := nil; + end; + Exit; + end; + raise Exception.Create('Cannot release theme'); +end; + +{ TTBXTheme } + +constructor TTBXTheme.Create(const AName: string); +begin + FName := AName; +end; + +{ Misc. Functions } + +function GetTBXCaptionRect(const WindowInfo: TTBXWindowInfo; + AdjustForBorder, MinusCloseButton: Boolean): TRect; +begin + Result := Rect(0, 0, WindowInfo.ClientWidth, GetSystemMetrics(SM_CYSMCAPTION) - 1); + if MinusCloseButton then Dec(Result.Right, Result.Bottom); + if AdjustForBorder then + with WindowInfo.FloatingBorderSize do OffsetRect(Result, X, Y); +end; + +function GetTBXCloseButtonRect(const WindowInfo: TTBXWindowInfo; + AdjustForBorder: Boolean): TRect; +begin + Result := GetTBXCaptionRect(WindowInfo, AdjustForBorder, False); + Result.Left := Result.Right - Result.Bottom + Result.Top; +end; + +function GetTBXDockedCloseButtonRect(const ToolbarInfo: TTBXToolbarInfo): TRect; +const + DragHandleSizes: array [Boolean, 0..2] of Integer = ((9, 0, 6), (14, 14, 14)); +var + X, Y, Z: Integer; +begin + with ToolbarInfo do + begin + Z := GetTBXDragHandleSize(ToolbarInfo) - 1; + if not IsVertical then + begin + X := BorderSize.X; + Y := BorderSize.Y; + end + else + begin + X := (ClientWidth + BorderSize.X) - Z; + Y := BorderSize.Y; + end; + Result := Bounds(X, Y, Z, Z); + end; +end; + +function GetTBXDragHandleSize(const ToolbarInfo: TTBXToolbarInfo): Integer; +const + DragHandleSizes: array [Boolean, 0..2] of Integer = ((9, 0, 6), (14, 14, 14)); +begin + with ToolbarInfo do + begin + if AllowDrag then + Result := DragHandleSizes[(CloseButtonState and CDBS_VISIBLE) <> 0, DragHandleStyle] + else + Result := 0; + end; +end; + +{ TTBXThemeManager } + +procedure TTBXThemeManager.AddNotification(AObject: TObject); +begin + FNotifies.Add(AObject); +end; + +function TTBXThemeManager.Broadcast(Msg: Cardinal; Param1, Param2: Integer): Integer; +var + I: Integer; + M: TMessage; +begin + if FNotifies.Count > 0 then + begin + M.Msg := Msg; + M.WParam := Param1; + M.LParam := Param2; + M.Result := 0; + for I := 0 to FNotifies.Count - 1 do TObject(FNotifies[I]).Dispatch(M); + Result := M.Result; + end + else Result := 0; +end; + +constructor TTBXThemeManager.Create; +begin + FEnableVisualStyles := True; + FFlatMenuStyle := FMS_AUTOMATIC; + FNotifies := TList.Create; + FWindowHandle := {$IFDEF JR_D6}Classes.{$ENDIF}AllocateHWnd(WndProc); + UpdateVariables; +end; + +destructor TTBXThemeManager.Destroy; +begin + VisualStylesClose; + {$IFDEF JR_D6}Classes.{$ENDIF}DeallocateHWnd(FWindowHandle); + FNotifies.Free; + VisualStylesClose; + inherited; +end; + +procedure TTBXThemeManager.Notify; +begin + if FNotifies.Count > 0 then + begin + Broadcast(TBX_SYSCOMMAND, TSC_BEFOREVIEWCHANGE, 0); + Broadcast(TBX_SYSCOMMAND, TSC_VIEWCHANGE, 0); + Broadcast(TBX_SYSCOMMAND, TSC_AFTERVIEWCHANGE, 0); + end; +end; + +procedure TTBXThemeManager.RemoveNotification(AObject: TObject); +begin + FNotifies.Remove(AObject); +end; + +procedure TTBXThemeManager.SetEnableVisualStyles(Value: Boolean); +begin + if Value <> FEnableVisualStyles then + begin + FEnableVisualStyles := Value; + UpdateVariables; + Notify; + end; +end; + +procedure TTBXThemeManager.SetFlatMenuStyle(Value: Integer); +begin + if Value <> FFlatMenuStyle then + begin + FFlatMenuStyle := Value; + UpdateVariables; + Notify; + end; +end; + +procedure TTBXThemeManager.UpdateVariables; +var + DC: HDC; + SysFlatMenus: Boolean; +begin + TBXUtils.RecreateStock; + + DC := GetDC(0); + try + TBXLoColor := GetDeviceCaps(DC, BITSPIXEL) * GetDeviceCaps(DC, PLANES) < 12; + TBXHiContrast := GetSysColor(COLOR_BTNFACE) = $00FFFFFF; + TBXNoBlending := TBXLoColor or TBXHiContrast; + finally + ReleaseDC(0, DC); + end; + + VisualStylesClose; + VisualStylesOpen; + + clToolbar := clBtnFace; + clToolbarText := clBtnText; + if USE_THEMES then + begin + GetThemeColor(TOOLBAR_THEME, 0, 0, TMT_FILLCOLOR, Cardinal(clToolbar)); + GetThemeColor(TOOLBAR_THEME, 0, 0, TMT_TEXTCOLOR, Cardinal(clToolbarText)); + end; + + SysFlatMenus := False; + if (Win32Platform = VER_PLATFORM_WIN32_NT) and + ((Win32MajorVersion > 5) or + ((Win32MajorVersion = 5) and (Win32MinorVersion >= 1))) then + begin + SystemParametersInfo(SPI_GETFLATMENU, 0, @SysFlatMenus, 0); + end; + + + if SysFlatMenus then // System indicates support for flat menus + begin + if FlatMenuStyle in [FMS_AUTOMATIC, FMS_ENABLED] then + begin + USE_FLATMENUS := True; + clPopup := clMenu; + clPopupText := clMenuText; + end + else + begin + USE_FLATMENUS := False; + clPopup := clToolbar; + clPopupText := clToolbarText; + end; + end + else + begin + if FlatMenuStyle = FMS_ENABLED then + begin + USE_FLATMENUS := True; + clPopup := clWindow; + clPopupText := clWindowText; + end + else + begin + USE_FLATMENUS := False; + clPopup := clMenu; + clPopupText := clMenuText; + end; + end; +end; + +procedure TTBXThemeManager.VisualStylesClose; + + procedure Close(var ATheme: THandle); + begin + if ATheme <> 0 then begin CloseThemeData(ATheme); ATheme := 0; end; + end; + +begin + if USE_THEMES then + begin + Close(BUTTON_THEME); + Close(SCROLLBAR_THEME); + Close(REBAR_THEME); + Close(TOOLBAR_THEME); + Close(WINDOW_THEME); + Close(COMBO_THEME); + Close(EXPLORERBAR_THEME); + Close(STATUSBAR_THEME); + Close(SPIN_THEME); + end; + FreeXPThemes; +end; + +procedure TTBXThemeManager.VisualStylesOpen; +begin + USE_THEMES := False; + if (Win32Platform = VER_PLATFORM_WIN32_NT) and ((Win32MajorVersion > 5) or + ((Win32MajorVersion = 5) and (Win32MinorVersion >= 1))) and EnableVisualStyles then + begin + InitXPThemes; + USE_THEMES := CanUseXPThemes; + try + BUTTON_THEME := OpenThemeData(FWindowHandle, 'BUTTON'); + SCROLLBAR_THEME := OpenThemeData(FWindowHandle, 'SCROLLBAR'); + REBAR_THEME := OpenThemeData(FWindowHandle, 'REBAR'); + TOOLBAR_THEME := OpenThemeData(FWindowHandle, 'TOOLBAR'); + WINDOW_THEME := OpenThemeData(FWindowHandle, 'WINDOW'); + COMBO_THEME := OpenThemeData(FWindowHandle, 'COMBOBOX'); + EXPLORERBAR_THEME := OpenThemeData(FWindowHandle, 'EXPLORERBAR'); + STATUSBAR_THEME := OpenThemeData(FWindowHandle, 'STATUS'); + SPIN_THEME := OpenThemeData(FWindowHandle, 'SPIN'); + except + VisualStylesClose; + end; + end; +end; + +procedure TTBXThemeManager.WndProc(var Message: TMessage); +const + ActiveFlags: array [Boolean] of Integer = (TSC_APPDEACTIVATE, TSC_APPACTIVATE); +begin + case Message.Msg of + WM_DISPLAYCHANGE, WM_SYSCOLORCHANGE, WM_THEMECHANGED: + begin + UpdateVariables; + ResetBrushedFillCache; + Notify; + end; + WM_ACTIVATEAPP: + Broadcast(TBX_SYSCOMMAND, ActiveFlags[Boolean(Message.WParam)], 0); + end; + with Message do Result := DefWindowProc(FWindowHandle, Msg, wParam, lParam); +end; + +initialization +if GetSysColorBrush(COLOR_HOTLIGHT) = 0 then clHotLight := clHighlight +else clHotLight := TColor($80000000 or 26); +Themes := nil; +ThemeManager := TTBXThemeManager.Create; + +finalization +ThemeManager.Free; +SetLength(Themes, 0); + +end. diff --git a/official/2.1.6+2.1.beta1/TBX/TBXThemes.pas.orig b/official/2.1.6+2.1.beta1/TBX/TBXThemes.pas.orig new file mode 100644 index 0000000..616f8dd --- /dev/null +++ b/official/2.1.6+2.1.beta1/TBX/TBXThemes.pas.orig @@ -0,0 +1,896 @@ +unit TBXThemes; + +// TBX Package +// Copyright 2001-2004 Alex A. Denisov. All Rights Reserved +// See TBX.chm for license and installation instructions +// +// $Id: TBXThemes.pas 16 2004-05-26 02:02:55Z Alex@ZEISS $ + +interface + +{$I TB2Ver.inc} +{$I TBX.inc} + +uses + Windows, Messages, Classes, Forms, Graphics, ImgList; + +{ TBX_SYSCOMMAND message } +const + TBX_SYSCOMMAND = WM_USER + 312; + TSC_BEFOREVIEWCHANGE = 1; + TSC_VIEWCHANGE = 2; + TSC_AFTERVIEWCHANGE = 3; + TSC_APPACTIVATE = 4; + TSC_APPDEACTIVATE = 5; + +{ Integer Metric IDs } +const + TMI_SPLITBTN_ARROWWIDTH = 10; + TMI_DROPDOWN_ARROWWIDTH = 20; + TMI_DROPDOWN_ARROWMARGIN = 21; + TMI_MENU_IMGTEXTSPACE = 32; + TMI_MENU_LCAPTIONMARGIN = 33; + TMI_MENU_RCAPTIONMARGIN = 34; + TMI_MENU_SEPARATORSIZE = 35; + TMI_MENU_MDI_DW = 36; + TMI_MENU_MDI_DH = 37; + TMI_TLBR_SEPARATORSIZE = 50; + TMI_EDIT_FRAMEWIDTH = 60; + TMI_EDIT_TEXTMARGINHORZ = 61; + TMI_EDIT_TEXTMARGINVERT = 62; + TMI_EDIT_BTNWIDTH = 65; + TMI_EDIT_MENURIGHTINDENT = 66; + +{ Boolean Metric IDs } +const + TMB_OFFICEXPPOPUPALIGNMENT = 1; + TMB_EDITMENUFULLSELECT = 3; // highlights the full edit item + TMB_EDITHEIGHTEVEN = 4; // forces the height of the edit item to be even number (otherwise it will be odd) + TMB_PAINTDOCKBACKGROUND = 5; // docks are painted by the theme instead of having a uniform color + TMB_SOLIDTOOLBARNCAREA = 6; // no transparency in NC area of toolbars + TMB_SOLIDTOOLBARCLIENTAREA = 7; // no transparency in client area of toolbars + + TMB_SOLIDTOOLBARS = TMB_SOLIDTOOLBARNCAREA; // for compatibility only + +{ Margins Metric IDs} +const + MID_TOOLBARITEM = 1; + MID_MENUITEM = 2; + MID_STATUSPANE = 3; + +{ View types } +const + VT_UNKNOWN = $0; + VT_TOOLBAR = $01000; + VT_POPUP = $02000; + VT_DOCKPANEL = $04000; + VT_DOCKWINDOW = $08000; + VT_STATUSBAR = $10000; // technicaly, this is not a view + + { Toolbar view types } + TVT_FLOATING = $800; + TVT_RESIZABLE = $400; // valid only when floating + TVT_EMBEDDED = $200; // when the toolbar is not floating or docked + TVT_NORMALTOOLBAR = VT_TOOLBAR or $01; + TVT_MENUBAR = VT_TOOLBAR or $02; + TVT_TOOLWINDOW = VT_TOOLBAR or $04; + + { Popup view types } + PVT_POPUPMENU = VT_POPUP or $01; + PVT_LISTBOX = VT_POPUP or $02; + PVT_TOOLBOX = VT_POPUP or $04; + PVT_CHEVRONMENU = VT_POPUP or $08; + + { Dockable panel view types } + DPVT_FLOATING = $800; + DPVT_RESIZABLE = $400; + DPVT_NORMAL = VT_DOCKPANEL or $01; + + { Dockable window view types } + DWVT_FLOATING = $800; + DWVT_RESIZABLE = $400; + DWVT_NORMAL = VT_DOCKWINDOW or $01; + +{ Item types } +const + IT_TOOLBARBUTTON = 1; + IT_MENUITEM = 2; + +{ Item options (bit flags) } +const + IO_TOOLBARSTYLE = $01; + IO_SUBMENUITEM = $04; + IO_COMBO = $08; + IO_DESIGNING = $10; + IO_APPACTIVE = $20; // True when Application.Active = True + +{ Drag handle styles } +const + DHS_DOUBLE = 0; + DHS_NONE = 1; + DHS_SINGLE = 2; + +{ Caption/drag handle button states (bit flags) } +const + CDBS_VISIBLE = $1; + CDBS_HOT = $2; + CDBS_PRESSED = $4; + +{ Window info's RedrawPart (bit flags) } +const + WRP_BORDER = $1; + WRP_CAPTION = $2; + WRP_CLOSEBTN = $4; + +{ Popup shadow types } +const + PST_NONE = 0; // no popup shadows + PST_WINDOWSXP = 1; + PST_OFFICEXP = 2; + PST_WINDOWS2K = 3; + +{ Edit (ComboBox) button types } +const + EBT_DROPDOWN = 1; + EBT_SPIN = 2; + + { Edit (ComboBox) button states for EBT_DROPDOWN type (bit flags) } + EBDS_DISABLED = $1; + EBDS_HOT = $2; + EBDS_PRESSED = $4; + + { Edit (ComboBox) button states for EBT_SPIN type (bit flags) } + EBSS_DISABLED = $1; + EBSS_HOT = $2; + EBSS_UP = $4; + EBSS_DOWN = $8; + +{ Page scroll button types } +const + PSBT_UP = 1; + PSBT_DOWN = 2; + PSBT_LEFT = 3; + PSBT_RIGHT = 4; + +{ PaintFrameControl kinds } +const + PFC_CHECKBOX = 1; + PFC_RADIOBUTTON = 2; + +{ PaintFrameControl states } + PFS_CHECKED = $01; + PFS_MIXED = $02; + PFS_DISABLED = $04; + PFS_HOT = $08; + PFS_PUSHED = $10; + PFS_FOCUSED = $20; + +{ Item state flags } +const + ISF_DISABLED = $001; + ISF_HOT = $002; + ISF_PUSHED = $004; + ISF_SELECTED = $008; + + ISF_LOCATIONMASK = $F00; + ISF_TOOLBARCOLOR = $000; // for text and images painted in toolbars + ISF_MENUCOLOR = $100; // for text and images painted in popups and DkPanels + ISF_STATUSCOLOR = $200; // for text and images painted in status bars + +{ StatusBar parts } +const + SBP_BODY = 0; + SBP_PANE = 1; + SBP_LASTPANE = 2; + SBP_GRIPPER = 3; + +{ Dock positions } +const + DP_TOP = 1; + DP_BOTTOM = 2; + DP_LEFT = 3; + DP_RIGHT = 4; + +type + TTBXItemLayout = (tbxlAuto, tbxlGlyphLeft, tbxlGlyphTop); + TTBXMargins = record + LeftWidth: Integer; + RightWidth: Integer; + TopHeight: Integer; + BottomHeight: Integer; + end; + + TTBXHoverKind = (hkNone, hkKeyboardHover, hkMouseHover); + TTBXComboPart = (cpNone, cpCombo, cpSplitLeft, cpSplitRight); + TTBXItemInfo = record + ViewType: Integer; // VT_*, TVT_*, PVT_*, or DPVT_* constant + ItemOptions: Integer; // IO_* flags + Enabled: Boolean; + Pushed: Boolean; + HoverKind: TTBXHoverKind; + Selected: Boolean; + ImageShown: Boolean; + ImageWidth: Integer; + ImageHeight: Integer; + IsVertical: Boolean; + ComboPart: TTBXComboPart; + IsPopupParent: Boolean; // used in officexp theme + PopupMargin: Integer; + AppFlags: Integer; // reserved for extensions + AppData: Integer; + end; + + TTBXWindowInfo = record + ParentHandle: HWND; // handle of a parent floating window + WindowHandle: HWND; // handle of a toolbar or dockable panel + ViewType: Integer; // TVT_* or DPVT_* view types (loating) + ClientWidth: Integer; + ClientHeight: Integer; + ShowCaption: Boolean; + FloatingBorderSize: TPoint; + CloseButtonState: Integer; // CDBS_* state flags + RedrawPart: Integer; // WRP_ constants + Caption: PChar; + EffectiveColor: TColor; + Active: Boolean; + AppFlags: Integer; // reserved for extensions + AppData: Integer; + end; + + TTBXPopupInfo = record + WindowHandle: HWND; + ViewType: Integer; + ParentRect: TRect; + BorderSize: TPoint; + AppFlags: Integer; // reserved for extensions + AppData: Integer; + end; + + TTBXToolbarInfo = record + WindowHandle: HWND; + ViewType: Integer; // TVT_* view types (docked) + IsVertical: Boolean; + AllowDrag: Boolean; + BorderStyle: TBorderStyle; + BorderSize: TPoint; + ClientWidth: Integer; + ClientHeight: Integer; + DragHandleStyle: Integer; + CloseButtonState: Integer; // CDBS_* state flags + Caption: PChar; + EffectiveColor: TColor; + AppFlags: Integer; // reserved for extensions + AppData: Integer; + end; + + TTBXDockPanelInfo = record + WindowHandle: HWND; + ViewType: Integer; // DPVT_* view types (docked) + IsVertical: Boolean; + AllowDrag: Boolean; + BorderStyle: TBorderStyle; + BorderSize: TPoint; + ClientWidth: Integer; + ClientHeight: Integer; + ShowCaption: Boolean; + CloseButtonState: Integer; + Caption: PChar; + EffectiveColor: TColor; + AppFlags: Integer; // reserved for extensions + AppData: Integer; + end; + + TTBXEditBtnInfo = record + ButtonType: Integer; // EBT_* button type + ButtonState: Integer; + end; + + TTBXEditInfo = record + LeftBtnWidth: Integer; + RightBtnWidth: Integer; + LeftBtnInfo: TTBXEditBtnInfo; // valid only if LeftBtnWidth > 0 + RightBtnInfo: TTBXEditBtnInfo; // valid only if RightBtnWidth > 0 + end; + + TTBXTheme = class + private + FName: string; + FTag: Integer; + public + constructor Create(const AName: string); virtual; + + { Margins, color, etc. } + function GetImageOffset(Canvas: TCanvas; const ItemInfo: TTBXItemInfo; ImageList: TCustomImageList): TPoint; virtual; abstract; + function GetItemColor(const ItemInfo: TTBXItemInfo): TColor; virtual; abstract; + function GetItemTextColor(const ItemInfo: TTBXItemInfo): TColor; virtual; abstract; + function GetItemImageBackground(const ItemInfo: TTBXItemInfo): TColor; virtual; abstract; + procedure GetMargins(MarginID: Integer; out Margins: TTBXMargins); virtual; abstract; + function GetPopupShadowType: Integer; virtual; abstract; // returns one of the PST_ constants + procedure GetViewBorder(ViewType: Integer; out Border: TPoint); virtual; abstract; + function GetViewColor(ViewType: Integer): TColor; virtual; abstract; + procedure GetViewMargins(ViewType: Integer; out Margins: TTBXMargins); virtual; abstract; + + { General painting routines } + procedure PaintBackgnd(Canvas: TCanvas; const ADockRect, ARect, AClipRect: TRect; AColor: TColor; Transparent: Boolean; AViewType: Integer); virtual; abstract; + procedure PaintButton(Canvas: TCanvas; const ARect: TRect; const ItemInfo: TTBXItemInfo); virtual; abstract; + procedure PaintCaption(Canvas: TCanvas; const ARect: TRect; const ItemInfo: TTBXItemInfo; const ACaption: string; AFormat: Cardinal; Rotated: Boolean); virtual; abstract; + procedure PaintCheckMark(Canvas: TCanvas; ARect: TRect; const ItemInfo: TTBXItemInfo); virtual; abstract; + procedure PaintChevron(Canvas: TCanvas; ARect: TRect; const ItemInfo: TTBXItemInfo); virtual; abstract; + procedure PaintEditFrame(Canvas: TCanvas; const ARect: TRect; var ItemInfo: TTBXItemInfo; const EditInfo: TTBXEditInfo); virtual; abstract; + procedure PaintEditButton(Canvas: TCanvas; const ARect: TRect; var ItemInfo: TTBXItemInfo; ButtonInfo: TTBXEditBtnInfo); virtual; abstract; + procedure PaintDock(Canvas: TCanvas; const ClientRect, DockRect: TRect; DockPosition: Integer); virtual; abstract; + procedure PaintDockPanelNCArea(Canvas: TCanvas; R: TRect; const DockPanelInfo: TTBXDockPanelInfo); virtual; abstract; + procedure PaintDropDownArrow(Canvas: TCanvas; const ARect: TRect; const ItemInfo: TTBXItemInfo); virtual; abstract; + procedure PaintFloatingBorder(Canvas: TCanvas; const ARect: TRect; const WindowInfo: TTBXWindowInfo); virtual; abstract; + procedure PaintFrame(Canvas: TCanvas; const ARect: TRect; const ItemInfo: TTBXItemInfo); virtual; abstract; + procedure PaintImage(Canvas: TCanvas; ARect: TRect; const ItemInfo: TTBXItemInfo; ImageList: TCustomImageList; ImageIndex: Integer); virtual; abstract; + procedure PaintMDIButton(Canvas: TCanvas; ARect: TRect; const ItemInfo: TTBXItemInfo; ButtonKind: Cardinal); virtual; abstract; + procedure PaintMenuItem(Canvas: TCanvas; const ARect: TRect; var ItemInfo: TTBXItemInfo); virtual; abstract; + procedure PaintMenuItemFrame(Canvas: TCanvas; const ARect: TRect; const ItemInfo: TTBXItemInfo); virtual; abstract; + procedure PaintPageScrollButton(Canvas: TCanvas; const ARect: TRect; ButtonType: Integer; Hot: Boolean); virtual; abstract; + procedure PaintPopupNCArea(Canvas: TCanvas; R: TRect; const PopupInfo: TTBXPopupInfo); virtual; abstract; + procedure PaintSeparator(Canvas: TCanvas; ARect: TRect; ItemInfo: TTBXItemInfo; Horizontal, LineSeparator: Boolean); virtual; abstract; + procedure PaintToolbarNCArea(Canvas: TCanvas; R: TRect; const WindowInfo: TTBXToolbarInfo); virtual; abstract; + procedure PaintFrameControl(Canvas: TCanvas; R: TRect; Kind, State: Integer; Params: Pointer); virtual; abstract; + procedure PaintStatusBar(Canvas: TCanvas; R: TRect; Part: Integer); virtual; abstract; + + { Integer metrics access } + function GetIntegerMetrics(Index: Integer): Integer; virtual; abstract; + property SplitBtnArrowWidth: Integer index TMI_SPLITBTN_ARROWWIDTH read GetIntegerMetrics; + property DropdownArrowWidth: Integer index TMI_DROPDOWN_ARROWWIDTH read GetIntegerMetrics; + property DropdownArrowMargin: Integer index TMI_DROPDOWN_ARROWMARGIN read GetIntegerMetrics; + property MenuImageTextSpace: Integer index TMI_MENU_IMGTEXTSPACE read GetIntegerMetrics; + property MenuLeftCaptionMargin: Integer index TMI_MENU_LCAPTIONMARGIN read GetIntegerMetrics; + property MenuRightCaptionMargin: Integer index TMI_MENU_RCAPTIONMARGIN read GetIntegerMetrics; + property MenuSeparatorSize: Integer index TMI_MENU_SEPARATORSIZE read GetIntegerMetrics; + property MenuMDIDW: Integer index TMI_MENU_MDI_DW read GetIntegerMetrics; + property MenuMDIDH: Integer index TMI_MENU_MDI_DH read GetIntegerMetrics; + property TlbrSeparatorSize: Integer index TMI_TLBR_SEPARATORSIZE read GetIntegerMetrics; + property EditFrameWidth: Integer index TMI_EDIT_FRAMEWIDTH read GetIntegerMetrics; + property EditTextMarginHorz: Integer index TMI_EDIT_TEXTMARGINHORZ read GetIntegerMetrics; + property EditTextMarginVert: Integer index TMI_EDIT_TEXTMARGINVERT read GetIntegerMetrics; + property EditBtnWidth: Integer index TMI_EDIT_BTNWIDTH read GetIntegerMetrics; + property EditMenuRightIndent: Integer index TMI_EDIT_MENURIGHTINDENT read GetIntegerMetrics; + + { Boolean metrics access } + function GetBooleanMetrics(Index: Integer): Boolean; virtual; abstract; + property OfficeXPPopupAlignment: Boolean index TMB_OFFICEXPPOPUPALIGNMENT read GetBooleanMetrics; + property EditMenuFullSelect: Boolean index TMB_EDITMENUFULLSELECT read GetBooleanMetrics; + property EditHeightEven: Boolean index TMB_EDITHEIGHTEVEN read GetBooleanMetrics; + property PaintDockBackground: Boolean index TMB_PAINTDOCKBACKGROUND read GetBooleanMetrics; + property SolidToolbarNCArea: Boolean index TMB_SOLIDTOOLBARNCAREA read GetBooleanMetrics; + property SolidToolbarClientArea: Boolean index TMB_SOLIDTOOLBARCLIENTAREA read GetBooleanMetrics; + + property Name: string read FName; + property Tag: Integer read FTag write FTag; + end; + + TTBXThemeClass = class of TTBXTheme; + +const +{ TBXSysParam Params } + TSP_FLATMENUSTYLE = 1; + TSP_XPVISUALSTYLE = 2; + +{ Flat menu styles } + FMS_AUTOMATIC = 0; + FMS_DISABLED = 1; + FMS_ENABLED = 2; + +{ XP visual styles} + XPVS_AUTOMATIC = 0; + XPVS_DISABLED = 2; + +procedure SetTBXSysParam(Param: Integer; Value: Integer); +function GetTBXSysParam(Param: Integer): Integer; + +procedure AddTBXSysChangeNotification(AObject: TObject); +procedure RemoveTBXSysChangeNotification(AObject: TObject); + +procedure RegisterTBXTheme(const AName: string; AThemeClass: TTBXThemeClass); +procedure UnregisterTBXTheme(const AName: string); +function IsTBXThemeAvailable(const AName: string): Boolean; +procedure GetAvailableTBXThemes(Strings: TStrings); + +function GetTBXTheme(const AName: string): TTBXTheme; +procedure ReleaseTBXTheme(var ATheme: TTBXTheme); + +{ Additional "system" variables - do not change } + +var + { Additional colors } + clHotLight: TColor; + clPopup: TColor; + clPopupText: TColor; + clToolbar: TColor; + clToolbarText: TColor; + + { Auxiliary flags corresponding to the system color scheme } + TBXLoColor: Boolean; + TBXHiContrast: Boolean; // this can me removed in future + TBXNoBlending: Boolean; // TBXNoColor or TBXHiContrast + + { Handles for Windows XP visual styles } + SCROLLBAR_THEME: THandle; + REBAR_THEME: THandle; + BUTTON_THEME: THandle; + TOOLBAR_THEME: THandle; + WINDOW_THEME: THandle; + COMBO_THEME: THandle; + EXPLORERBAR_THEME: THandle; + STATUSBAR_THEME: THandle; + SPIN_THEME: THandle; + +var + USE_FLATMENUS: Boolean; + USE_THEMES: Boolean; + +{ Misc. Functions } +{ Warning: These functions may be changed or relocated in future versions } + +function GetTBXCaptionRect(const WindowInfo: TTBXWindowInfo; AdjustForBorder, MinusCloseButton: Boolean): TRect; +function GetTBXCloseButtonRect(const WindowInfo: TTBXWindowInfo; AdjustForBorder: Boolean): TRect; +function GetTBXDockedCloseButtonRect(const ToolbarInfo: TTBXToolbarInfo): TRect; +function GetTBXDragHandleSize(const ToolbarInfo: TTBXToolbarInfo): Integer; + +implementation + +uses + SysUtils, TBXUtils, TBXUxThemes; + +const + SPI_GETFLATMENU = $1022; + +type + TThemeInfo = record + Name: ShortString; + ThemeClass: TTBXThemeClass; + ThemeInstance: TTBXTheme; + RefCount: Integer; + end; + +var + Themes: array of TThemeInfo; + +{ TTBXThemeManager } + +type + TTBXThemeManager = class + private + FEnableVisualStyles: Boolean; + FFlatMenuStyle: Integer; + FNotifies: TList; + FWindowHandle: HWND; + procedure SetEnableVisualStyles(Value: Boolean); + procedure SetFlatMenuStyle(Value: Integer); + protected + procedure VisualStylesClose; + procedure VisualStylesOpen; + procedure UpdateVariables; + procedure WndProc(var Message: TMessage); + public + constructor Create; + destructor Destroy; override; + function Broadcast(Msg: Cardinal; Param1, Param2: Integer): Integer; + procedure Notify; + procedure AddNotification(AObject: TObject); + procedure RemoveNotification(AObject: TObject); + property EnableVisualStyles: Boolean read FEnableVisualStyles write SetEnableVisualStyles; + property FlatMenuStyle: Integer read FFlatMenuStyle write SetFlatMenuStyle; + end; + +var + ThemeManager: TTBXThemeManager; + +procedure SetTBXSysParam(Param: Integer; Value: Integer); +begin + case Param of + TSP_FLATMENUSTYLE: ThemeManager.FlatMenuStyle := Value; + TSP_XPVISUALSTYLE: ThemeManager.EnableVisualStyles := (Value = XPVS_AUTOMATIC); + end; +end; + +function GetTBXSysParam(Param: Integer): Integer; +const + CXPVStyles: array [Boolean] of Integer = (XPVS_DISABLED, XPVS_AUTOMATIC); +begin + Assert(ThemeManager <> nil); + case Param of + TSP_FLATMENUSTYLE: Result := ThemeManager.FlatMenuStyle; + TSP_XPVISUALSTYLE: Result := CXPVStyles[ThemeManager.EnableVisualStyles]; + else + Result := -1; + end; +end; + +procedure AddTBXSysChangeNotification(AObject: TObject); +begin + ThemeManager.AddNotification(AObject); +end; + +procedure RemoveTBXSysChangeNotification(AObject: TObject); +begin + ThemeManager.RemoveNotification(AObject); +end; + +function FindTBXTheme(const AName: string): Integer; +begin + for Result := 0 to Length(Themes) - 1 do + if CompareText(Themes[Result].Name, AName) = 0 then Exit; + Result := -1; +end; + +procedure RegisterTBXTheme(const AName: string; AThemeClass: TTBXThemeClass); +var + Index: Integer; +begin + if (Length(AName) = 0) or (AThemeClass = nil) then + raise Exception.Create('Cannot register theme'); + Index := FindTBXTheme(AName); + if Index >= 0 then raise Exception.CreateFmt('Theme %s is already registered', [AName]); + Index := Length(Themes); + SetLength(Themes, Index + 1); + with Themes[Index] do + begin + Name := AName; + ThemeClass := AThemeClass; + ThemeInstance := nil; + RefCount := 0; + end; +end; + +procedure UnregisterTBXTheme(const AName: string); +var + Index, L: Integer; +begin + Index := FindTBXTheme(AName); + if Index < 0 then raise Exception.CreateFmt('Cannot unregister unknown theme %s', [AName]); + L := Length(Themes); + if Index < L - 1 then + Move(Themes[Index + 1], Themes[Index], SizeOf(TThemeInfo) * (L - Index - 1)); + SetLength(Themes, L - 1); +end; + +function IsTBXThemeAvailable(const AName: string): Boolean; +begin + Result := FindTBXTheme(AName) >= 0; +end; + +procedure GetAvailableTBXThemes(Strings: TStrings); +var + I: Integer; +begin + Assert(Strings <> nil); + for I := 0 to Length(Themes) - 1 do + Strings.Add(Themes[I].Name); +end; + +function GetTBXTheme(const AName: string): TTBXTheme; +const + ActiveFlags: array [Boolean] of Integer = (TSC_APPDEACTIVATE, TSC_APPACTIVATE); +var + Index: Integer; + M: TMessage; +begin + Index := FindTBXTheme(AName); + if Index < 0 then raise Exception.Create('Unknown theme ' + AName); + with Themes[Index] do + begin + if RefCount = 0 then + begin + { Create a new instance and increase reference count } + Assert(ThemeInstance = nil); + ThemeInstance := ThemeClass.Create(Name); + M.Msg := TBX_SYSCOMMAND; + M.WParam := Integer(Application.Active); + M.LParam := 0; + M.Result := 0; + ThemeInstance.Dispatch(M); + end; + Inc(RefCount); + Result := ThemeInstance; + end; +end; + +procedure ReleaseTBXTheme(var ATheme: TTBXTheme); +var + Index: Integer; +begin + for Index := 0 to Length(Themes) - 1 do + with Themes[Index] do + if ThemeInstance = ATheme then + begin + if RefCount < 1 then raise Exception.Create('Cannot release theme ' + Themes[Index].Name); + Dec(RefCount); + if RefCount = 0 then + begin + ThemeInstance.Free; + ThemeInstance := nil; + ATheme := nil; + end; + Exit; + end; + raise Exception.Create('Cannot release theme'); +end; + +{ TTBXTheme } + +constructor TTBXTheme.Create(const AName: string); +begin + FName := AName; +end; + +{ Misc. Functions } + +function GetTBXCaptionRect(const WindowInfo: TTBXWindowInfo; + AdjustForBorder, MinusCloseButton: Boolean): TRect; +begin + Result := Rect(0, 0, WindowInfo.ClientWidth, GetSystemMetrics(SM_CYSMCAPTION) - 1); + if MinusCloseButton then Dec(Result.Right, Result.Bottom); + if AdjustForBorder then + with WindowInfo.FloatingBorderSize do OffsetRect(Result, X, Y); +end; + +function GetTBXCloseButtonRect(const WindowInfo: TTBXWindowInfo; + AdjustForBorder: Boolean): TRect; +begin + Result := GetTBXCaptionRect(WindowInfo, AdjustForBorder, False); + Result.Left := Result.Right - Result.Bottom + Result.Top; +end; + +function GetTBXDockedCloseButtonRect(const ToolbarInfo: TTBXToolbarInfo): TRect; +const + DragHandleSizes: array [Boolean, 0..2] of Integer = ((9, 0, 6), (14, 14, 14)); +var + X, Y, Z: Integer; +begin + with ToolbarInfo do + begin + Z := GetTBXDragHandleSize(ToolbarInfo) - 1; + if not IsVertical then + begin + X := BorderSize.X; + Y := BorderSize.Y; + end + else + begin + X := (ClientWidth + BorderSize.X) - Z; + Y := BorderSize.Y; + end; + Result := Bounds(X, Y, Z, Z); + end; +end; + +function GetTBXDragHandleSize(const ToolbarInfo: TTBXToolbarInfo): Integer; +const + DragHandleSizes: array [Boolean, 0..2] of Integer = ((9, 0, 6), (14, 14, 14)); +begin + with ToolbarInfo do + begin + if AllowDrag then + Result := DragHandleSizes[(CloseButtonState and CDBS_VISIBLE) <> 0, DragHandleStyle] + else + Result := 0; + end; +end; + +{ TTBXThemeManager } + +procedure TTBXThemeManager.AddNotification(AObject: TObject); +begin + FNotifies.Add(AObject); +end; + +function TTBXThemeManager.Broadcast(Msg: Cardinal; Param1, Param2: Integer): Integer; +var + I: Integer; + M: TMessage; +begin + if FNotifies.Count > 0 then + begin + M.Msg := Msg; + M.WParam := Param1; + M.LParam := Param2; + M.Result := 0; + for I := 0 to FNotifies.Count - 1 do TObject(FNotifies[I]).Dispatch(M); + Result := M.Result; + end + else Result := 0; +end; + +constructor TTBXThemeManager.Create; +begin + FEnableVisualStyles := True; + FFlatMenuStyle := FMS_AUTOMATIC; + FNotifies := TList.Create; + FWindowHandle := {$IFDEF JR_D6}Classes.{$ENDIF}AllocateHWnd(WndProc); + UpdateVariables; +end; + +destructor TTBXThemeManager.Destroy; +begin + VisualStylesClose; + {$IFDEF JR_D6}Classes.{$ENDIF}DeallocateHWnd(FWindowHandle); + FNotifies.Free; + VisualStylesClose; + inherited; +end; + +procedure TTBXThemeManager.Notify; +begin + if FNotifies.Count > 0 then + begin + Broadcast(TBX_SYSCOMMAND, TSC_BEFOREVIEWCHANGE, 0); + Broadcast(TBX_SYSCOMMAND, TSC_VIEWCHANGE, 0); + Broadcast(TBX_SYSCOMMAND, TSC_AFTERVIEWCHANGE, 0); + end; +end; + +procedure TTBXThemeManager.RemoveNotification(AObject: TObject); +begin + FNotifies.Remove(AObject); +end; + +procedure TTBXThemeManager.SetEnableVisualStyles(Value: Boolean); +begin + if Value <> FEnableVisualStyles then + begin + FEnableVisualStyles := Value; + UpdateVariables; + Notify; + end; +end; + +procedure TTBXThemeManager.SetFlatMenuStyle(Value: Integer); +begin + if Value <> FFlatMenuStyle then + begin + FFlatMenuStyle := Value; + UpdateVariables; + Notify; + end; +end; + +procedure TTBXThemeManager.UpdateVariables; +var + DC: HDC; + SysFlatMenus: Boolean; +begin + TBXUtils.RecreateStock; + + DC := GetDC(0); + try + TBXLoColor := GetDeviceCaps(DC, BITSPIXEL) * GetDeviceCaps(DC, PLANES) < 12; + TBXHiContrast := GetSysColor(COLOR_BTNFACE) = $00FFFFFF; + TBXNoBlending := TBXLoColor or TBXHiContrast; + finally + ReleaseDC(0, DC); + end; + + VisualStylesClose; + VisualStylesOpen; + + clToolbar := clBtnFace; + clToolbarText := clBtnText; + if USE_THEMES then + begin + GetThemeColor(TOOLBAR_THEME, 0, 0, TMT_FILLCOLOR, Cardinal(clToolbar)); + GetThemeColor(TOOLBAR_THEME, 0, 0, TMT_TEXTCOLOR, Cardinal(clToolbarText)); + end; + + SysFlatMenus := False; + if (Win32Platform = VER_PLATFORM_WIN32_NT) and + ((Win32MajorVersion > 5) or + ((Win32MajorVersion = 5) and (Win32MinorVersion >= 1))) then + begin + SystemParametersInfo(SPI_GETFLATMENU, 0, @SysFlatMenus, 0); + end; + + + if SysFlatMenus then // System indicates support for flat menus + begin + if FlatMenuStyle in [FMS_AUTOMATIC, FMS_ENABLED] then + begin + USE_FLATMENUS := True; + clPopup := clMenu; + clPopupText := clMenuText; + end + else + begin + USE_FLATMENUS := False; + clPopup := clToolbar; + clPopupText := clToolbarText; + end; + end + else + begin + if FlatMenuStyle = FMS_ENABLED then + begin + USE_FLATMENUS := True; + clPopup := clWindow; + clPopupText := clWindowText; + end + else + begin + USE_FLATMENUS := False; + clPopup := clMenu; + clPopupText := clMenuText; + end; + end; +end; + +procedure TTBXThemeManager.VisualStylesClose; + + procedure Close(var ATheme: THandle); + begin + if ATheme <> 0 then begin CloseThemeData(ATheme); ATheme := 0; end; + end; + +begin + if USE_THEMES then + begin + Close(BUTTON_THEME); + Close(SCROLLBAR_THEME); + Close(REBAR_THEME); + Close(TOOLBAR_THEME); + Close(WINDOW_THEME); + Close(COMBO_THEME); + Close(EXPLORERBAR_THEME); + Close(STATUSBAR_THEME); + Close(SPIN_THEME); + end; + FreeXPThemes; +end; + +procedure TTBXThemeManager.VisualStylesOpen; +begin + USE_THEMES := False; + if (Win32Platform = VER_PLATFORM_WIN32_NT) and ((Win32MajorVersion > 5) or + ((Win32MajorVersion = 5) and (Win32MinorVersion >= 1))) and EnableVisualStyles then + begin + InitXPThemes; + USE_THEMES := CanUseXPThemes; + try + BUTTON_THEME := OpenThemeData(FWindowHandle, 'BUTTON'); + SCROLLBAR_THEME := OpenThemeData(FWindowHandle, 'SCROLLBAR'); + REBAR_THEME := OpenThemeData(FWindowHandle, 'REBAR'); + TOOLBAR_THEME := OpenThemeData(FWindowHandle, 'TOOLBAR'); + WINDOW_THEME := OpenThemeData(FWindowHandle, 'WINDOW'); + COMBO_THEME := OpenThemeData(FWindowHandle, 'COMBOBOX'); + EXPLORERBAR_THEME := OpenThemeData(FWindowHandle, 'EXPLORERBAR'); + STATUSBAR_THEME := OpenThemeData(FWindowHandle, 'STATUS'); + SPIN_THEME := OpenThemeData(FWindowHandle, 'SPIN'); + except + VisualStylesClose; + end; + end; +end; + +procedure TTBXThemeManager.WndProc(var Message: TMessage); +const + ActiveFlags: array [Boolean] of Integer = (TSC_APPDEACTIVATE, TSC_APPACTIVATE); +begin + case Message.Msg of + WM_DISPLAYCHANGE, WM_SYSCOLORCHANGE, WM_THEMECHANGED: + begin + UpdateVariables; + ResetBrushedFillCache; + Notify; + end; + WM_ACTIVATEAPP: + Broadcast(TBX_SYSCOMMAND, ActiveFlags[Boolean(Message.WParam)], 0); + end; + with Message do Result := DefWindowProc(FWindowHandle, Msg, wParam, lParam); +end; + +initialization +if GetSysColorBrush(COLOR_HOTLIGHT) = 0 then clHotLight := clHighlight +else clHotLight := TColor($80000000 or 26); +Themes := nil; +ThemeManager := TTBXThemeManager.Create; + +finalization +ThemeManager.Free; +SetLength(Themes, 0); + +end. diff --git a/official/2.1.6+2.1.beta1/TBX/TBXToolPals.pas b/official/2.1.6+2.1.beta1/TBX/TBXToolPals.pas new file mode 100644 index 0000000..4dae0fa --- /dev/null +++ b/official/2.1.6+2.1.beta1/TBX/TBXToolPals.pas @@ -0,0 +1,986 @@ +unit TBXToolPals; + +// TBX Package +// Copyright 2001-2004 Alex A. Denisov. All Rights Reserved +// See TBX.chm for license and installation instructions +// +// $Id: TBXToolPals.pas 7 2004-02-21 06:07:53Z $ + +interface + +uses + Windows, Messages, Classes, SysUtils, Controls, Forms, Graphics, TB2Item, TBX, + TBXThemes; + +{$I ..\..\Source\TB2Ver.inc} +{$I TBX.inc} + +type + TRowColCount = 1..100; + TTBXCustomToolPalette = class; + + TTPCalcSize = procedure(Sender: TTBXCustomToolPalette; Canvas: TCanvas; + var AWidth, AHeight: Integer) of object; + TTPGetCellVisible = procedure(Sender: TTBXCustomToolPalette; + ACol, ARow: Integer; var Visible: Boolean) of object; + TTPGetCellHint = procedure(Sender: TTBXCustomToolPalette; + ACol, ARow: Integer; var HintText: string) of object; + TTPDrawCellImage = procedure(Sender: TTBXCustomToolPalette; Canvas: TCanvas; + ARect: TRect; ACol, ARow: Integer; Selected, Hot, Enabled: Boolean) of object; + TTPCellClick = procedure(Sender: TTBXCustomToolPalette; + var ACol, ARow: Integer; var AllowChange: Boolean) of object; + TTBXToolPaletteOptions = set of (tpoCustomImages, tpoNoAutoSelect); + + TTBXCustomToolPalette = class(TTBXCustomItem) + private + FColCount: TRowColCount; + FPaletteOptions: TTBXToolPaletteOptions; + FRowCount: TRowColCount; + FSelectedCell: TPoint; + FOnCalcImageSize: TTPCalcSize; + FOnChange: TNotifyEvent; + FOnCellClick: TTPCellClick; + FOnDrawCellImage: TTPDrawCellImage; + FOnGetCellVisible: TTPGetCellVisible; + FOnGetCellHint: TTPGetCellHint; + procedure SetColCount(Value: TRowColCount); + procedure SetPaletteOptions(Value: TTBXToolPaletteOptions); + procedure SetRowCount(Value: TRowColCount); + procedure SetSelectedCell(Value: TPoint); + protected + procedure DoCalcCellSize(Canvas: TCanvas; var AWidth, AHeight: Integer); virtual; + procedure DoCalcImageSize(Canvas: TCanvas; var AWidth, AHeight: Integer); virtual; + function DoCellClick(var ACol, ARow: Integer): Boolean; virtual; + procedure DoChange; virtual; + procedure DoDrawCellImage(Canvas: TCanvas; const ARect: TRect; ACol, ARow: Integer; ItemInfo: TTBXItemInfo); virtual; + procedure DoGetCellVisible(ACol, ARow: Integer; var Visible: Boolean); virtual; + procedure DoGetHint(ACell: TPoint; var HintText: string); virtual; + function GetItemViewerClass(AView: TTBView): TTBItemViewerClass; override; + procedure HandleClickCell(ACol, ARow: Integer); virtual; + property ColCount: TRowColCount read FColCount write SetColCount default 1; + property PaletteOptions: TTBXToolPaletteOptions read FPaletteOptions write SetPaletteOptions; + property RowCount: TRowColCount read FRowCount write SetRowCount default 1; + property SelectedCell: TPoint read FSelectedCell write SetSelectedCell; + property OnChange: TNotifyEvent read FOnChange write FOnChange; + property OnCalcImageSize: TTPCalcSize read FOnCalcImageSize write FOnCalcImageSize; + property OnCellClick: TTPCellClick read FOnCellClick write FOnCellClick; + property OnDrawCellImage: TTPDrawCellImage read FOnDrawCellImage write FOnDrawCellImage; + property OnGetCellVisible: TTPGetCellVisible read FOnGetCellVisible write FOnGetCellVisible; + property OnGetCellHint: TTPGetCellHint read FOnGetCellHint write FOnGetCellHint; + public + constructor Create(AOwner: TComponent); override; + end; + + TTBXToolPalette = class(TTBXCustomToolPalette) + public + property SelectedCell; + published + property ColCount; + property HelpContext; + property Images; + property Options; + property PaletteOptions; + property RowCount; + property Stretch; + property Visible; + property OnChange; + property OnCalcImageSize; + property OnCellClick; + property OnDrawCellImage; + property OnGetCellHint; + property OnGetCellVisible; + end; + + TTBXToolViewer = class(TTBXItemViewer) + private + FCellHeight: Integer; + FCellWidth: Integer; + FColCount: Integer; + FRowCount: Integer; + FHotCell: TPoint; + protected + Indent: Integer; + MouseIsDown: Boolean; + procedure CalcCellSize(Canvas: TCanvas; var AWidth, AHeight: Integer); virtual; + procedure CalcImageSize(Canvas: TCanvas; var AWidth, AHeight: Integer); virtual; + procedure CalcSize(const Canvas: TCanvas; var AWidth, AHeight: Integer); override; + function GetImageIndex(Col, Row: Integer): Integer; + function GetCellAt(X, Y: Integer; out Col, Row: Integer): Boolean; + function GetCellRect(ClientAreaRect: TRect; Col, Row: Integer): TRect; virtual; + function GetHint(Col, Row: Integer): string; + procedure CMHintShow(var Message: TCMHintShow); message CM_HINTSHOW; + procedure DrawCell(Canvas: TCanvas; const CellRect: TRect; Col, Row: Integer; var ItemInfo: TTBXItemInfo); + procedure DrawCellImage(Canvas: TCanvas; const ARect: TRect; Col, Row: Integer; ItemInfo: TTBXItemInfo); virtual; + procedure Entering(OldSelected: TTBItemViewer); override; + procedure InvalidateCell(ACol, ARow: Integer); + function IsCellVisible(Cell: TPoint): Boolean; virtual; + procedure KeyDown(var Key: Word; Shift: TShiftState); override; + procedure MouseDown(Shift: TShiftState; X, Y: Integer;var MouseDownOnMenu: Boolean); override; + procedure MouseMove(X, Y: Integer); override; + procedure MouseUp(X, Y: Integer; MouseWasDownOnMenu: Boolean); override; + procedure Paint(const Canvas: TCanvas; const ClientAreaRect: TRect; IsHoverItem, IsPushed, UseDisabledShadow: Boolean); override; + property CellHeight: Integer read FCellHeight; + property CellWidth: Integer read FCellWidth; + property ColCount: Integer read FColCount; + property HotCell: TPoint read FHotCell; + property RowCount: Integer read FRowCount; + public + constructor Create(AView: TTBView; AItem: TTBCustomItem; AGroupLevel: Integer); override; + end; + + { TTBXCustomColorSet } + TTBXCustomColorSet = class; + TCSGetColorInfo = procedure(Sender: TTBXCustomColorSet; Col, Row: Integer; + var Color: TColor; var Name: string) of object; + + TTBXCustomColorSet = class(TComponent) + private + FPalettes: TList; + FColCount: Integer; + FRowCount: Integer; + FOnGetColorInfo: TCSGetColorInfo; + procedure SetColCount(Value: Integer); + procedure SetRowCount(Value: Integer); + protected + procedure UpdateSize(NewColCount, NewRowCount: Integer); virtual; + function ColorToString(Color: TColor): string; virtual; + procedure GetColorInfo(Col, Row: Integer; out Color: TColor; out ColorName: string); virtual; + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + function GetColor(Col, Row: Integer): TColor; + function GetName(Col, Row: Integer): string; + property ColCount: Integer read FColCount write SetColCount; + property RowCount: Integer read FRowCount write SetRowCount; + property OnGetColorInfo: TCSGetColorInfo read FOnGetColorInfo write FOnGetColorInfo; + end; + + TTBXColorSet = class(TTBXCustomColorSet) + published + property ColCount; + property RowCount; + property OnGetColorInfo; + end; + + TTBXColorPalette = class(TTBXCustomToolPalette) + private + FColor: TColor; + FColorSet: TTBXCustomColorSet; + procedure SetColorSet(Value: TTBXCustomColorSet); + procedure SetColor(Value: TColor); + protected + procedure DoCalcImageSize(Canvas: TCanvas; var AWidth, AHeight: Integer); override; + procedure DoChange; override; + procedure DoGetCellVisible(ACol, ARow: Integer; var Visible: Boolean); override; + procedure DoGetHint(ACell: TPoint; var HintText: string); override; + procedure DoDrawCellImage(Canvas: TCanvas; const ARect: TRect; ACol, ARow: Integer; ItemInfo: TTBXItemInfo); override; + function GetColorSet: TTBXCustomColorSet; + function GetCellColor(ACol, ARow: Integer): TColor; virtual; + procedure Notification(AComponent: TComponent; Operation: TOperation); override; + public + constructor Create(AOwner: TComponent); override; + function FindCell(AColor: TColor): TPoint; + function ColorToString(AColor: TColor): string; + published + property Color: TColor read FColor write SetColor default clNone; + property ColorSet: TTBXCustomColorSet read FColorSet write SetColorSet; + property HelpContext; + property InheritOptions; + property MaskOptions; + property Options default [tboShowHint]; + property PaletteOptions; + property Stretch; + property Visible; + property OnChange; + property OnCellClick; + property OnGetCellHint; + end; + +implementation + +uses ImgList, TBXUxThemes; + +var + DefaultColorSet: TTBXCustomColorSet; + +type + TTBViewAccess = class(TTBView); + +{ TTBXCustomToolPalette } + +constructor TTBXCustomToolPalette.Create(AOwner: TComponent); +begin + inherited; + FColCount := 1; + FRowCount := 1; + FSelectedCell.X := -1; +// Options := Options + [tboToolbarStyle]; +end; + +procedure TTBXCustomToolPalette.DoCalcCellSize(Canvas: TCanvas; var AWidth, AHeight: Integer); +begin +end; + +procedure TTBXCustomToolPalette.DoCalcImageSize(Canvas: TCanvas; var AWidth, AHeight: Integer); +begin + if Assigned(FOnCalcImageSize) then FOnCalcImageSize(Self, Canvas, AWidth, AHeight); +end; + +function TTBXCustomToolPalette.DoCellClick(var ACol, ARow: Integer): Boolean; +begin + Result := True; + if Assigned(FOnCellClick) then FOnCellClick(Self, ACol, ARow, Result); +end; + +procedure TTBXCustomToolPalette.DoChange; +begin + if Assigned(FOnChange) then FOnChange(Self); +end; + +procedure TTBXCustomToolPalette.DoDrawCellImage(Canvas: TCanvas; + const ARect: TRect; ACol, ARow: Integer; ItemInfo: TTBXItemInfo); +begin + if Assigned(FOnDrawCellImage) then + begin + FOnDrawCellImage(Self, Canvas, ARect, ACol, ARow, ItemInfo.Selected, + ItemInfo.HoverKind <> hkNone, ItemInfo.Enabled); + end; +end; + +procedure TTBXCustomToolPalette.DoGetCellVisible(ACol, ARow: Integer; var Visible: Boolean); +begin + if Assigned(FOnGetCellVisible) then FOnGetCellVisible(Self, ACol, ARow, Visible); +end; + +procedure TTBXCustomToolPalette.DoGetHint(ACell: TPoint; var HintText: string); +begin + if Assigned(FOnGetCellHint) then FOnGetCellHint(Self, ACell.X, ACell.Y, HintText); +end; + +function TTBXCustomToolPalette.GetItemViewerClass(AView: TTBView): TTBItemViewerClass; +begin + Result := TTBXToolViewer; +end; + +procedure TTBXCustomToolPalette.HandleClickCell(ACol, ARow: Integer); +begin + if DoCellClick(ACol, ARow) and not (tpoNoAutoSelect in PaletteOptions) then + SelectedCell := Point(ACol, ARow); +end; + +procedure TTBXCustomToolPalette.SetColCount(Value: TRowColCount); +begin + if FColCount <> Value then + begin + FColCount := Value; + Change(True); + end; +end; + +procedure TTBXCustomToolPalette.SetPaletteOptions(Value: TTBXToolPaletteOptions); +begin + if FPaletteOptions <> Value then + begin + FPaletteOptions := Value; + Change(True); + end; +end; + +procedure TTBXCustomToolPalette.SetRowCount(Value: TRowColCount); +begin + if FRowCount <> Value then + begin + FRowCount := Value; + Change(True); + end; +end; + +procedure TTBXCustomToolPalette.SetSelectedCell(Value: TPoint); +begin + FSelectedCell := Value; + Change(True); + DoChange; +end; + +{ TTBXToolViewer } + +procedure TTBXToolViewer.CalcCellSize(Canvas: TCanvas; var AWidth, AHeight: Integer); +begin + CalcImageSize(Canvas, AWidth, AHeight); + TTBXCustomToolPalette(Item).DoCalcCellSize(Canvas, AWidth, AHeight); + Inc(AWidth, 6); + Inc(AHeight, 6); +end; + +procedure TTBXToolViewer.CalcImageSize(Canvas: TCanvas; var AWidth, AHeight: Integer); +var + ImgList: TCustomImageList; +begin + ImgList := GetImageList; + if ImgList <> nil then + begin + AWidth := ImgList.Width; + AHeight := ImgList.Height; + end + else + begin + AWidth := 16; + AHeight := 16; + end; + TTBXCustomToolPalette(Item).DoCalcImageSize(Canvas, AWidth, AHeight); +end; + +procedure TTBXToolViewer.CalcSize(const Canvas: TCanvas; var AWidth, AHeight: Integer); +var + CellWidth, CellHeight: Integer; +begin + if not IsToolbarStyle then with CurrentTheme do + Indent := GetPopupMargin(Self) + MenuImageTextSpace + MenuLeftCaptionMargin - 3 + else + Indent := 0; + FColCount := TTBXCustomToolPalette(Item).ColCount; + FRowCount := TTBXCustomToolPalette(Item).RowCount; + CalcCellSize(Canvas, CellWidth, CellHeight); + AWidth := Indent + CellWidth * ColCount; + if not IsToolbarStyle then Inc(AWidth, CurrentTheme.MenuRightCaptionMargin); + AHeight := CellHeight * RowCount; + if AWidth < 8 then AWidth := 8; + if AHeight < 8 then AHeight := 8; +end; + +procedure TTBXToolViewer.CMHintShow(var Message: TCMHintShow); +var + Col, Row: Integer; +begin + with Message.HintInfo^ do + begin + if GetCellAt(CursorPos.X - BoundsRect.Left, CursorPos.Y - BoundsRect.Top, Col, Row) then + begin + CursorRect := GetCellRect(CursorRect, Col, Row); + HintStr := GetHint(Col, Row); + end + else HintStr := ''; + end; +end; + +constructor TTBXToolViewer.Create(AView: TTBView; AItem: TTBCustomItem; AGroupLevel: Integer); +begin + inherited; + FColCount := TTBXCustomToolPalette(AItem).ColCount; + FRowCount := TTBXCustomToolPalette(AItem).RowCount; +end; + +procedure TTBXToolViewer.DrawCell(Canvas: TCanvas; const CellRect: TRect; + Col, Row: Integer; var ItemInfo: TTBXItemInfo); +var + ImageWidth, ImageHeight: Integer; + R: TRect; +begin + CurrentTheme.PaintButton(Canvas, CellRect, ItemInfo); + CalcImageSize(Canvas, ImageWidth, ImageHeight); + R := Bounds((CellRect.Right + CellRect.Left - ImageWidth) div 2, + (CellRect.Top + CellRect.Bottom - ImageHeight) div 2, ImageWidth, ImageHeight); + DrawCellImage(Canvas, R, Col, Row, ItemInfo); +end; + +procedure TTBXToolViewer.DrawCellImage(Canvas: TCanvas; const ARect: TRect; + Col, Row: Integer; ItemInfo: TTBXItemInfo); +var + ImgIndex: Integer; + ImgList: TCustomImageList; +begin + if not (tpoCustomImages in TTBXCustomToolPalette(Item).PaletteOptions) then + begin + ImgIndex := GetImageIndex(Col, Row); + ImgList := GetImageList; + if (ImgList <> nil) and (ImgIndex >= 0) and (ImgIndex < ImgList.Count) then + CurrentTheme.PaintImage(Canvas, ARect, ItemInfo, ImgList, ImgIndex); + end; + TTBXCustomToolPalette(Item).DoDrawCellImage(Canvas, ARect, Col, Row, ItemInfo); +end; + +procedure TTBXToolViewer.Entering(OldSelected: TTBItemViewer); +begin + FHotCell := Point(-1, 0); + if (View is TTBXPopupView) and (OldSelected <> nil) then + begin + if OldSelected.Index > Index then + begin + FHotCell := Point(ColCount - 1, RowCount - 1); + while (FHotCell.X > 0) and not IsCellVisible(FHotCell) do Dec(FHotCell.X); + end + else if OldSelected.Index < Index then + FHotCell := Point(0, 0); + end; + inherited Entering(OldSelected); +end; + +function TTBXToolViewer.GetCellAt(X, Y: Integer; out Col, Row: Integer): Boolean; +begin + { Returns true if there is a cell at (X,Y) point } + if (CellWidth = 0) or (CellHeight = 0) then + begin + Col := 0; + Row := 0; + end + else if not TTBXCustomToolPalette(Item).Stretch then + begin + Col := (X - Indent) div CellWidth; + Row := Y div CellHeight; + end + else + begin + Col := (X - Indent) * ColCount div (BoundsRect.Right - BoundsRect.Left); + Row := Y * RowCount div (BoundsRect.Bottom - BoundsRect.Top); + end; + Result := IsCellVisible(Point(Col, Row)); +end; + +function TTBXToolViewer.GetCellRect(ClientAreaRect: TRect; Col, Row: Integer): TRect; +var + W, H: Integer; +begin + with ClientAreaRect do + if not TTBXCustomToolPalette(Item).Stretch then + begin + Result := Bounds(Left + Indent + Col * CellWidth, Top + Row * CellHeight, CellWidth, CellHeight) + end + else + begin + W := Right - Left; + H := Bottom - Top; + Result.Left := Left + Indent + W * Col div ColCount; + Result.Top := Top + H * Row div RowCount; + Result.Right := Left + W * (Col + 1) div ColCount; + Result.Bottom := Top + H * (Row + 1) div RowCount; + end; +end; + +function TTBXToolViewer.GetHint(Col, Row: Integer): string; +begin + Result := ''; + TTBXCustomToolPalette(Item).DoGetHint(Point(Col, Row), Result); +end; + +function TTBXToolViewer.GetImageIndex(Col, Row: Integer): Integer; +begin + Result := Col + Row * ColCount; +end; + +procedure TTBXToolViewer.InvalidateCell(ACol, ARow: Integer); +var + R: TRect; +begin + R := GetCellRect(BoundsRect, ACol, ARow); + InvalidateRect(View.Window.Handle, @R, False); +end; + +function TTBXToolViewer.IsCellVisible(Cell: TPoint): Boolean; +var + ImgList: TCustomImageList; +begin + Result := (Cell.X >= 0) and (Cell.Y >= 0) and (Cell.X < ColCount) and (Cell.Y < RowCount); + if Result then + begin + if not (tpoCustomImages in TTBXCustomToolPalette(Item).PaletteOptions) then + begin + ImgList := GetImageList; + if ImgList <> nil then Result := (Cell.X + Cell.Y * ColCount) < ImgList.Count; + end; + TTBXCustomToolPalette(Item).DoGetCellVisible(Cell.X, Cell.Y, Result); + end; +end; + +procedure TTBXToolViewer.KeyDown(var Key: Word; Shift: TShiftState); +var + OldPos, Pos: TPoint; +begin + if IsCellVisible(HotCell) then OldPos := HotCell + else if IsCellVisible(TTBXCustomToolPalette(Item).SelectedCell) then + OldPos := TTBXCustomToolPalette(Item).SelectedCell + else OldPos.X := -1; + + if OldPos.X >= 0 then + begin + Pos := OldPos; + case Key of + VK_LEFT: + begin + Dec(Pos.X); + if Pos.X < 0 then + begin + Pos.X := ColCount - 1; + Dec(Pos.Y); + end; + end; + VK_UP: Dec(Pos.Y); + VK_RIGHT: + begin + Inc(Pos.X); + if Pos.X >= ColCount then + begin + Pos.X := 0; + Inc(Pos.Y); + end; + end; + VK_DOWN: Inc(Pos.Y); + VK_PRIOR: Pos.Y := 0; + VK_NEXT: Pos.Y := RowCount - 1; + VK_HOME: Pos.X := 0; + VK_END: Pos.Y := ColCount - 1; + VK_RETURN: + if IsCellVisible(HotCell) then + begin + TTBXCustomToolPalette(Item).HandleClickCell(HotCell.X, HotCell.Y); + Exit; + end; + else + inherited; + Exit; + end; + end + else + begin + OldPos := Point(-1, 0); + Pos := Point(0, 0); + end; + + if ((OldPos.X <> Pos.X) or (OldPos.Y <> Pos.Y)) and IsCellVisible(Pos) then + begin + Key := 0; + FHotCell := Pos; + TTBXCustomToolPalette(Item).Change(False); + end; +end; + +procedure TTBXToolViewer.MouseDown(Shift: TShiftState; X, Y: Integer; var MouseDownOnMenu: Boolean); +begin + MouseIsDown := True; + MouseMove(X, Y); + inherited; + View.SetCapture; +end; + +procedure TTBXToolViewer.MouseMove(X, Y: Integer); +var + OldHotCell: TPoint; +begin + OldHotCell := HotCell; + if not GetCellAt(X, Y, FHotCell.X, FHotCell.Y) then FHotCell := Point(-1, 0); + if (HotCell.X <> OldHotCell.X) or (HotCell.Y <> OldHotCell.Y) then + begin + with TTBXCustomToolPalette(Item) do + begin + if Show and not IsRectEmpty(BoundsRect) and + not (Item is TTBControlItem) then + begin + Include(State, tbisInvalidated); + InvalidateCell(OldHotCell.X, OldHotCell.Y); + InvalidateCell(HotCell.X, HotCell.Y); + end; + end; + end; +end; + +procedure TTBXToolViewer.MouseUp(X, Y: Integer; MouseWasDownOnMenu: Boolean); +var + Col, Row: Integer; + DAD: TTBDoneActionData; +begin + MouseIsDown := False; + if GetCellAt(X, Y, Col, Row) then + TTBXCustomToolPalette(Item).HandleClickCell(Col, Row); + DAD := TTBViewAccess(TTBViewAccess(View).GetRootView).DoneActionData; + DAD.ClickItem := Item; + DAD.DoneAction := tbdaClickItem; + DAD.Sound := True; + TTBViewAccess(TTBViewAccess(View).GetRootView).DoneActionData := DAD; + inherited; +end; + +procedure TTBXToolViewer.Paint(const Canvas: TCanvas; const ClientAreaRect: TRect; + IsHoverItem, IsPushed, UseDisabledShadow: Boolean); +const + CDesigning: array [Boolean] of Integer = (0, IO_DESIGNING); +var + I, J: Integer; + ItemInfo: TTBXItemInfo; + Hover: TTBXHoverKind; + R, CellRect: TRect; +begin + FillChar(ItemInfo, SizeOf(TTBXItemInfo), 0); + ItemInfo.ViewType := GetViewType(View); + ItemInfo.ItemOptions := CDesigning[csDesigning in Item.ComponentState]; + ItemInfo.Enabled := Item.Enabled or View.Customizing; + ItemInfo.Pushed := False; + ItemInfo.Selected := False; + ItemInfo.ImageShown := True; + with ItemInfo do CalcImageSize(Canvas, ImageWidth, ImageHeight); + ItemInfo.HoverKind := hkNone; + if not IsToolbarStyle then ItemInfo.PopupMargin := GetPopupMargin(Self); + + if not IsToolbarStyle then with CurrentTheme do + begin + R := ClientAreaRect; + CurrentTheme.PaintMenuItemFrame(Canvas, R, ItemInfo); + end; + + CalcCellSize(Canvas, FCellWidth, FCellHeight); + if IsHoverItem then + begin + if not ItemInfo.Enabled and not View.MouseOverSelected then Hover := hkKeyboardHover + else if ItemInfo.Enabled then Hover := hkMouseHover + else Hover := hkNone; + end + else + Hover := hkNone; + + for J := 0 to RowCount - 1 do + for I := 0 to ColCount - 1 do + begin + if IsCellVisible(Point(I, J)) then + begin + if (Hover <> hkNone) and (HotCell.X = I) and (HotCell.Y = J) then + begin + ItemInfo.HoverKind := Hover; + if IsPushed then ItemInfo.Pushed := True + end + else + begin + ItemInfo.HoverKind := hkNone; + ItemInfo.Pushed := False; + end; + with TTBXCustomToolPalette(Item) do + if (SelectedCell.X = I) and (SelectedCell.Y = J) then + ItemInfo.Selected := True + else + ItemInfo.Selected := False; + CellRect := GetCellRect(ClientAreaRect, I, J); + DrawCell(Canvas, CellRect, I, J, ItemInfo); + end; + end; +end; + +//----------------------------------------------------------------------------// + +{ TTBXCustomColorSet } + +constructor TTBXCustomColorSet.Create(AOwner: TComponent); +begin + inherited; + FPalettes := TList.Create; +end; + +destructor TTBXCustomColorSet.Destroy; +begin + FPalettes.Free; + inherited; +end; + +function TTBXCustomColorSet.GetColor(Col, Row: Integer): TColor; +var + Dummy: string; +begin + GetColorInfo(Col, Row, Result, Dummy); +end; + +procedure TTBXCustomColorSet.GetColorInfo(Col, Row: Integer; out Color: TColor; out ColorName: string); +begin + Color := clNone; + SetLength(ColorName, 0); + if Assigned(FOnGetColorInfo) then FOnGetColorInfo(Self, Col, Row, Color, ColorName); +end; + +function TTBXCustomColorSet.ColorToString(Color: TColor): string; +var + I, J: Integer; + C: TColor; + N: string; + + function GetRGB(C: TColor): TColor; + begin + Result := (C and $FF00) + C shr 16 + (C and $FF shl 16); + end; + +begin + if Color = clNone then Result := 'None' + else + begin + if Color < 0 then Color := GetSysColor(Color and $000000FF); + Color := Color and $00FFFFFF; + + for J := 0 to RowCount - 1 do + for I := 0 to ColCount - 1 do + begin + GetColorInfo(I, J, C, N); + if C <> clNone then + begin + if C < 0 then C := GetSysColor(C and $000000FF); + C := C and $00FFFFFF; + if C = Color then + begin + Result := N; + if Length(N) = 0 then Result := '#' + IntToHex(GetRGB(Color), 6); + Exit; + end + end; + end; + + Result := '#' + IntToHex(GetRGB(Color), 6); + end; +end; + +function TTBXCustomColorSet.GetName(Col, Row: Integer): string; +var + Dummy: TColor; +begin + GetColorInfo(Col, Row, Dummy, Result); +end; + +procedure TTBXCustomColorSet.SetColCount(Value: Integer); +begin + UpdateSize(Value, RowCount); +end; + +procedure TTBXCustomColorSet.SetRowCount(Value: Integer); +begin + UpdateSize(ColCount, Value); +end; + +procedure TTBXCustomColorSet.UpdateSize(NewColCount, NewRowCount: Integer); +var + I: Integer; +begin + FColCount := NewColCount; + FRowCount := NewRowCount; + for I := 0 to FPalettes.Count - 1 do + with TTBXColorPalette(FPalettes[I]) do + begin + ColCount := Self.ColCount; + RowCount := Self.RowCount; + end; +end; + +//----------------------------------------------------------------------------// + +{ TTBXColorPalette } + +function TTBXColorPalette.ColorToString(AColor: TColor): string; +begin + Result := GetColorSet.ColorToString(AColor); +end; + +constructor TTBXColorPalette.Create(AOwner: TComponent); +begin + inherited; + ColCount := DefaultColorSet.ColCount; + RowCount := DefaultColorSet.RowCount; + Options := Options + [tboShowHint]; + FColor := clNone; + PaletteOptions := PaletteOptions + [tpoCustomImages]; +end; + +procedure TTBXColorPalette.DoCalcImageSize(Canvas: TCanvas; var AWidth, AHeight: Integer); +begin + AWidth := 12; + AHeight := 12; +end; + +procedure TTBXColorPalette.DoChange; +begin + if SelectedCell.X >= 0 then + FColor := GetCellColor(SelectedCell.X, SelectedCell.Y); + inherited; +end; + +procedure TTBXColorPalette.DoDrawCellImage(Canvas: TCanvas; + const ARect: TRect; ACol, ARow: Integer; ItemInfo: TTBXItemInfo); +var + R: TRect; +begin + R := ARect; + Canvas.Brush.Color := clBtnShadow; + Canvas.FrameRect(R); + InflateRect(R, -1, -1); + if ItemInfo.Enabled then + begin + Canvas.Brush.Color := GetCellColor(ACol, ARow); + Canvas.FillRect(R); + end; +end; + +procedure TTBXColorPalette.DoGetCellVisible(ACol, ARow: Integer; var Visible: Boolean); +begin + Visible := GetCellColor(ACol, ARow) <> clNone; +end; + +procedure TTBXColorPalette.DoGetHint(ACell: TPoint; var HintText: string); +begin + HintText := GetColorSet.GetName(ACell.X, ACell.Y); +end; + +function TTBXColorPalette.FindCell(AColor: TColor): TPoint; +var + I, J: Integer; + C: TColor; +begin + if AColor <> clNone then AColor := ColorToRGB(AColor); + for J := 0 to RowCount - 1 do + for I := 0 to ColCount - 1 do + begin + C := GetCellColor(I, J); + if C <> clNone then C := ColorToRGB(C); + if C = AColor then + begin + Result.X := I; + Result.Y := J; + Exit; + end; + end; + Result.X := -1; + Result.Y := 0; +end; + +function TTBXColorPalette.GetCellColor(ACol, ARow: Integer): TColor; +begin + Result := GetColorSet.GetColor(ACol, ARow); +end; + +function TTBXColorPalette.GetColorSet: TTBXCustomColorSet; +begin + if FColorSet = nil then Result := DefaultColorSet + else Result := FColorSet; +end; + +procedure TTBXColorPalette.Notification(AComponent: TComponent; Operation: TOperation); +begin + inherited; + if (AComponent = FColorSet) and (Operation = opRemove) then ColorSet := nil; +end; + +procedure TTBXColorPalette.SetColor(Value: TColor); +begin + FColor := Value; + SelectedCell := FindCell(Value); +end; + +procedure TTBXColorPalette.SetColorSet(Value: TTBXCustomColorSet); +begin + if FColorSet <> Value then + begin + if Assigned(FColorSet) then FColorSet.FPalettes.Remove(Self); + FColorSet := Value; + if Assigned(Value) then + begin + Value.FreeNotification(Self); + Value.FPalettes.Add(Self); + ColCount := Value.ColCount; + RowCount := Value.RowCount; + end + else + begin + ColCount := DefaultColorSet.ColCount; + RowCount := DefaultColorSet.RowCount; + end; + Change(True); + end; +end; + +{ TTBXDefaultColorSet } + +type + TTBXDefaultColorSet = class (TTBXCustomColorSet) + protected + procedure GetColorInfo(Col, Row: Integer; out Color: TColor; out ColorName: string); override; + public + constructor Create(AOwner: TComponent); override; + end; + +procedure TTBXDefaultColorSet.GetColorInfo(Col, Row: Integer; out Color: TColor; out ColorName: string); + + procedure Clr(const AName: string; AColor: TColor); + begin + Color := AColor; + ColorName := AName; + end; + +begin + Color := clNone; + Name := ''; + case Row of + 0: + case Col of + 0: Clr('Black', $000000); + 1: Clr('Brown', $003399); + 2: Clr('Olive Green', $003333); + 3: Clr('Dark Green', $003300); + 4: Clr('Dark Teal', $663300); + 5: Clr('Dark blue', $800000); + 6: Clr('Indigo', $993333); + 7: Clr('Gray-80%', $333333); + end; + + 1: + case Col of + 0: Clr('Dark Red', $000080); + 1: Clr('Orange', $0066FF); + 2: Clr('Dark Yellow', $008080); + 3: Clr('Green', $008000); + 4: Clr('Teal', $808000); + 5: Clr('Blue', $FF0000); + 6: Clr('Blue-Gray', $996666); + 7: Clr('Gray-50%', $808080); + end; + + 2: + case Col of + 0: Clr('Red', $0000FF); + 1: Clr('Light Orange', $0099FF); + 2: Clr('Lime', $00CC99); + 3: Clr('Sea Green', $669933); + 4: Clr('Aqua', $CCCC33); + 5: Clr('Light Blue', $FF6633); + 6: Clr('Violet', $800080); + 7: Clr('Gray-40%', $969696); + end; + + 3: + case Col of + 0: Clr('Pink', $FF00FF); + 1: Clr('Gold', $00CCFF); + 2: Clr('Yellow', $00FFFF); + 3: Clr('Bright Green', $00FF00); + 4: Clr('Turquoise', $FFFF00); + 5: Clr('Sky Blue', $FFCC00); + 6: Clr('Plum', $663399); + 7: Clr('Gray-25%', $C0C0C0); + end; + + 4: + case Col of + 0: Clr('Rose', $CC99FF); + 1: Clr('Tan', $99CCFF); + 2: Clr('Light Yellow', $99FFFF); + 3: Clr('Light Green', $CCFFCC); + 4: Clr('Light Turquoise', $FFFFCC); + 5: Clr('Pale Blue', $FFCC99); + 6: Clr('Lavender', $FF99CC); + 7: Clr('White', $FFFFFF); + end; + end; +end; + +constructor TTBXDefaultColorSet.Create(AOwner: TComponent); +begin + inherited; + FColCount := 8; + FRowCount := 5; +end; + +initialization + DefaultColorSet := TTBXDefaultColorSet.Create(nil); + +finalization + DefaultColorSet.Free; + +end. diff --git a/official/2.1.6+2.1.beta1/TBX/TBXUtils.pas b/official/2.1.6+2.1.beta1/TBX/TBXUtils.pas new file mode 100644 index 0000000..01f0601 --- /dev/null +++ b/official/2.1.6+2.1.beta1/TBX/TBXUtils.pas @@ -0,0 +1,2329 @@ +unit TBXUtils; + +// TBX Package +// Copyright 2001-2004 Alex A. Denisov. All Rights Reserved +// See TBX.chm for license and installation instructions +// +// $Id: TBXUtils.pas 11 2004-04-01 07:22:56Z Alex@ZEISS $ + +interface + +{$I ..\..\Source\TB2Ver.inc} +{$I TBX.inc} + +uses + Windows, Messages, Classes, SysUtils, Graphics, Controls, Forms, ImgList; + +{$IFDEF TBX_UNICODE} +function GetTextHeightW(DC: HDC): Integer; +function GetTextWidthW(DC: HDC; const S: WideString; StripAccelChar: Boolean): Integer; +procedure DrawRotatedTextW(DC: HDC; AText: WideString; const ARect: TRect; const AFormat: Cardinal); +function EscapeAmpersandsW(const S: WideString): WideString; +function FindAccelCharW(const S: WideString): WideChar; +function StripAccelCharsW(const S: WideString): WideString; +function StripTrailingPunctuationW(const S: WideString): WideString; +{$ENDIF} + +{$IFNDEF JR_D6} +function CheckWin32Version(AMajor, AMinor: Integer = 0): Boolean; {vb+} +{$ENDIF} +procedure GetRGB(C: TColor; out R, G, B: Integer); +function MixColors(C1, C2: TColor; W1: Integer): TColor; +function SameColors(C1, C2: TColor): Boolean; +function Lighten(C: TColor; Amount: Integer): TColor; +function NearestLighten(C: TColor; Amount: Integer): TColor; +function NearestMixedColor(C1, C2: TColor; W1: Integer): TColor; +function ColorIntensity(C: TColor): Integer; +function IsDarkColor(C: TColor; Threshold: Integer = 100): Boolean; +function Blend(C1, C2: TColor; W1: Integer): TColor; +procedure SetContrast(var Color: TColor; BkgndColor: TColor; Threshold: Integer); +procedure RGBtoHSL(RGB: TColor; out H, S, L : Single); +function HSLtoRGB(H, S, L: Single): TColor; +function GetBGR(C: TColorRef): Cardinal; + +{ A few drawing functions } +{ these functions recognize clNone value of TColor } + +procedure SetPixelEx(DC: HDC; X, Y: Integer; C: TColorRef; Alpha: Longword = $FF); +function CreatePenEx(Color: TColor): HPen; +function CreateBrushEx(Color: TColor): HBrush; +function CreateDitheredBrush(C1, C2: TColor): HBrush; +function FillRectEx(DC: HDC; const Rect: TRect; Color: TColor): Boolean; {$IFDEF COMPATIBLE_GFX}overload;{$ENDIF} +function FrameRectEx(DC: HDC; var Rect: TRect; Color: TColor; Adjust: Boolean): Boolean; {$IFDEF COMPATIBLE_GFX}overload;{$ENDIF} +procedure DrawLineEx(DC: HDC; X1, Y1, X2, Y2: Integer; Color: TColor); {$IFDEF COMPATIBLE_GFX}overload;{$ENDIF} +function PolyLineEx(DC: HDC; const Points: array of TPoint; Color: TColor): Boolean; +procedure PolygonEx(DC: HDC; const Points: array of TPoint; OutlineColor, FillColor: TColor); +procedure RoundRectEx(DC: HDC; Left, Top, Right, Bottom: Integer; EllipseWidth, EllipseHeight, OutlineColor, FillColor: TColor); overload; {vb+} +procedure RoundRectEx(DC: HDC; const R: TRect; EllipseWidth, EllipseHeight, OutlineColor, FillColor: TColor); overload; {vb+} +procedure DitherRect(DC: HDC; const R: TRect; C1, C2: TColor); {$IFDEF COMPATIBLE_GFX}overload;{$ENDIF} +procedure Frame3D(DC: HDC; var Rect: TRect; TopColor, BottomColor: TColor; Adjust: Boolean); {$IFDEF COMPATIBLE_GFX}overload;{$ENDIF} +procedure DrawDraggingOutline(DC: HDC; const NewRect, OldRect: TRect); + +{ Gradients } +type + TGradientKind = (gkHorz, gkVert); + +procedure GradFill(DC: HDC; ARect: TRect; ClrTopLeft, ClrBottomRight: TColor; Kind: TGradientKind); +procedure BrushedFill(DC: HDC; Origin: PPoint; ARect: TRect; Color: TColor; Roughness: Integer); +procedure ResetBrushedFillCache; + +{ drawing functions for compatibility with previous versions } +{$IFDEF COMPATIBLE_GFX} +function FillRectEx(Canvas: TCanvas; const Rect: TRect; Color: TColor): Boolean; overload; +function FrameRectEx(Canvas: TCanvas; var Rect: TRect; Color: TColor; Adjust: Boolean = False): Boolean; overload; +procedure DrawLineEx(Canvas: TCanvas; X1, Y1, X2, Y2: Integer; Color: TColor); overload; +procedure DitherRect(Canvas: TCanvas; const R: TRect; C1, C2: TColor); overload; +procedure Frame3D(Canvas: TCanvas; var Rect: TRect; TopColor, BottomColor: TColor); overload; +function FillRectEx2(DC: HDC; const Rect: TRect; Color: TColor): Boolean; deprecated; +function FrameRectEx2(DC: HDC; var Rect: TRect; Color: TColor; Adjust: Boolean = False): Boolean; deprecated; +{$ENDIF} + +{ alternatives to fillchar and move routines what work with 32-bit aligned memory blocks } +procedure FillLongword(var X; Count: Integer; Value: Longword); +procedure MoveLongword(const Source; var Dest; Count: Integer); + +{ extended icon painting routines } +procedure DrawTBXIcon(Canvas: TCanvas; const R: TRect; + ImageList: TCustomImageList; ImageIndex: Integer; HiContrast: Boolean); +procedure BlendTBXIcon(Canvas: TCanvas; const R: TRect; + ImageList: TCustomImageList; ImageIndex: Integer; Opacity: Byte); +procedure HighlightTBXIcon(Canvas: TCanvas; const R: TRect; + ImageList: TCustomImageList; ImageIndex: Integer; HighlightColor: TColor; Amount: Byte); +procedure DrawTBXIconShadow(Canvas: TCanvas; const R: TRect; + ImageList: TCustomImageList; ImageIndex: Integer; Density: Integer); +procedure DrawTBXIconFlatShadow(Canvas: TCanvas; const R: TRect; + ImageList: TCustomImageList; ImageIndex: Integer; ShadowColor: TColor); +procedure DrawTBXIconFullShadow(Canvas: TCanvas; const R: TRect; + ImageList: TCustomImageList; ImageIndex: Integer; ShadowColor: TColor); + +procedure DrawGlyph(DC: HDC; X, Y: Integer; ImageList: TCustomImageList; ImageIndex: Integer; Color: TColor); overload; +procedure DrawGlyph(DC: HDC; const R: TRect; ImageList: TCustomImageList; ImageIndex: Integer; Color: TColor); overload; +procedure DrawGlyph(DC: HDC; X, Y: Integer; const Bits; Color: TColor); overload; +procedure DrawGlyph(DC: HDC; const R: TRect; Width, Height: Integer; const Bits; Color: TColor); overload; + +function GetClientSizeEx(Control: TWinControl): TPoint; + +const + SHD_DENSE = 0; + SHD_LIGHT = 1; + +{ An additional declaration for D4 compiler } +type + PColor = ^TColor; + +{ Stock Objects } +var + StockBitmap1, StockBitmap2: TBitmap; + StockMonoBitmap, StockCompatibleBitmap: TBitmap; + SmCaptionFont: TFont; + +const + ROP_DSPDxax = $00E20746; + +{ Support for window shadows } +type + TShadowEdges = set of (seTopLeft, seBottomRight); + TShadowStyle = (ssFlat, ssLayered, ssAlphaBlend); + + TShadow = class(TCustomControl) + protected + FOpacity: Byte; + FBuffer: TBitmap; + FClearRect: TRect; + FEdges: TShadowEdges; + FStyle: TShadowStyle; + FSaveBits: Boolean; + procedure GradR(const R: TRect); + procedure GradB(const R: TRect); + procedure GradBR(const R: TRect); + procedure GradTR(const R: TRect); + procedure GradBL(const R: TRect); + procedure CreateParams(var Params: TCreateParams); override; + procedure FillBuffer; virtual; abstract; + procedure WMNCHitTest(var Message: TMessage); message WM_NCHITTEST; + procedure WMEraseBkgnd(var Message: TWMEraseBkgnd); message WM_ERASEBKGND; + public + constructor Create(const Bounds: TRect; Opacity: Byte; LoColor: Boolean; Edges: TShadowEdges); reintroduce; + procedure Clear(const R: TRect); + procedure Render; + procedure Show(ParentHandle: HWND); + end; + + THorzShadow = class(TShadow) + protected + procedure FillBuffer; override; + end; + + TVertShadow = class(TShadow) + protected + procedure FillBuffer; override; + end; + + TShadows = class + private + FSaveBits: Boolean; + procedure SetSaveBits(Value: Boolean); + protected + V1: TShadow; + H1: TShadow; + V2: TShadow; + H2: TShadow; + V3: TShadow; + H3: TShadow; + public + constructor Create(R1, R2: TRect; Size: Integer; Opacity: Byte; LoColor: Boolean); + destructor Destroy; override; + procedure Show(ParentHandle: HWND); + property SaveBits: Boolean read FSaveBits write SetSaveBits; + end; + +procedure RecreateStock; + +type + PBlendFunction = ^TBlendFunction; + TBlendFunction = packed record + BlendOp: Byte; + BlendFlags: Byte; + SourceConstantAlpha: Byte; + AlphaFormat: Byte; + end; + + TUpdateLayeredWindow = function(hWnd : hWnd; hdcDst : hDC; pptDst : PPoint; + psize : PSize; hdcSrc : hDC; pptSrc : PPoint; crKey : TColorRef; + pblend : PBlendFunction; dwFlags : Integer): Integer; stdcall; + + TAlphaBlend = function(hdcDest: HDC; nXOriginDest, nYOriginDest, + nWidthDest, nHeightDest: Integer; hdcSrc: HDC; + nXOriginSrc, nYOriginSrc, nWidthSrc, nHeightSrc: Integer; + blendFunction: TBlendFunction): BOOL; stdcall; + + TGradientFill = function(Handle: HDC; pVertex: Pointer; dwNumVertex: DWORD; + pMesh: Pointer; dwNumMesh: DWORD; dwMode: DWORD): DWORD; stdcall; + +var + UpdateLayeredWindow: TUpdateLayeredWindow = nil; + AlphaBlend: TAlphaBlend = nil; + GradientFill: TGradientFill = nil; + + +implementation + +{$R-}{$Q-} + +uses TB2Common, Math; + + +{$IFDEF TBX_UNICODE} + +function GetTextHeightW(DC: HDC): Integer; +var + TextMetric: TTextMetricW; +begin + GetTextMetricsW(DC, TextMetric); + Result := TextMetric.tmHeight; +end; + +function GetTextWidthW(DC: HDC; const S: WideString; StripAccelChar: Boolean): Integer; +var + Size: TSize; + S2: WideString; +begin + if StripAccelChar then + begin + S2 := StripAccelCharsW(S); + GetTextExtentPoint32W(DC, PWideChar(S2), Length(S2), Size); + end + else GetTextExtentPoint32W(DC, PWideChar(S), Length(S), Size); + Result := Size.cx; +end; + +procedure DrawRotatedTextW(DC: HDC; AText: WideString; const ARect: TRect; const AFormat: Cardinal); +{ Like DrawText, but draws the text at a 270 degree angle. + The format flag this function respects are + DT_NOPREFIX, DT_HIDEPREFIX, DT_CENTER, DT_END_ELLIPSIS, DT_NOCLIP } +var + RotatedFont, SaveFont: HFONT; + TextMetrics: TTextMetricW; + X, Y, P, I, SU, FU, W: Integer; + SaveAlign: UINT; + Clip: Boolean; + + function GetSize(DC: HDC; const S: WideString): Integer; + var + Size: TSize; + begin + GetTextExtentPoint32W(DC, PWideChar(S), Length(S), Size); + Result := Size.cx; + end; + +begin + if Length(AText) = 0 then Exit; + + RotatedFont := CreateRotatedFont(DC); + SaveFont := SelectObject(DC, RotatedFont); + + GetTextMetricsW(DC, TextMetrics); + X := ARect.Left + ((ARect.Right - ARect.Left) - TextMetrics.tmHeight) div 2; + + Clip := AFormat and DT_NOCLIP = 0; + + { Find the index of the character that should be underlined. Delete '&' + characters from the string. Like DrawText, only the last prefixed character + will be underlined. } + P := 0; + I := 1; + if AFormat and DT_NOPREFIX = 0 then + while I <= Length(AText) do + begin + if AText[I] = '&' then + begin + Delete(AText, I, 1); + if PWideChar(AText)[I - 1] <> '&' then P := I; + end; + Inc(I); + end; + + if AFormat and DT_END_ELLIPSIS <> 0 then + begin + if (Length(AText) > 1) and (GetSize(DC, AText) > ARect.Bottom - ARect.Top) then + begin + W := ARect.Bottom - ARect.Top; + if W > 2 then + begin + Delete(AText, Length(AText), 1); + while (Length(AText) > 1) and (GetSize(DC, AText + '...') > W) do + Delete(AText, Length(AText), 1); + end + else AText := AText[1]; + if P > Length(AText) then P := 0; + AText := AText + '...'; + end; + end; + + if AFormat and DT_CENTER <> 0 then + Y := ARect.Top + ((ARect.Bottom - ARect.Top) - GetSize(DC, AText)) div 2 + else + Y := ARect.Top; + + if Clip then + begin + SaveDC(DC); + with ARect do IntersectClipRect(DC, Left, Top, Right, Bottom); + end; + + SaveAlign := SetTextAlign(DC, TA_BOTTOM); + TextOutW(DC, X, Y, PWideChar(AText), Length(AText)); + SetTextAlign(DC, SaveAlign); + + { Underline } + if (P > 0) and (AFormat and DT_HIDEPREFIX = 0) then + begin + SU := GetTextWidthW(DC, Copy(AText, 1, P - 1), False); + FU := SU + GetTextWidthW(DC, PWideChar(AText)[P - 1], False); + Inc(X, TextMetrics.tmDescent - 2); + DrawLineEx(DC, X, Y + SU, X, Y + FU, GetTextColor(DC)); + end; + + if Clip then RestoreDC(DC, -1); + + SelectObject(DC, SaveFont); + DeleteObject(RotatedFont); +end; + +function EscapeAmpersandsW(const S: WideString): WideString; +var + I: Integer; +begin + Result := S; + I := 1; + while I <= Length(Result) do + begin + if Result[I] = '&' then + begin + Inc(I); + Insert('&', Result, I); + end; + Inc(I); + end; +end; + +function FindAccelCharW(const S: WideString): WideChar; +var + PStart, P: PWideChar; +begin + { locate the last char with '&' prefix } + Result := #0; + if Length(S) > 0 then + begin + PStart := PWideChar(S); + P := PStart; + Inc(P, Length(S) - 2); + while P >= PStart do + begin + if P^ = '&' then + begin + if (P = PStart) or (PWideChar(Integer(P) - 2)^ <> '&') then + begin + Result := PWideChar(Integer(P) + 2)^; + Exit; + end + else Dec(P); + end; + Dec(P); + end; + end; +end; + +function StripAccelCharsW(const S: WideString): WideString; +var + I: Integer; +begin + Result := S; + I := 1; + while I <= Length(Result) do + begin + if Result[I] = '&' then + System.Delete(Result, I, 1); + Inc(I); + end; +end; + +function StripTrailingPunctuationW(const S: WideString): WideString; +var + L: Integer; +begin + Result := S; + L := Length(Result); + if (L > 1) and (Result[L] = ':') then SetLength(Result, L - 1) + else if (L > 3) and (Result[L - 2] = '.') and (Result[L - 1] = '.') and + (Result[L] = '.') then SetLength(Result, L - 3); +end; + +{$ENDIF} + +{$IFNDEF JR_D6} +function CheckWin32Version(AMajor, AMinor: Integer = 0): Boolean; {vb+} +begin + Result := (Win32MajorVersion > AMajor) or + ((Win32MajorVersion = AMajor) and (Win32MinorVersion >= AMinor)); +end; +{$ENDIF} + +type + PPoints = ^TPoints; + TPoints = array [0..0] of TPoint; + +const + WeightR: single = 0.764706; + WeightG: single = 1.52941; + WeightB: single = 0.254902; + +procedure GetRGB(C: TColor; out R, G, B: Integer); +begin + if Integer(C) < 0 then C := GetSysColor(C and $000000FF); + R := C and $FF; + G := C shr 8 and $FF; + B := C shr 16 and $FF; +end; + +function MixColors(C1, C2: TColor; W1: Integer): TColor; +var + W2: Cardinal; +begin + Assert(W1 in [0..255]); + W2 := W1 xor 255; + if Integer(C1) < 0 then C1 := GetSysColor(C1 and $000000FF); + if Integer(C2) < 0 then C2 := GetSysColor(C2 and $000000FF); + Result := Integer( + ((Cardinal(C1) and $FF00FF) * Cardinal(W1) + + (Cardinal(C2) and $FF00FF) * W2) and $FF00FF00 + + ((Cardinal(C1) and $00FF00) * Cardinal(W1) + + (Cardinal(C2) and $00FF00) * W2) and $00FF0000) shr 8; +end; + +function SameColors(C1, C2: TColor): Boolean; +begin + if C1 < 0 then C1 := GetSysColor(C1 and $000000FF); + if C2 < 0 then C2 := GetSysColor(C2 and $000000FF); + Result := C1 = C2; +end; + +function Lighten(C: TColor; Amount: Integer): TColor; +var + R, G, B: Integer; +begin + if C < 0 then C := GetSysColor(C and $000000FF); + R := C and $FF + Amount; + G := C shr 8 and $FF + Amount; + B := C shr 16 and $FF + Amount; + if R < 0 then R := 0 else if R > 255 then R := 255; + if G < 0 then G := 0 else if G > 255 then G := 255; + if B < 0 then B := 0 else if B > 255 then B := 255; + Result := R or (G shl 8) or (B shl 16); +end; + +function NearestLighten(C: TColor; Amount: Integer): TColor; +begin + Result := GetNearestColor(StockCompatibleBitmap.Canvas.Handle, Lighten(C, Amount)); +end; + +function NearestMixedColor(C1, C2: TColor; W1: Integer): TColor; +begin + Result := MixColors(C1, C2, W1); + Result := GetNearestColor(StockCompatibleBitmap.Canvas.Handle, Result); +end; + +function ColorIntensity(C: TColor): Integer; +begin + if C < 0 then C := GetSysColor(C and $FF); + Result := ((C shr 16 and $FF) * 30 + (C shr 8 and $FF) * 150 + (C and $FF) * 76) shr 8; +end; + +function IsDarkColor(C: TColor; Threshold: Integer = 100): Boolean; +begin + if C < 0 then C := GetSysColor(C and $FF); + Threshold := Threshold shl 8; + Result := ((C and $FF) * 76 + (C shr 8 and $FF) * 150 + (C shr 16 and $FF) * 30 ) < Threshold; +end; + +function Blend(C1, C2: TColor; W1: Integer): TColor; +var + W2, A1, A2, D, F, G: Integer; +begin + if C1 < 0 then C1 := GetSysColor(C1 and $FF); + if C2 < 0 then C2 := GetSysColor(C2 and $FF); + + if W1 >= 100 then D := 1000 + else D := 100; + + W2 := D - W1; + F := D div 2; + + A2 := C2 shr 16 * W2; + A1 := C1 shr 16 * W1; + G := (A1 + A2 + F) div D and $FF; + Result := G shl 16; + + A2 := (C2 shr 8 and $FF) * W2; + A1 := (C1 shr 8 and $FF) * W1; + G := (A1 + A2 + F) div D and $FF; + Result := Result or G shl 8; + + A2 := (C2 and $FF) * W2; + A1 := (C1 and $FF) * W1; + G := (A1 + A2 + F) div D and $FF; + Result := Result or G; +end; + +function ColorDistance(C1, C2: Integer): Single; +var + DR, DG, DB: Integer; +begin + DR := (C1 and $FF) - (C2 and $FF); + Result := Sqr(DR * WeightR); + DG := (C1 shr 8 and $FF) - (C2 shr 8 and $FF); + Result := Result + Sqr(DG * WeightG); + DB := (C1 shr 16) - (C2 shr 16); + Result := Result + Sqr(DB * WeightB); + Result := SqRt(Result); +end; + +function GetAdjustedThreshold(BkgndIntensity, Threshold: Single): Single; +begin + if BkgndIntensity < 220 then Result := (2 - BkgndIntensity / 220) * Threshold + else Result := Threshold; +end; + +function IsContrastEnough(AColor, ABkgndColor: Integer; + DoAdjustThreshold: Boolean; Threshold: Single): Boolean; +begin + if DoAdjustThreshold then + Threshold := GetAdjustedThreshold(ColorDistance(ABkgndColor, $000000), Threshold); + Result := ColorDistance(ABkgndColor, AColor) > Threshold; +end; + +procedure AdjustContrast(var AColor: Integer; ABkgndColor: Integer; Threshold: Single); +var + x, y, z: Single; + r, g, b: Single; + RR, GG, BB: Integer; + i1, i2, s, q, w: Single; + DoInvert: Boolean; +begin + i1 := ColorDistance(AColor, $000000); + i2 := ColorDistance(ABkgndColor, $000000); + Threshold := GetAdjustedThreshold(i2, Threshold); + + if i1 > i2 then DoInvert := i2 < 442 - Threshold + else DoInvert := i2 < Threshold; + + x := (ABkgndColor and $FF) * WeightR; + y := (ABkgndColor shr 8 and $FF) * WeightG; + z := (ABkgndColor shr 16) * WeightB; + + r := (AColor and $FF) * WeightR; + g := (AColor shr 8 and $FF) * WeightG; + b := (AColor shr 16) * WeightB; + + if DoInvert then + begin + r := 195 - r; + g := 390 - g; + b := 65 - b; + x := 195 - x; + y := 390 - y; + z := 65 - z; + end; + + s := Sqrt(Sqr(b) + Sqr(g) + Sqr(r)); + if s < 0.01 then s := 0.01; + + q := (r * x + g * y + b * z) / S; + + x := Q / S * r - x; + y := Q / S * g - y; + z := Q / S * b - z; + + w := Sqrt(Sqr(Threshold) - Sqr(x) - Sqr(y) - Sqr(z)); + + r := (q - w) * r / s; + g := (q - w) * g / s; + b := (q - w) * b / s; + + if DoInvert then + begin + r := 195 - r; + g := 390 - g; + b := 65 - b; + end; + + if r < 0 then r := 0 else if r > 195 then r := 195; + if g < 0 then g := 0 else if g > 390 then g := 390; + if b < 0 then b := 0 else if b > 65 then b := 65; + + RR := Trunc(r * (1 / WeightR) + 0.5); + GG := Trunc(g * (1 / WeightG) + 0.5); + BB := Trunc(b * (1 / WeightB) + 0.5); + + if RR > $FF then RR := $FF else if RR < 0 then RR := 0; + if GG > $FF then GG := $FF else if GG < 0 then GG := 0; + if BB > $FF then BB := $FF else if BB < 0 then BB := 0; + + AColor := (BB and $FF) shl 16 or (GG and $FF) shl 8 or (RR and $FF); +end; + +procedure SetContrast(var Color: TColor; BkgndColor: TColor; Threshold: Integer); +var + t: Single; +begin + if Color < 0 then Color := GetSysColor(Color and $FF); + if BkgndColor < 0 then BkgndColor := GetSysColor(BkgndColor and $FF); + t := Threshold; + if not IsContrastEnough(Color, BkgndColor, True, t) then + AdjustContrast(Integer(Color), BkgndColor, t); +end; + +procedure RGBtoHSL(RGB: TColor; out H, S, L : Single); +var + R, G, B, D, Cmax, Cmin: Single; +begin + if RGB < 0 then RGB := GetSysColor(RGB and $FF); + R := GetRValue(RGB) / 255; + G := GetGValue(RGB) / 255; + B := GetBValue(RGB) / 255; + Cmax := Max(R, Max(G, B)); + Cmin := Min(R, Min(G, B)); + L := (Cmax + Cmin) / 2; + + if Cmax = Cmin then + begin + H := 0; + S := 0 + end + else + begin + D := Cmax - Cmin; + if L < 0.5 then S := D / (Cmax + Cmin) + else S := D / (2 - Cmax - Cmin); + if R = Cmax then H := (G - B) / D + else + if G = Cmax then H := 2 + (B - R) / D + else H := 4 + (R - G) / D; + H := H / 6; + if H < 0 then H := H + 1 + end; +end; + +function HSLtoRGB(H, S, L: Single): TColor; +const + OneOverThree = 1 / 3; +var + M1, M2: Single; + R, G, B: Byte; + + function HueToColor(Hue: Single): Byte; + var + V: Double; + begin + Hue := Hue - Floor(Hue); + if 6 * Hue < 1 then V := M1 + (M2 - M1) * Hue * 6 + else if 2 * Hue < 1 then V := M2 + else if 3 * Hue < 2 then V := M1 + (M2 - M1) * (2 / 3 - Hue) * 6 + else V := M1; + Result := Round(255 * V); + end; + +begin + if S = 0 then + begin + R := Round(255 * L); + G := R; + B := R; + end + else + begin + if L <= 0.5 then M2 := L * (1 + S) + else M2 := L + S - L * S; + M1 := 2 * L - M2; + R := HueToColor(H + OneOverThree); + G := HueToColor(H); + B := HueToColor(H - OneOverThree) + end; + Result := RGB(R, G, B); +end; + +{ Drawing routines } + +function GetBGR(C: TColorRef): Cardinal; +asm + MOV ECX,EAX // this function swaps R and B bytes in ABGR + SHR EAX,16 + XCHG AL,CL + MOV AH,$00 // and writes $FF into A component + SHL EAX,16 + MOV AX,CX +end; + +procedure SetPixelEx(DC: HDC; X, Y: Integer; C: TColorRef; Alpha: Longword = $FF); +var + W2: Cardinal; + B: TColorRef; +begin + if Alpha <= 0 then Exit + else if Alpha >= 255 then SetPixelV(DC, X, Y, C) + else + begin + B := GetPixel(DC, X, Y); + if B <> CLR_INVALID then + begin + Inc(Alpha, Integer(Alpha > 127)); + W2 := 256 - Alpha; + B := + ((C and $FF00FF) * Alpha + (B and $FF00FF) * W2 + $007F007F) and $FF00FF00 + + ((C and $00FF00) * Alpha + (B and $00FF00) * W2 + $00007F00) and $00FF0000; + SetPixelV(DC, X, Y, B shr 8); + end; + end; +end; + +function CreatePenEx(Color: TColor): HPen; +begin + if Color = clNone then Result := CreatePen(PS_NULL, 1, 0) + else if Color < 0 then Result := CreatePen(PS_SOLID, 1, GetSysColor(Color and $000000FF)) + else Result := CreatePen(PS_SOLID, 1, Color); +end; + +function CreateBrushEx(Color: TColor): HBrush; +var + LB: TLogBrush; +begin + if Color = clNone then + begin + LB.lbStyle := BS_HOLLOW; + Result := CreateBrushIndirect(LB); + end + {else if Color < 0 then Result := GetSysColorBrush(Color and $000000FF)} {vb-} + else begin {vb+} + if Color < 0 then Color := GetSysColor(Color and $000000FF); + Result := CreateSolidBrush(Color); + end; +end; + +function FillRectEx(DC: HDC; const Rect: TRect; Color: TColor): Boolean; +var + Brush: HBRUSH; +begin + Result := Color <> clNone; + if Result then + begin + if Color < 0 then Brush := GetSysColorBrush(Color and $000000FF) + else Brush := CreateSolidBrush(Color); + Windows.FillRect(DC, Rect, Brush); + {DeleteObject(Brush);} {vb-} + if Color >= 0 then DeleteObject(Brush); {vb+} + end; +end; + +function FrameRectEx(DC: HDC; var Rect: TRect; Color: TColor; Adjust: Boolean): Boolean; +var + Brush: HBRUSH; +begin + Result := Color <> clNone; + if Result then + begin + if Color < 0 then Brush := GetSysColorBrush(Color and $000000FF) + else Brush := CreateSolidBrush(Color); + Windows.FrameRect(DC, Rect, Brush); + {DeleteObject(Brush);} {vb-} + if Color >= 0 then DeleteObject(Brush); {vb+} + end; + if Adjust then with Rect do + begin + Inc(Left); Dec(Right); + Inc(Top); Dec(Bottom); + end; +end; + +procedure DrawLineEx(DC: HDC; X1, Y1, X2, Y2: Integer; Color: TColor); +var + OldPen, Pen: HPen; +begin + Pen := CreatePen(PS_SOLID, 1, ColorToRGB(Color)); + OldPen := SelectObject(DC, Pen); + Windows.MoveToEx(DC, X1, Y1, nil); + Windows.LineTo(DC, X2, Y2); + SelectObject(DC, OldPen); + DeleteObject(Pen); +end; + +function PolyLineEx(DC: HDC; const Points: array of TPoint; Color: TColor): Boolean; overload; +var + Pen, OldPen: HPEN; +begin + Result := Color <> clNone; + if Result then + begin + if Color < 0 then Color := GetSysColor(Color and $FF); + Pen := CreatePen(PS_SOLID, 1, Color); + OldPen := SelectObject(DC, Pen); + Windows.Polyline(DC, PPoints(@Points[0])^, Length(Points)); + SelectObject(DC, OldPen); + DeleteObject(Pen); + end; +end; + +procedure PolygonEx(DC: HDC; const Points: array of TPoint; OutlineColor, FillColor: TColor); +var + OldBrush, Brush: HBrush; + OldPen, Pen: HPen; +begin + if (OutlineColor = clNone) and (FillColor = clNone) then Exit; + Pen := CreatePenEx(OutlineColor); + Brush := CreateBrushEx(FillColor); + OldPen := SelectObject(DC, Pen); + OldBrush := SelectObject(DC, Brush); + Windows.Polygon(DC, PPoints(@Points[0])^, Length(Points)); + SelectObject(DC, OldBrush); + SelectObject(DC, OldPen); + DeleteObject(Brush); + DeleteObject(Pen); +end; + +procedure RoundRectEx(DC: HDC; Left, Top, Right, Bottom: Integer; + EllipseWidth, EllipseHeight, OutlineColor, FillColor: TColor); {vb+} +var + OldBrush, Brush: HBrush; + OldPen, Pen: HPen; +begin + if (OutlineColor = clNone) and (FillColor = clNone) then Exit; + Pen := CreatePenEx(OutlineColor); + Brush := CreateBrushEx(FillColor); + OldPen := SelectObject(DC, Pen); + OldBrush := SelectObject(DC, Brush); + Windows.RoundRect(DC, Left, Top, Right, Bottom, EllipseWidth, EllipseHeight); + SelectObject(DC, OldBrush); + SelectObject(DC, OldPen); + DeleteObject(Brush); + DeleteObject(Pen); +end; + +procedure RoundRectEx(DC: HDC; const R: TRect; EllipseWidth, EllipseHeight, + OutlineColor, FillColor: TColor); {vb+} +begin + with R do + RoundRectEx(DC, Left, Top, Right, Bottom, EllipseWidth, + EllipseHeight, OutlineColor, FillColor); +end; + +function CreateDitheredBrush(C1, C2: TColor): HBrush; +var + B: TBitmap; +begin + B := AllocPatternBitmap(C1, C2); + B.HandleType := bmDDB; + Result := CreatePatternBrush(B.Handle); +end; + +procedure DitherRect(DC: HDC; const R: TRect; C1, C2: TColor); +var + Brush: HBRUSH; +begin + Brush := CreateDitheredBrush(C1, C2); + FillRect(DC, R, Brush); + DeleteObject(Brush); +end; + +procedure Frame3D(DC: HDC; var Rect: TRect; TopColor, BottomColor: TColor; Adjust: Boolean); +var + TopRight, BottomLeft: TPoint; +begin + with Rect do + begin + Dec(Bottom); Dec(Right); + TopRight.X := Right; + TopRight.Y := Top; + BottomLeft.X := Left; + BottomLeft.Y := Bottom; + PolyLineEx(DC, [BottomLeft, TopLeft, TopRight], TopColor); + Dec(BottomLeft.X); + PolyLineEx(DC, [TopRight, BottomRight, BottomLeft], BottomColor); + if Adjust then + begin + Inc(Left); + Inc(Top); + end + else + begin + Dec(Right); + Dec(Bottom); + end; + end; +end; + + +{$IFDEF COMPATIBLE_GFX} +procedure DitherRect(Canvas: TCanvas; const R: TRect; C1, C2: TColor); +begin + DitherRect(Canvas.Handle, R, C1, C2); +end; + +procedure Frame3D(Canvas: TCanvas; var Rect: TRect; TopColor, BottomColor: TColor); +var + TopRight, BottomLeft: TPoint; +begin + with Canvas, Rect do + begin + Pen.Width := 1; + Dec(Bottom); Dec(Right); + TopRight.X := Right; + TopRight.Y := Top; + BottomLeft.X := Left; + BottomLeft.Y := Bottom; + Pen.Color := TopColor; + PolyLine([BottomLeft, TopLeft, TopRight]); + Pen.Color := BottomColor; + Dec(BottomLeft.X); + PolyLine([TopRight, BottomRight, BottomLeft]); + Inc(Left); Inc(Top); + end; +end; + +function FillRectEx(Canvas: TCanvas; const Rect: TRect; Color: TColor): Boolean; +begin + Result := FillRectEx(Canvas.Handle, Rect, Color); +end; + +function FillRectEx2(DC: HDC; const Rect: TRect; Color: TColor): Boolean; deprecated; +begin + Result := FillRectEx(DC, Rect, Color); +end; + +function FrameRectEx(Canvas: TCanvas; var Rect: TRect; Color: TColor; Adjust: Boolean = False): Boolean; +begin + Result := FrameRectEx(Canvas.Handle, Rect, Color, Adjust); +end; + +function FrameRectEx2(DC: HDC; var Rect: TRect; Color: TColor; Adjust: Boolean = False): Boolean; deprecated; +begin + Result := FrameRectEx(DC, Rect, Color, Adjust); +end; + +procedure DrawLineEx(Canvas: TCanvas; X1, Y1, X2, Y2: Integer; Color: TColor); +begin + DrawLineEx(Canvas.Handle, X1, Y1, X2, Y2, Color); +end; +{$ENDIF} + +procedure DrawDraggingOutline(DC: HDC; const NewRect, OldRect: TRect); +var + Sz: TSize; +begin + Sz.CX := 3; Sz.CY := 2; + DrawHalftoneInvertRect(DC, @NewRect, @OldRect, Sz, Sz); +end; + +procedure FillLongword(var X; Count: Integer; Value: Longword); +asm +// EAX = X; EDX = Count; ECX = Value + PUSH EDI + MOV EDI,EAX // Point EDI to destination + MOV EAX,ECX + MOV ECX,EDX + TEST ECX,ECX + JS @exit + REP STOSD // Fill count dwords +@exit: + POP EDI +end; + +procedure MoveLongword(const Source; var Dest; Count: Integer); +asm +// EAX = Source; EDX = Dest; ECX = Count + PUSH ESI + PUSH EDI + MOV ESI,EAX // Source + MOV EDI,EDX // Destination + MOV EAX,ECX // Counter + CMP EDI,ESI + JE @exit + REP MOVSD +@exit: + POP EDI + POP ESI +end; + +procedure DrawTBXIcon(Canvas: TCanvas; const R: TRect; + ImageList: TCustomImageList; ImageIndex: Integer; HiContrast: Boolean); +{const + CWeirdColor = $00203241;} {vb -} +var + ImageWidth, ImageHeight: Integer; + I, J: Integer; + Src, Dst: PColor; + S, C: TColor; +begin + if not HiContrast then + begin + ImageList.Draw(Canvas, R.Left, R.Top, ImageIndex); + Exit; + end; + ImageWidth := R.Right - R.Left; + ImageHeight := R.Bottom - R.Top; + with ImageList do + begin + if Width < ImageWidth then ImageWidth := Width; + if Height < ImageHeight then ImageHeight := Height; + end; + + StockBitmap1.Width := ImageWidth; + StockBitmap1.Height := ImageHeight; + StockBitmap2.Width := ImageWidth; + StockBitmap2.Height := ImageHeight; + + BitBlt(StockBitmap1.Canvas.Handle, 0, 0, ImageWidth, ImageHeight, + Canvas.Handle, R.Left, R.Top, SRCCOPY); + {for J := 0 to ImageHeight - 1 do + FillLongWord(StockBitmap2.ScanLine[J]^, ImageWidth, CWeirdColor);} {vb -} + BitBlt(StockBitmap2.Canvas.Handle, 0, 0, ImageWidth, ImageHeight, + Canvas.Handle, R.Left, R.Top, SRCCOPY); {vb +} + ImageList.Draw(StockBitmap2.Canvas, 0, 0, ImageIndex); + + for J := 0 to ImageHeight - 1 do + begin + Src := StockBitmap2.ScanLine[J]; + Dst := StockBitmap1.ScanLine[J]; + for I := 0 to ImageWidth - 1 do + begin + {S := Src^ and $00FFFFFF;} {vb -} + S := Src^; {vb +} + {if S <> CWeirdColor then} {vb -} + if S <> Dst^ then {vb +} + begin + {C := (S and $FF0000) shr 16 * 76 + (S and $00FF00) shr 8 * 150 + + (S and $0000FF) * 29;} {vb -} + C := (S and $00FF0000) shr 16 * 76 + (S and $0000FF00) shr 8 * 150 + + (S and $000000FF) * 29; {vb +} + if C > $FD00 then S := $000000 + else if C < $6400 then S := $FFFFFF; + Dst^ := Lighten(S, 32); + end; + Inc(Src); + Inc(Dst); + end; + end; + BitBlt(Canvas.Handle, R.Left, R.Top, ImageWidth, ImageHeight, + StockBitmap1.Canvas.Handle, 0, 0, SRCCOPY); +end; + +procedure BlendTBXIcon(Canvas: TCanvas; const R: TRect; + ImageList: TCustomImageList; ImageIndex: Integer; Opacity: Byte); +{const + CWeirdColor = $00203241;} {vb -} +var + ImageWidth, ImageHeight: Integer; + I, J: Integer; + Src, Dst: ^Cardinal; + S, C, CBRB, CBG: Cardinal; + Wt1, Wt2: Cardinal; +begin + Wt2 := Opacity; + Wt1 := 255 - Wt2; + ImageWidth := R.Right - R.Left; + ImageHeight := R.Bottom - R.Top; + with ImageList do + begin + if Width < ImageWidth then ImageWidth := Width; + if Height < ImageHeight then ImageHeight := Height; + end; + + StockBitmap1.Width := ImageWidth; + StockBitmap1.Height := ImageHeight; + StockBitmap2.Width := ImageWidth; + StockBitmap2.Height := ImageHeight; + + BitBlt(StockBitmap1.Canvas.Handle, 0, 0, ImageWidth, ImageHeight, + Canvas.Handle, R.Left, R.Top, SRCCOPY); + {BitBlt(StockBitmap2.Canvas.Handle, 0, 0, ImageWidth, ImageHeight, + StockBitmap1.Canvas.Handle, 0, 0, SRCCOPY);} {vb -} + BitBlt(StockBitmap2.Canvas.Handle, 0, 0, ImageWidth, ImageHeight, + Canvas.Handle, R.Left, R.Top, SRCCOPY); {vb +} + ImageList.Draw(StockBitmap2.Canvas, 0, 0, ImageIndex, True); + + for J := 0 to ImageHeight - 1 do + begin + Src := StockBitmap2.ScanLine[J]; + Dst := StockBitmap1.ScanLine[J]; + for I := 0 to ImageWidth - 1 do + begin + S := Src^; + if S <> Dst^ then + begin + CBRB := (Dst^ and $00FF00FF) * Wt1; + CBG := (Dst^ and $0000FF00) * Wt1; + {C := ((S and $FF00FF) * Wt2 + CBRB) and $FF00FF00 + + ((S and $00FF00) * Wt2 + CBG) and $00FF0000;} {vb -} + C := ((S and $00FF00FF) * Wt2 + CBRB) and $FF00FF00 + + ((S and $0000FF00) * Wt2 + CBG) and $00FF0000; {vb +} + Dst^ := C shr 8; + end; + Inc(Src); + Inc(Dst); + end; + end; + BitBlt(Canvas.Handle, R.Left, R.Top, ImageWidth, ImageHeight, + StockBitmap1.Canvas.Handle, 0, 0, SRCCOPY); +end; + +procedure HighlightTBXIcon(Canvas: TCanvas; const R: TRect; + ImageList: TCustomImageList; ImageIndex: Integer; HighlightColor: TColor; Amount: Byte); +{const + CWeirdColor = $00203241;} {vb -} +var + ImageWidth, ImageHeight: Integer; + I, J: Integer; + {Src, Dst: PColor;} {vb -} + Src, Dst: ^Cardinal; {vb +} + S, C: Cardinal; + CBRB, CBG: Cardinal; + W1, W2: Cardinal; +begin + ImageWidth := R.Right - R.Left; + ImageHeight := R.Bottom - R.Top; + with ImageList do + begin + if Width < ImageWidth then ImageWidth := Width; + if Height < ImageHeight then ImageHeight := Height; + end; + + StockBitmap1.Width := ImageWidth; + StockBitmap1.Height := ImageHeight; + StockBitmap2.Width := ImageWidth; + StockBitmap2.Height := ImageHeight; + + BitBlt(StockBitmap1.Canvas.Handle, 0, 0, ImageWidth, ImageHeight, + Canvas.Handle, R.Left, R.Top, SRCCOPY); + {for J := 0 to ImageHeight - 1 do + FillLongWord(StockBitmap2.ScanLine[J]^, ImageWidth, CWeirdColor);} {vb -} + BitBlt(StockBitmap2.Canvas.Handle, 0, 0, ImageWidth, ImageHeight, + Canvas.Handle, R.Left, R.Top, SRCCOPY); {vb +} + ImageList.Draw(StockBitmap2.Canvas, 0, 0, ImageIndex); + + W2 := Amount; + W1 := 255 - W2; + HighlightColor := GetBGR(ColorToRGB(HighlightColor)); + CBRB := (Cardinal(HighlightColor) and $00FF00FF) * W1; + CBG := (Cardinal(HighlightColor) and $0000FF00) * W1; + + for J := 0 to ImageHeight - 1 do + begin + Src := StockBitmap2.ScanLine[J]; + Dst := StockBitmap1.ScanLine[J]; + for I := 0 to ImageWidth - 1 do + begin + {S := Src^ and $00FFFFFF;} {vb -} + S := Src^; {vb +} + {if S <> CWeirdColor then} {vb -} + if S <> Dst^ then {vb +} + begin + {C := ((S and $FF00FF) * W2 + CBRB) and $FF00FF00 + + ((S and $00FF00) * W2 + CBG) and $00FF0000;} {vb -} + C := ((S and $00FF00FF) * W2 + CBRB) and $FF00FF00 + + ((S and $0000FF00) * W2 + CBG) and $00FF0000; {vb +} + Dst^ := C shr 8; + end; + Inc(Src); + Inc(Dst); + end; + end; + BitBlt(Canvas.Handle, R.Left, R.Top, ImageWidth, ImageHeight, + StockBitmap1.Canvas.Handle, 0, 0, SRCCOPY); +end; + +procedure DrawTBXIconShadow(Canvas: TCanvas; const R: TRect; + ImageList: TCustomImageList; ImageIndex: Integer; Density: Integer); +const + D_DIV: array [0..2] of Cardinal = (3, 8, 20); + D_ADD: array [0..2] of Cardinal = (255 - 255 div 3, 255 - 255 div 8, 255 - 255 div 20); +var + ImageWidth, ImageHeight: Integer; + I, J: Integer; + Src, Dst: ^Cardinal; + S, C, CBRB, CBG: Cardinal; +begin + Assert(Density in [0..2]); + + ImageWidth := R.Right - R.Left; + ImageHeight := R.Bottom - R.Top; + with ImageList do + begin + if Width < ImageWidth then ImageWidth := Width; + if Height < ImageHeight then ImageHeight := Height; + end; + + StockBitmap1.Width := ImageWidth; + StockBitmap1.Height := ImageHeight; + StockBitmap2.Width := ImageWidth; + StockBitmap2.Height := ImageHeight; + + BitBlt(StockBitmap1.Canvas.Handle, 0, 0, ImageWidth, ImageHeight, + Canvas.Handle, R.Left, R.Top, SRCCOPY); + {BitBlt(StockBitmap2.Canvas.Handle, 0, 0, ImageWidth, ImageHeight, + StockBitmap1.Canvas.Handle, 0, 0, SRCCOPY);} {vb -} + BitBlt(StockBitmap2.Canvas.Handle, 0, 0, ImageWidth, ImageHeight, + Canvas.Handle, R.Left, R.Top, SRCCOPY); {vb +} + ImageList.Draw(StockBitmap2.Canvas, 0, 0, ImageIndex, True); + + for J := 0 to ImageHeight - 1 do + begin + Src := StockBitmap2.ScanLine[J]; + Dst := StockBitmap1.ScanLine[J]; + for I := 0 to ImageWidth - 1 do + begin + S := Src^; + if S <> Dst^ then + begin + CBRB := Dst^ and $00FF00FF; + CBG := Dst^ and $0000FF00; + {C := ((S and $FF0000) shr 16 * 29 + (S and $00FF00) shr 8 * 150 + + (S and $0000FF) * 76) shr 8;} {vb -} + C := ((S and $00FF0000) shr 16 * 29 + (S and $0000FF00) shr 8 * 150 + + (S and $000000FF) * 76) shr 8; {vb +} + C := C div D_DIV[Density] + D_ADD[Density]; + Dst^ := ((CBRB * C and $FF00FF00) or (CBG * C and $00FF0000)) shr 8; + end; + Inc(Src); + Inc(Dst); + end; + end; + BitBlt(Canvas.Handle, R.Left, R.Top, ImageWidth, ImageHeight, + StockBitmap1.Canvas.Handle, 0, 0, SRCCOPY); +end; + +procedure DrawTBXIconFlatShadow(Canvas: TCanvas; const R: TRect; + ImageList: TCustomImageList; ImageIndex: Integer; ShadowColor: TColor); +const + CShadowThreshold = 180 * 256; +var + ImageWidth, ImageHeight: Integer; + I, J: Integer; + P: ^Cardinal; + C: Cardinal; + SrcDC, DstDC: HDC; +begin + ImageWidth := R.Right - R.Left; + ImageHeight := R.Bottom - R.Top; + with ImageList do + begin + if Width < ImageWidth then ImageWidth := Width; + if Height < ImageHeight then ImageHeight := Height; + end; + + StockBitmap2.Width := ImageWidth; + StockBitmap2.Height := ImageHeight; + StockBitmap2.Canvas.Brush.Color := clWhite; + StockBitmap2.Canvas.FillRect(Rect(0, 0, ImageWidth, ImageHeight)); + ImageList.Draw(StockBitmap2.Canvas, 0, 0, ImageIndex, True); + + for J := 0 to ImageHeight - 1 do + begin + P := StockBitmap2.ScanLine[J]; + for I := 0 to ImageWidth - 1 do + begin + C := P^ and $00FFFFFF; + if C <> $0 then + begin + C := (C and $FF0000) shr 16 * 76 + (C and $00FF00) shr 8 * 150 + (C and $0000FF) * 29; + if C > CShadowThreshold then P^ := $00FFFFFF + else P^ := $00000000; + end; + Inc(P); + end; + end; + + StockMonoBitmap.Width := ImageWidth; + StockMonoBitmap.Height := ImageHeight; + StockMonoBitmap.Canvas.Brush.Color := clBlack; + BitBlt(StockMonoBitmap.Canvas.Handle, 0, 0, ImageWidth, ImageHeight, + StockBitmap2.Canvas.Handle, 0, 0, SRCCOPY); + + SrcDC := StockMonoBitmap.Canvas.Handle; + Canvas.Brush.Color := ColorToRGB(ShadowColor); + DstDC := Canvas.Handle; + Windows.SetTextColor(DstDC, clWhite); + Windows.SetBkColor(DstDC, clBlack); + BitBlt(DstDC, R.Left, R.Top, ImageWidth, ImageHeight, SrcDC, 0, 0, ROP_DSPDxax); +end; + +procedure DrawTBXIconFullShadow(Canvas: TCanvas; const R: TRect; + ImageList: TCustomImageList; ImageIndex: Integer; ShadowColor: TColor); +const + CWeirdColor = $00203241; +var + ImageWidth, ImageHeight: Integer; + I, J: Integer; + P: ^Cardinal; + C: Cardinal; + SrcDC, DstDC: HDC; +begin + ImageWidth := R.Right - R.Left; + ImageHeight := R.Bottom - R.Top; + with ImageList do + begin + if Width < ImageWidth then ImageWidth := Width; + if Height < ImageHeight then ImageHeight := Height; + end; + + StockBitmap2.Width := ImageWidth; + StockBitmap2.Height := ImageHeight; + for J := 0 to ImageHeight - 1 do + FillLongWord(StockBitmap2.ScanLine[J]^, ImageWidth, CWeirdColor); + ImageList.Draw(StockBitmap2.Canvas, 0, 0, ImageIndex, True); + + for J := 0 to ImageHeight - 1 do + begin + P := StockBitmap2.ScanLine[J]; + for I := 0 to ImageWidth - 1 do + begin + C := P^ and $00FFFFFF; + if C <> CWeirdColor then P^ := $00000000 + else P^ := $00FFFFFF; + Inc(P); + end; + end; + + StockMonoBitmap.Width := ImageWidth; + StockMonoBitmap.Height := ImageHeight; + StockMonoBitmap.Canvas.Brush.Color := clBlack; + BitBlt(StockMonoBitmap.Canvas.Handle, 0, 0, ImageWidth, ImageHeight, + StockBitmap2.Canvas.Handle, 0, 0, SRCCOPY); + + SrcDC := StockMonoBitmap.Canvas.Handle; + Canvas.Brush.Color := ColorToRGB(ShadowColor); + DstDC := Canvas.Handle; + Windows.SetTextColor(DstDC, clWhite); + Windows.SetBkColor(DstDC, clBlack); + BitBlt(DstDC, R.Left, R.Top, ImageWidth, ImageHeight, SrcDC, 0, 0, ROP_DSPDxax); +end; + +procedure DrawGlyph(DC: HDC; X, Y: Integer; ImageList: TCustomImageList; ImageIndex: Integer; Color: TColor); +var + B: TBitmap; + OldTextColor, OldBkColor: Longword; + OldBrush, Brush: HBrush; +begin + if Color = clNone then Exit; + B := TBitmap.Create; + B.Monochrome := True; + ImageList.GetBitmap(ImageIndex, B); + OldTextColor := SetTextColor(DC, clBlack); + OldBkColor := SetBkColor(DC, clWhite); + if Color < 0 then Brush := GetSysColorBrush(Color and $FF) + else Brush := CreateSolidBrush(Color); + OldBrush := SelectObject(DC, Brush); + BitBlt(DC, X, Y, ImageList.Width, ImageList.Height, B.Canvas.Handle, 0, 0, ROP_DSPDxax); + SelectObject(DC, OldBrush); + if Color >= 0 then DeleteObject(Brush); + SetTextColor(DC, OldTextColor); + SetBkColor(DC, OldBkColor); + B.Free; +end; + +procedure DrawGlyph(DC: HDC; const R: TRect; ImageList: TCustomImageList; ImageIndex: Integer; Color: TColor); overload; +begin + DrawGlyph(DC, (R.Left + R.Right + 1 - ImageList.Width) div 2, (R.Top + R.Bottom + 1 - ImageList.Height) div 2, ImageList, ImageIndex, Color); +end; + +procedure DrawGlyph(DC: HDC; X, Y: Integer; const Bits; Color: TColor); overload; +var + B: TBitmap; + OldTextColor, OldBkColor: Longword; + OldBrush, Brush: HBrush; +begin + B := TBitmap.Create; + B.Handle := CreateBitmap(8, 8, 1, 1, @Bits); + OldTextColor := SetTextColor(DC, clBlack); + OldBkColor := SetBkColor(DC, clWhite); + if Color < 0 then Brush := GetSysColorBrush(Color and $FF) + else Brush := CreateSolidBrush(Color); + OldBrush := SelectObject(DC, Brush); + BitBlt(DC, X, Y, 8, 8, B.Canvas.Handle, 0, 0, ROP_DSPDxax); + SelectObject(DC, OldBrush); + if Color >= 0 then DeleteObject(Brush); + SetTextColor(DC, OldTextColor); + SetBkColor(DC, OldBkColor); + B.Free; +end; + +procedure DrawGlyph(DC: HDC; const R: TRect; Width, Height: Integer; const Bits; Color: TColor); overload; +var + B: TBitmap; + OldTextColor, OldBkColor: Longword; + OldBrush, Brush: HBrush; +begin + B := TBitmap.Create; + B.Handle := CreateBitmap(8, 8, 1, 1, @Bits); + OldTextColor := SetTextColor(DC, clBlack); + OldBkColor := SetBkColor(DC, clWhite); + if Color < 0 then Brush := GetSysColorBrush(Color and $FF) + else Brush := CreateSolidBrush(Color); + OldBrush := SelectObject(DC, Brush); + BitBlt(DC, (R.Left + R.Right + 1 - Width) div 2, (R.Top + R.Bottom + 1 - Height) div 2, Width, Height, B.Canvas.Handle, 0, 0, ROP_DSPDxax); + SelectObject(DC, OldBrush); + if Color >= 0 then DeleteObject(Brush); + SetTextColor(DC, OldTextColor); + SetBkColor(DC, OldBkColor); + B.Free; +end; + +type + TCustomFormAccess = class(TCustomForm); + +function GetClientSizeEx(Control: TWinControl): TPoint; +var + R: TRect; +begin + if (Control is TCustomForm) and (TCustomFormAccess(Control).FormStyle = fsMDIForm) + and not (csDesigning in Control.ComponentState) then + GetWindowRect(TCustomFormAccess(Control).ClientHandle, R) + else + R := Control.ClientRect; + Result.X := R.Right - R.Left; + Result.Y := R.Bottom - R.Top; +end; + +procedure InitializeStock; +var + NonClientMetrics: TNonClientMetrics; +begin + StockBitmap1 := TBitmap.Create; + StockBitmap1.PixelFormat := pf32bit; + StockBitmap2 := TBitmap.Create; + StockBitmap2.PixelFormat := pf32bit; + StockMonoBitmap := TBitmap.Create; + StockMonoBitmap.Monochrome := True; + StockCompatibleBitmap := TBitmap.Create; + StockCompatibleBitmap.Width := 8; + StockCompatibleBitmap.Height := 8; + SmCaptionFont := TFont.Create; + NonClientMetrics.cbSize := SizeOf(NonClientMetrics); + if SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, @NonClientMetrics, 0) then + SmCaptionFont.Handle := CreateFontIndirect(NonClientMetrics.lfSmCaptionFont); +end; + +procedure FinalizeStock; +begin + SmCaptionFont.Free; + SmCaptionFont := nil; + StockCompatibleBitmap.Free; + StockMonoBitmap.Free; + StockBitmap2.Free; + StockBitmap1.Free; +end; + +procedure RecreateStock; +begin + FinalizeStock; + InitializeStock; +end; + +{ TShadow } //////////////////////////////////////////////////////////////////// + +procedure TShadow.Clear(const R: TRect); +begin + FClearRect := R; +end; + +constructor TShadow.Create(const Bounds: TRect; Opacity: Byte; LoColor: Boolean; Edges: TShadowEdges); +begin + inherited Create(nil); + Hide; + ParentWindow := Application.Handle; + BoundsRect := Bounds; + Color := clBtnShadow; + FOpacity := Opacity; + FEdges := Edges; + FSaveBits := False; + + if LoColor then FStyle := ssFlat + else if (@UpdateLayeredWindow <> nil) and (@AlphaBlend <> nil) then + FStyle := ssLayered + else if @AlphaBlend <> nil then + FStyle := ssAlphaBlend + else + FStyle := ssFlat; +end; + +procedure TShadow.CreateParams(var Params: TCreateParams); +begin + inherited; + with Params do + begin + Style := (Style and not (WS_CHILD or WS_GROUP or WS_TABSTOP)) or WS_POPUP; + ExStyle := ExStyle or WS_EX_TOOLWINDOW; + if FSaveBits then WindowClass.Style := WindowClass.Style or CS_SAVEBITS; + end; +end; + +procedure TShadow.GradB(const R: TRect); +var + J, W, H: Integer; + V: Cardinal; + P: ^Cardinal; +begin + W := R.Right - R.Left; + H := R.Bottom - R.Top; + for J := 0 to H - 1 do + begin + P := FBuffer.ScanLine[J + R.Top]; + Inc(P, R.Left); + V := (255 - J shl 8 div H) shl 24; + FillLongword(P^, W, V); + end; +end; + +procedure TShadow.GradBL(const R: TRect); +var + I, J, W, H, CX, CY, D, DMax, A, B: Integer; + P: ^Cardinal; +begin + W := R.Right - R.Left; + H := R.Bottom - R.Top; + DMax := W; + if H > W then DMax := H; + CX := DMax - 1; + CY := H - DMax; + for J := 0 to H - 1 do + begin + P := FBuffer.ScanLine[J + R.Top]; + Inc(P, R.Left); + for I := 0 to W - 1 do + begin + A := Abs(I - CX); + B := Abs(J - CY); + D := A; + if B > A then D := B; + D := (A + B + D) * 128 div DMax; + if D < 255 then P^ := (255 - D) shl 24 + else P^ := 0; + Inc(P); + end; + end; +end; + +procedure TShadow.GradBR(const R: TRect); +var + I, J, W, H, CX, CY, D, DMax, A, B: Integer; + P: ^Cardinal; +begin + W := R.Right - R.Left; + H := R.Bottom - R.Top; + DMax := W; + if H > W then DMax := H; + CX := W - DMax; + CY := H - DMax; + for J := 0 to H - 1 do + begin + P := FBuffer.ScanLine[J + R.Top]; + Inc(P, R.Left); + for I := 0 to W - 1 do + begin + A := Abs(I - CX); + B := Abs(J - CY); + D := A; + if B > A then D := B; + D := (A + B + D) * 128 div DMax; + if D < 255 then P^ := (255 - D) shl 24 + else P^ := 0; + Inc(P); + end; + end; +end; + +procedure TShadow.GradR(const R: TRect); +var + I, J, W: Integer; + P: ^Cardinal; + ScanLine: array of Cardinal; +begin + W := R.Right - R.Left; + SetLength(ScanLine, W); + for I := 0 to W - 1 do + ScanLine[I] :=(255 - I shl 8 div W) shl 24; + + for J := R.Top to R.Bottom - 1 do + begin + P := FBuffer.ScanLine[J]; + Inc(P, R.Left); + MoveLongword(ScanLine[0], P^, W); + end; +end; + +procedure TShadow.GradTR(const R: TRect); +var + I, J, W, H, CX, CY, D, DMax, A, B: Integer; + P: ^Cardinal; +begin + W := R.Right - R.Left; + H := R.Bottom - R.Top; + DMax := W; + if H > W then DMax := H; + CX := W - DMax; + CY := DMax - 1; + for J := 0 to H - 1 do + begin + P := FBuffer.ScanLine[J + R.Top]; + Inc(P, R.Left); + for I := 0 to W - 1 do + begin + A := Abs(I - CX); + B := Abs(J - CY); + D := A; + if B > A then D := B; + D := (A + B + D) * 128 div DMax; + if D < 255 then P^ := (255 - D) shl 24 + else P^ := 0; + Inc(P); + end; + end; +end; + +procedure TShadow.Render; +var + DstDC: HDC; + SrcPos, DstPos: TPoint; + Size: TSize; + BlendFunc: TBlendFunction; +begin + if FStyle <> ssLayered then Exit; + Assert(Assigned(UpdateLayeredWindow)); + + SetWindowLong(Handle, GWL_EXSTYLE, GetWindowLong(Handle, GWL_EXSTYLE) or $00080000{WS_EX_LAYERED}); + DstDC := GetDC(0); + try + SrcPos := Point(0, 0); + with BoundsRect do + begin + DstPos := Point(Left, Top); + Size.cx := Right - Left; + Size.cy := Bottom - Top; + end; + BlendFunc.BlendOp := 0; + BlendFunc.BlendFlags := 0; + BlendFunc.SourceConstantAlpha := FOpacity; + BlendFunc.AlphaFormat := 1; + + FBuffer := TBitmap.Create; + FBuffer.PixelFormat := pf32bit; + FBuffer.Width := Size.cx; + FBuffer.Height := Size.cy; + + FillBuffer; + + UpdateLayeredWindow( + Handle, + DstDC, + @DstPos, + @Size, + FBuffer.Canvas.Handle, + @SrcPos, + 0, + @BlendFunc, + $00000002{ULW_ALPHA}); + + FBuffer.Free; + finally + ReleaseDC(0, DstDC); + end; +end; + +procedure TShadow.Show(ParentHandle: HWND); +begin + SetWindowPos(Handle, ParentHandle, 0, 0, 0, 0, + SWP_NOACTIVATE or SWP_NOSENDCHANGING or SWP_NOMOVE or + SWP_NOOWNERZORDER or SWP_NOSIZE or SWP_SHOWWINDOW); +end; + +procedure TShadow.WMEraseBkgnd(var Message: TWMEraseBkgnd); +var + SrcPos, DstPos: TPoint; + Size: TSize; + BlendFunc: TBlendFunction; +begin + if FStyle = ssAlphaBlend then + begin + Assert(Assigned(AlphaBlend)); + + { Dispatch all the painting messages } + ProcessPaintMessages; + + SrcPos := Point(0, 0); + with BoundsRect do + begin + DstPos := Point(Left, Top); + Size.cx := Right - Left; + Size.cy := Bottom - Top; + end; + + FBuffer := TBitmap.Create; + FBuffer.PixelFormat := pf32bit; + FBuffer.Width := Size.cx; + FBuffer.Height := Size.cy; + + FillBuffer; + + { Blend the buffer directly into the screen } + BlendFunc.BlendOp := 0; + BlendFunc.BlendFlags := 0; + BlendFunc.SourceConstantAlpha := FOpacity; + BlendFunc.AlphaFormat := 1; + AlphaBlend(Message.DC, 0, 0, Size.cx, Size.cy, + FBuffer.Canvas.Handle, 0, 0, Size.cx, Size.cy, BlendFunc); + FBuffer.Free; + + Message.Result := 1; + end + else inherited; +end; + +procedure TShadow.WMNCHitTest(var Message: TMessage); +begin + Message.Result := HTTRANSPARENT; +end; + +{ THorzShadow } + +procedure THorzShadow.FillBuffer; +var + R: TRect; + L1, L2, L3: Integer; +begin + if seTopLeft in FEdges then L1 := Height else L1 := 0; + if seBottomRight in FEdges then L3 := Height else L3 := 0; + if L1 + L3 > Width then + begin + if (L1 > 0) and (L3 > 0) then + begin + L1 := Width div 2; + L3 := L1; + end + else if L1 > 0 then L1 := Width + else if L3 > 0 then L3 := Width; + end; + L2 := Width - L1 - L3; + R := Rect(0, 0, Width, Height); + R.Right := R.Left + L1; + if L1 > 0 then GradBL(R); + R.Left := R.Right; + R.Right := R.Left + L2; + if L2 > 0 then GradB(R); + if L3 > 0 then + begin + R.Left := R.Right; + R.Right := R.Left + L3; + GradBR(R); + end; +end; + +{ TVertShadow } + +procedure TVertShadow.FillBuffer; +var + R: TRect; + L1, L2, L3: Integer; +begin + if seTopLeft in FEdges then L1 := Width else L1 := 0; + if seBottomRight in FEdges then L3 := Width else L3 := 0; + if L1 + L3 > Height then + begin + if (L1 > 0) and (L3 > 0) then + begin + L1 := Height div 2; + L3 := L1; + end + else if L1 > 0 then L1 := Height + else if L3 > 0 then L3 := Height; + end; + L2 := Height - L1 - L3; + + R := Rect(0, 0, Width, Height); + R.Bottom := R.Top + L1; + if L1 > 0 then GradTR(R); + R.Top := R.Bottom; + R.Bottom := R.Top + L2; + if L2 > 0 then GradR(R); + if L3 > 0 then + begin + R.Top := R.Bottom; + R.Bottom := R.Top + L3; + GradBR(R); + end; +end; + +{ TShadows } + +constructor TShadows.Create(R1, R2: TRect; Size: Integer; Opacity: Byte; LoColor: Boolean); +var + R: TRect; + R1Valid, R2Valid: Boolean; +begin + if LoColor or + ((@UpdateLayeredWindow = nil) and (@AlphaBlend = nil)) then + begin + Size := Size div 2; + end; + + R1Valid := not IsRectEmpty(R1); + R2Valid := not IsRectEmpty(R2); + if not (R1Valid or R2Valid) then Exit; + + if R1Valid xor R2Valid then + begin + { A simple square shadow } + if R1Valid then R := R1 else R:= R2; + with R do + begin + V1 := TVertShadow.Create(Rect(Right, Top + Size, Right + Size, Bottom), Opacity, LoColor, [seTopLeft]); + H1 := THorzShadow.Create(Rect(Left + Size, Bottom, Right + Size, Bottom + Size), Opacity, LoColor, [seTopLeft, seBottomRight]) + end; + end + else + begin + + if (R1.Bottom <= R2.Top + 2) or (R1.Top >= R2.Bottom - 2) then + begin + if R1.Top > R2.Top then + begin + R := R2; + R2 := R1; + R1 := R; + end; + if R1.Left + Size < R2.Left then + H1 := THorzShadow.Create(Rect(R1.Left + Size, R1.Bottom, R2.Left, R1.Bottom + Size), Opacity, LoColor, [seTopLeft]); + H2 := THorzShadow.Create(Rect(R2.Left + Size, R2.Bottom, R2.Right + Size, R2.Bottom + Size), Opacity, LoColor, [seTopLeft, seBottomRight]); + V1 := TVertShadow.Create(Rect(R1.Right, R1.Top + Size, R1.Right + Size, R1.Bottom), Opacity, LoColor, [seTopLeft]); + if R1.Right > R2.Right then + H3 := THorzShadow.Create(Rect(R2.Right, R1.Bottom, R1.Right + Size, R1.Bottom + Size), Opacity, LoColor, [seTopLeft, seBottomRight]); + if R1.Right + Size < R2.Right then + V2 := TVertShadow.Create(Rect(R2.Right, R2.Top + Size, R2.Right + Size, R2.Bottom), Opacity, LoColor, [seTopLeft]) + else + V2 := TVertShadow.Create(Rect(R2.Right, R2.Top + 1, R2.Right + Size, R2.Bottom), Opacity, LoColor, []); + end + else if (R1.Right <= R2.Left + 2) or (R1.Left >= R2.Right - 2) then + begin + if R1.Left > R2.Left then + begin + R := R2; + R2 := R1; + R1 := R; + end; + if R1.Top + Size < R2.Top then + V1 := TVertShadow.Create(Rect(R1.Right, R1.Top + Size, R1.Right + Size, R2.Top), Opacity, LoColor, [seTopLeft]); + V2 := TVertShadow.Create(Rect(R2.Right, R2.Top + Size, R2.Right + Size, R2.Bottom + Size), Opacity, LoColor, [seTopLeft, seBottomRight]); + H1 := THorzShadow.Create(Rect(R1.Left + Size, R1.Bottom, R1.Right, R1.Bottom + Size), Opacity, LoColor, [seTopLeft]); + if R1.Bottom > R2.Bottom then + V3 := TVertShadow.Create(Rect(R1.Right, R2.Bottom, R1.Right + Size, R1.Bottom + Size), Opacity, LoColor, [seTopLeft, seBottomRight]); + if R1.Bottom + Size < R2.Bottom then + H2 := THorzShadow.Create(Rect(R2.Left + Size, R2.Bottom, R2.Right, R2.Bottom + Size), Opacity, LoColor, [seTopLeft]) + else + H2 := THorzShadow.Create(Rect(R2.Left, R2.Bottom, R2.Right, R2.Bottom + Size), Opacity, LoColor, []); + end; + end; + + if V1 <> nil then V1.Render; + if H1 <> nil then H1.Render; + if V2 <> nil then V2.Render; + if H2 <> nil then H2.Render; + if V3 <> nil then V3.Render; + if H3 <> nil then H3.Render; + + SetSaveBits(True); +end; + +destructor TShadows.Destroy; +begin + H3.Free; + V3.Free; + H2.Free; + V2.Free; + H1.Free; + V1.Free; + inherited; +end; + +procedure TShadows.SetSaveBits(Value: Boolean); +begin + FSaveBits := Value; + if V1 <> nil then V1.FSaveBits := Value; + if H1 <> nil then H1.FSaveBits := Value; + if V2 <> nil then V2.FSaveBits := Value; + if H2 <> nil then H2.FSaveBits := Value; + if V3 <> nil then V3.FSaveBits := Value; + if H3 <> nil then H3.FSaveBits := Value; +end; + +procedure TShadows.Show(ParentHandle: HWND); +begin + if V1 <> nil then V1.Show(ParentHandle); + if H1 <> nil then H1.Show(ParentHandle); + if V2 <> nil then V2.Show(ParentHandle); + if H2 <> nil then H2.Show(ParentHandle); + if V3 <> nil then V3.Show(ParentHandle); + if H3 <> nil then H3.Show(ParentHandle); +end; + +{ Gradients } ////////////////////////////////////////////////////////////////// + +const + GRADIENT_CACHE_SIZE = 16; + +type + PRGBQuad = ^TRGBQuad; + TRGBQuad = Integer; + PRGBQuadArray = ^TRGBQuadArray; + TRGBQuadArray = array [0..0] of TRGBQuad; + + +var + GradientCache: array [0..GRADIENT_CACHE_SIZE] of array of TRGBQuad; + NextCacheIndex: Integer = 0; + +function FindGradient(Size: Integer; CL, CR: TRGBQuad): Integer; +begin + Assert(Size > 0); + Result := GRADIENT_CACHE_SIZE - 1; + while Result >= 0 do + begin + if (Length(GradientCache[Result]) = Size) and + (GradientCache[Result][0] = CL) and + (GradientCache[Result][Length(GradientCache[Result]) - 1] = CR) then Exit; + Dec(Result); + end; +end; + +function MakeGradient(Size: Integer; CL, CR: TRGBQuad): Integer; +var + R1, G1, B1: Integer; + R2, G2, B2: Integer; + R, G, B: Integer; + I: Integer; + Bias: Integer; +begin + Assert(Size > 0); + Result := NextCacheIndex; + Inc(NextCacheIndex); + if NextCacheIndex >= GRADIENT_CACHE_SIZE then NextCacheIndex := 0; + R1 := CL and $FF; + G1 := CL shr 8 and $FF; + B1 := CL shr 16 and $FF; + R2 := CR and $FF - R1; + G2 := CR shr 8 and $FF - G1; + B2 := CR shr 16 and $FF - B1; + SetLength(GradientCache[Result], Size); + Dec(Size); + Bias := Size div 2; + if Size > 0 then + for I := 0 to Size do + begin + R := R1 + (R2 * I + Bias) div Size; + G := G1 + (G2 * I + Bias) div Size; + B := B1 + (B2 * I + Bias) div Size; + GradientCache[Result][I] := R + G shl 8 + B shl 16; + end + else + begin + R := R1 + R2 div 2; + G := G1 + G2 div 2; + B := B1 + B2 div 2; + GradientCache[Result][0] := R + G shl 8 + B shl 16; + end; +end; + +function GetGradient(Size: Integer; CL, CR: TRGBQuad): Integer; +begin + Result := FindGradient(Size, CL, CR); + if Result < 0 then Result := MakeGradient(Size, CL, CR); +end; + +{ GradFill function } + +procedure GradFill(DC: HDC; ARect: TRect; ClrTopLeft, ClrBottomRight: TColor; Kind: TGradientKind); +const + GRAD_MODE: array [TGradientKind] of DWORD = (GRADIENT_FILL_RECT_H, GRADIENT_FILL_RECT_V); + W: array [TGradientKind] of Integer = (2, 1); + H: array [TGradientKind] of Integer = (1, 2); +type + TriVertex = packed record + X, Y: Longint; + R, G, B, A: Word; + end; +var + V: array [0..1] of TriVertex; + GR: GRADIENT_RECT; + Size, I, Start, Finish: Integer; + GradIndex: Integer; + R, CR: TRect; + Brush: HBRUSH; +begin + if not RectVisible(DC, ARect) then Exit; + + ClrTopLeft := ColorToRGB(ClrTopLeft); + ClrBottomRight := ColorToRGB(ClrBottomRight); + if @GradientFill <> nil then + begin + { Use msimg32.dll } + with V[0] do + begin + X := ARect.Left; + Y := ARect.Top; + R := ClrTopLeft shl 8 and $FF00; + G := ClrTopLeft and $FF00; + B := ClrTopLeft shr 8 and $FF00; + A := 0; + end; + with V[1] do + begin + X := ARect.Right; + Y := ARect.Bottom; + R := ClrBottomRight shl 8 and $FF00; + G := ClrBottomRight and $FF00; + B := ClrBottomRight shr 8 and $FF00; + A := 0; + end; + GR.UpperLeft := 0; GR.LowerRight := 1; + GradientFill(DC, @V, 2, @GR, 1, GRAD_MODE[Kind]); + end + else + begin + { Have to do it manually if msimg32.dll is not available } + GetClipBox(DC, CR); + + if Kind = gkHorz then + begin + Size := ARect.Right - ARect.Left; + if Size <= 0 then Exit; + Start := 0; Finish := Size - 1; + if CR.Left > ARect.Left then Inc(Start, CR.Left - ARect.Left); + if CR.Right < ARect.Right then Dec(Finish, ARect.Right - CR.Right); + R := ARect; Inc(R.Left, Start); R.Right := R.Left + 1; + end + else + begin + Size := ARect.Bottom - ARect.Top; + if Size <= 0 then Exit; + Start := 0; Finish := Size - 1; + if CR.Top > ARect.Top then Inc(Start, CR.Top - ARect.Top); + if CR.Bottom < ARect.Bottom then Dec(Finish, ARect.Bottom - CR.Bottom); + R := ARect; Inc(R.Top, Start); R.Bottom := R.Top + 1; + end; + GradIndex := GetGradient(Size, ClrTopLeft, ClrBottomRight); + for I := Start to Finish do + begin + Brush := CreateSolidBrush(GradientCache[GradIndex][I]); + Windows.FillRect(DC, R, Brush); + OffsetRect(R, Integer(Kind = gkHorz), Integer(Kind = gkVert)); + DeleteObject(Brush); + end; + end; +end; + +{ Brushed Fill } /////////////////////////////////////////////////////////////// + +{ Templates } + +const + NUM_TEMPLATES = 8; + MIN_TEMPLATE_SIZE = 100; + MAX_TEMPLATE_SIZE = 200; + +var + ThreadTemplates: array [0..NUM_TEMPLATES - 1] of array of Integer; + RandThreadIndex: array [0..1023] of Integer; + RandThreadPositions: array [0..1023] of Integer; + +procedure InitializeBrushedFill; +const + Pi = 3.14159265358987; +var + TemplateIndex, Size, I, V, V1, V2: Integer; + T, R12, R13, R14, R21, R22, R23, R24: Single; +begin + { Make thread templates } + for TemplateIndex := 0 to NUM_TEMPLATES - 1 do + begin + Size := (MIN_TEMPLATE_SIZE + Random(MAX_TEMPLATE_SIZE - MIN_TEMPLATE_SIZE + 1)) div 2; + SetLength(ThreadTemplates[TemplateIndex], Size * 2); + R12 := Random * 2 * Pi; + R13 := Random * 2 * Pi; + R14 := Random * 2 * Pi; + R21 := Random * 2 * Pi; + R22 := Random * 2 * Pi; + R23 := Random * 2 * Pi; + R24 := Random * 2 * Pi; + for I := 0 to Size - 1 do + begin + T := 2 * Pi * I / Size; + V1 := Round(150 * Sin(T) + 100 * Sin(2 * T + R12) + 50 * Sin(3 * T + R13) + 20 * Sin(4 * T + R14)); + if V1 > 255 then V1 := 255; + if V1 < -255 then V1 := -255; + + V2 := Round(150 * Sin(T + R21) + 100 * Sin(2 * T + R22) + 50 * Sin(3 * T + R23) + 20 * Sin(4 * T + R24)); + if V2 > 255 then V2 := 255; + if V2 < -255 then V2 := -255; + + if Abs(V2 - V1) > 300 then + begin + V := (V1 + V2) div 2; + V1 := V - 150; + V2 := V + 150; + end; + + ThreadTemplates[TemplateIndex][I * 2] := Min(V1, V2); + ThreadTemplates[TemplateIndex][I * 2 + 1] := Max(V1, V2); + end; + end; + + { Initialize Rand arrays } + for I := 0 to 1023 do + begin + RandThreadIndex[I] := Random(NUM_TEMPLATES); + V1 := Random(Length(ThreadTemplates[RandThreadIndex[I]])) and not $1; + if Odd(I) then Inc(V1); + RandThreadPositions[I] := V1; + end; +end; + +{ Cache } + +const + THREAD_CACHE_SIZE = 16; + +type + TThreadCacheItem = record + BaseColor: TColorRef; + Roughness: Integer; + Bitmaps: array [0..NUM_TEMPLATES - 1] of HBITMAP; + end; + +var + ThreadCache: array [0..THREAD_CACHE_SIZE] of TThreadCacheItem; + NextCacheEntry: Integer = 0; + +procedure ClearCacheItem(var CacheItem: TThreadCacheItem); +var + I: Integer; +begin + with CacheItem do + begin + BaseColor := $FFFFFFFF; + Roughness := -1; + for I := NUM_TEMPLATES - 1 downto 0 do + begin + if Bitmaps[I] <> 0 then + begin + DeleteObject(Bitmaps[I]); + Bitmaps[I] := 0; + end; + end; + end; +end; + +procedure ResetBrushedFillCache; +var + I: Integer; +begin + { Should be called each time the screen parameters change } + for I := THREAD_CACHE_SIZE - 1 downto 0 do ClearCacheItem(ThreadCache[I]); +end; + +procedure FinalizeBrushedFill; +begin + ResetBrushedFillCache; +end; + +procedure MakeCacheItem(var CacheItem: TThreadCacheItem; Color: TColorRef; Roughness: Integer); +var + TemplateIndex, Size, I, V: Integer; + CR, CG, CB: Integer; + R, G, B: Integer; + ScreenDC: HDC; + BMI: TBitmapInfo; + Bits: PRGBQuadArray; + DIBSection: HBITMAP; + DIBDC, CacheDC: HDC; +begin + ScreenDC := GetDC(0); + FillChar(BMI, SizeOf(TBitmapInfo), 0); + with BMI.bmiHeader do + begin + biSize := SizeOf(TBitmapInfoHeader); + biPlanes := 1; + biCompression := BI_RGB; + biWidth := MAX_TEMPLATE_SIZE; + biHeight := -1; + biBitCount := 32; + end; + DIBSection := CreateDIBSection(0, BMI, DIB_RGB_COLORS, Pointer(Bits), 0, 0); + DIBDC := CreateCompatibleDC(0); + SelectObject(DIBDC, DIBSection); + CacheDC := CreateCompatibleDC(0); + + CR := Color shl 8 and $FF00; + CG := Color and $FF00; + CB := Color shr 8 and $FF00; + + try + for TemplateIndex := 0 to NUM_TEMPLATES - 1 do + begin + CacheItem.BaseColor := Color; + CacheItem.Roughness := Roughness; + Size := Length(ThreadTemplates[TemplateIndex]); + + if CacheItem.Bitmaps[TemplateIndex] = 0 then + CacheItem.Bitmaps[TemplateIndex] := CreateCompatibleBitmap(ScreenDC, Size, 1); + SelectObject(CacheDC, CacheItem.Bitmaps[TemplateIndex]); + + for I := 0 to Size - 1 do + begin + V := ThreadTemplates[TemplateIndex][I]; + R := CR + V * Roughness; + G := CG + V * Roughness; + B := CB + V * Roughness; + if R < 0 then R := 0; + if G < 0 then G := 0; + if B < 0 then B := 0; + if R > $EF00 then R := $EF00; + if G > $EF00 then G := $EF00; + if B > $EF00 then B := $EF00; + Bits^[I] := (R and $FF00 + (G and $FF00) shl 8 + (B and $FF00) shl 16) shr 8; + end; + + BitBlt(CacheDC, 0, 0, Size, 1, DIBDC, 0, 0, SRCCOPY); + end; + + finally + DeleteDC(CacheDC); + DeleteDC(DIBDC); + DeleteObject(DIBSection); + ReleaseDC(0, ScreenDC); + end; +end; + +function FindCacheItem(Color: TColorRef; Roughness: Integer): Integer; +begin + Result := THREAD_CACHE_SIZE - 1; + while Result >= 0 do + if (ThreadCache[Result].BaseColor = Color) and (ThreadCache[Result].Roughness = Roughness) then Exit + else Dec(Result); +end; + +function GetCacheItem(Color: TColorRef; Roughness: Integer): Integer; +begin + Result := FindCacheItem(Color, Roughness); + if Result >= 0 then Exit + else + begin + Result := NextCacheEntry; + MakeCacheItem(ThreadCache[Result], Color, Roughness); + NextCacheEntry := (NextCacheEntry + 1) mod THREAD_CACHE_SIZE; + end; +end; + +procedure BrushedFill(DC: HDC; Origin: PPoint; ARect: TRect; Color: TColor; Roughness: Integer); +const + ZeroOrigin: TPoint = (X: 0; Y: 0); +var + CR: TColorRef; + X, Y: Integer; + CacheIndex: Integer; + TemplateIndex: Integer; + CacheDC: HDC; + Size: Integer; + BoxR: TRect; +begin + if (Color = clNone) or not RectVisible(DC, ARect) then Exit; + CR := GetBGR(ColorToRGB(Color)); + if Origin = nil then Origin := @ZeroOrigin; + CacheIndex := GetCacheItem(CR, Roughness); + GetClipBox(DC, BoxR); + IntersectRect(ARect, ARect, BoxR); + SaveDC(DC); + with ARect do IntersectClipRect(DC, Left, Top, Right, Bottom); + + CacheDC := CreateCompatibleDC(0); + for Y := ARect.Top to ARect.Bottom - 1 do + begin + TemplateIndex := RandThreadIndex[(65536 + Y - Origin.Y) mod 1024]; + Size := Length(ThreadTemplates[TemplateIndex]); + X := -RandThreadPositions[(65536 + Y - Origin.Y) mod 1024] + Origin.X; + SelectObject(CacheDC, ThreadCache[CacheIndex].Bitmaps[TemplateIndex]); + while X < ARect.Right do + begin + if X + Size >= ARect.Left then BitBlt(DC, X, Y, Size, 1, CacheDC, 0, 0, SRCCOPY); + Inc(X, Size); + end; + end; + DeleteDC(CacheDC); + + RestoreDC(DC, -1); +end; + +var + hMSImg: HModule; + +initialization + @UpdateLayeredWindow := GetProcAddress( + GetModuleHandle('user32.dll'), 'UpdateLayeredWindow'); + hMSImg := LoadLibrary('msimg32.dll'); + if hMSImg <> 0 then + begin + @AlphaBlend := GetProcAddress(hMSImg, 'AlphaBlend'); + @GradientFill := GetProcAddress(hMSImg, 'GradientFill'); + end; + InitializeStock; + InitializeBrushedFill; + ResetBrushedFillCache; +finalization + FinalizeBrushedFill; + FinalizeStock; + if hMSImg <> 0 then FreeLibrary(hMSImg); +end. diff --git a/official/2.1.6+2.1.beta1/TBX/TBXUtils.pas.orig b/official/2.1.6+2.1.beta1/TBX/TBXUtils.pas.orig new file mode 100644 index 0000000..cdc2bd1 --- /dev/null +++ b/official/2.1.6+2.1.beta1/TBX/TBXUtils.pas.orig @@ -0,0 +1,2263 @@ +unit TBXUtils; + +// TBX Package +// Copyright 2001-2004 Alex A. Denisov. All Rights Reserved +// See TBX.chm for license and installation instructions +// +// $Id: TBXUtils.pas 11 2004-04-01 07:22:56Z Alex@ZEISS $ + +interface + +{$I TB2Ver.inc} +{$I TBX.inc} + +uses + Windows, Messages, Classes, SysUtils, Graphics, Controls, Forms, ImgList; + +{$IFDEF TBX_UNICODE} +function GetTextHeightW(DC: HDC): Integer; +function GetTextWidthW(DC: HDC; const S: WideString; StripAccelChar: Boolean): Integer; +procedure DrawRotatedTextW(DC: HDC; AText: WideString; const ARect: TRect; const AFormat: Cardinal); +function EscapeAmpersandsW(const S: WideString): WideString; +function FindAccelCharW(const S: WideString): WideChar; +function StripAccelCharsW(const S: WideString): WideString; +function StripTrailingPunctuationW(const S: WideString): WideString; +{$ENDIF} + +procedure GetRGB(C: TColor; out R, G, B: Integer); +function MixColors(C1, C2: TColor; W1: Integer): TColor; +function SameColors(C1, C2: TColor): Boolean; +function Lighten(C: TColor; Amount: Integer): TColor; +function NearestLighten(C: TColor; Amount: Integer): TColor; +function NearestMixedColor(C1, C2: TColor; W1: Integer): TColor; +function ColorIntensity(C: TColor): Integer; +function IsDarkColor(C: TColor; Threshold: Integer = 100): Boolean; +function Blend(C1, C2: TColor; W1: Integer): TColor; +procedure SetContrast(var Color: TColor; BkgndColor: TColor; Threshold: Integer); +procedure RGBtoHSL(RGB: TColor; out H, S, L : Single); +function HSLtoRGB(H, S, L: Single): TColor; +function GetBGR(C: TColorRef): Cardinal; + +{ A few drawing functions } +{ these functions recognize clNone value of TColor } + +procedure SetPixelEx(DC: HDC; X, Y: Integer; C: TColorRef; Alpha: Longword = $FF); +function CreatePenEx(Color: TColor): HPen; +function CreateBrushEx(Color: TColor): HBrush; +function CreateDitheredBrush(C1, C2: TColor): HBrush; +function FillRectEx(DC: HDC; const Rect: TRect; Color: TColor): Boolean; {$IFDEF COMPATIBLE_GFX}overload;{$ENDIF} +function FrameRectEx(DC: HDC; var Rect: TRect; Color: TColor; Adjust: Boolean): Boolean; {$IFDEF COMPATIBLE_GFX}overload;{$ENDIF} +procedure DrawLineEx(DC: HDC; X1, Y1, X2, Y2: Integer; Color: TColor); {$IFDEF COMPATIBLE_GFX}overload;{$ENDIF} +function PolyLineEx(DC: HDC; const Points: array of TPoint; Color: TColor): Boolean; +procedure PolygonEx(DC: HDC; const Points: array of TPoint; OutlineColor, FillColor: TColor); +procedure DitherRect(DC: HDC; const R: TRect; C1, C2: TColor); {$IFDEF COMPATIBLE_GFX}overload;{$ENDIF} +procedure Frame3D(DC: HDC; var Rect: TRect; TopColor, BottomColor: TColor; Adjust: Boolean); {$IFDEF COMPATIBLE_GFX}overload;{$ENDIF} +procedure DrawDraggingOutline(DC: HDC; const NewRect, OldRect: TRect); + +{ Gradients } +type + TGradientKind = (gkHorz, gkVert); + +procedure GradFill(DC: HDC; ARect: TRect; ClrTopLeft, ClrBottomRight: TColor; Kind: TGradientKind); +procedure BrushedFill(DC: HDC; Origin: PPoint; ARect: TRect; Color: TColor; Roughness: Integer); +procedure ResetBrushedFillCache; + +{ drawing functions for compatibility with previous versions } +{$IFDEF COMPATIBLE_GFX} +function FillRectEx(Canvas: TCanvas; const Rect: TRect; Color: TColor): Boolean; overload; +function FrameRectEx(Canvas: TCanvas; var Rect: TRect; Color: TColor; Adjust: Boolean = False): Boolean; overload; +procedure DrawLineEx(Canvas: TCanvas; X1, Y1, X2, Y2: Integer; Color: TColor); overload; +procedure DitherRect(Canvas: TCanvas; const R: TRect; C1, C2: TColor); overload; +procedure Frame3D(Canvas: TCanvas; var Rect: TRect; TopColor, BottomColor: TColor); overload; +function FillRectEx2(DC: HDC; const Rect: TRect; Color: TColor): Boolean; deprecated; +function FrameRectEx2(DC: HDC; var Rect: TRect; Color: TColor; Adjust: Boolean = False): Boolean; deprecated; +{$ENDIF} + +{ alternatives to fillchar and move routines what work with 32-bit aligned memory blocks } +procedure FillLongword(var X; Count: Integer; Value: Longword); +procedure MoveLongword(const Source; var Dest; Count: Integer); + +{ extended icon painting routines } +procedure DrawTBXIcon(Canvas: TCanvas; const R: TRect; + ImageList: TCustomImageList; ImageIndex: Integer; HiContrast: Boolean); +procedure BlendTBXIcon(Canvas: TCanvas; const R: TRect; + ImageList: TCustomImageList; ImageIndex: Integer; Opacity: Byte); +procedure HighlightTBXIcon(Canvas: TCanvas; const R: TRect; + ImageList: TCustomImageList; ImageIndex: Integer; HighlightColor: TColor; Amount: Byte); +procedure DrawTBXIconShadow(Canvas: TCanvas; const R: TRect; + ImageList: TCustomImageList; ImageIndex: Integer; Density: Integer); +procedure DrawTBXIconFlatShadow(Canvas: TCanvas; const R: TRect; + ImageList: TCustomImageList; ImageIndex: Integer; ShadowColor: TColor); +procedure DrawTBXIconFullShadow(Canvas: TCanvas; const R: TRect; + ImageList: TCustomImageList; ImageIndex: Integer; ShadowColor: TColor); + +procedure DrawGlyph(DC: HDC; X, Y: Integer; ImageList: TCustomImageList; ImageIndex: Integer; Color: TColor); overload; +procedure DrawGlyph(DC: HDC; const R: TRect; ImageList: TCustomImageList; ImageIndex: Integer; Color: TColor); overload; +procedure DrawGlyph(DC: HDC; X, Y: Integer; const Bits; Color: TColor); overload; +procedure DrawGlyph(DC: HDC; const R: TRect; Width, Height: Integer; const Bits; Color: TColor); overload; + +function GetClientSizeEx(Control: TWinControl): TPoint; + +const + SHD_DENSE = 0; + SHD_LIGHT = 1; + +{ An additional declaration for D4 compiler } +type + PColor = ^TColor; + +{ Stock Objects } +var + StockBitmap1, StockBitmap2: TBitmap; + StockMonoBitmap, StockCompatibleBitmap: TBitmap; + SmCaptionFont: TFont; + +const + ROP_DSPDxax = $00E20746; + +{ Support for window shadows } +type + TShadowEdges = set of (seTopLeft, seBottomRight); + TShadowStyle = (ssFlat, ssLayered, ssAlphaBlend); + + TShadow = class(TCustomControl) + protected + FOpacity: Byte; + FBuffer: TBitmap; + FClearRect: TRect; + FEdges: TShadowEdges; + FStyle: TShadowStyle; + FSaveBits: Boolean; + procedure GradR(const R: TRect); + procedure GradB(const R: TRect); + procedure GradBR(const R: TRect); + procedure GradTR(const R: TRect); + procedure GradBL(const R: TRect); + procedure CreateParams(var Params: TCreateParams); override; + procedure FillBuffer; virtual; abstract; + procedure WMNCHitTest(var Message: TMessage); message WM_NCHITTEST; + procedure WMEraseBkgnd(var Message: TWMEraseBkgnd); message WM_ERASEBKGND; + public + constructor Create(const Bounds: TRect; Opacity: Byte; LoColor: Boolean; Edges: TShadowEdges); reintroduce; + procedure Clear(const R: TRect); + procedure Render; + procedure Show(ParentHandle: HWND); + end; + + THorzShadow = class(TShadow) + protected + procedure FillBuffer; override; + end; + + TVertShadow = class(TShadow) + protected + procedure FillBuffer; override; + end; + + TShadows = class + private + FSaveBits: Boolean; + procedure SetSaveBits(Value: Boolean); + protected + V1: TShadow; + H1: TShadow; + V2: TShadow; + H2: TShadow; + V3: TShadow; + H3: TShadow; + public + constructor Create(R1, R2: TRect; Size: Integer; Opacity: Byte; LoColor: Boolean); + destructor Destroy; override; + procedure Show(ParentHandle: HWND); + property SaveBits: Boolean read FSaveBits write SetSaveBits; + end; + +procedure RecreateStock; + +type + PBlendFunction = ^TBlendFunction; + TBlendFunction = packed record + BlendOp: Byte; + BlendFlags: Byte; + SourceConstantAlpha: Byte; + AlphaFormat: Byte; + end; + + TUpdateLayeredWindow = function(hWnd : hWnd; hdcDst : hDC; pptDst : PPoint; + psize : PSize; hdcSrc : hDC; pptSrc : PPoint; crKey : TColorRef; + pblend : PBlendFunction; dwFlags : Integer): Integer; stdcall; + + TAlphaBlend = function(hdcDest: HDC; nXOriginDest, nYOriginDest, + nWidthDest, nHeightDest: Integer; hdcSrc: HDC; + nXOriginSrc, nYOriginSrc, nWidthSrc, nHeightSrc: Integer; + blendFunction: TBlendFunction): BOOL; stdcall; + + TGradientFill = function(Handle: HDC; pVertex: Pointer; dwNumVertex: DWORD; + pMesh: Pointer; dwNumMesh: DWORD; dwMode: DWORD): DWORD; stdcall; + +var + UpdateLayeredWindow: TUpdateLayeredWindow = nil; + AlphaBlend: TAlphaBlend = nil; + GradientFill: TGradientFill = nil; + + +implementation + +{$R-}{$Q-} + +uses TB2Common, Math; + + +{$IFDEF TBX_UNICODE} + +function GetTextHeightW(DC: HDC): Integer; +var + TextMetric: TTextMetricW; +begin + GetTextMetricsW(DC, TextMetric); + Result := TextMetric.tmHeight; +end; + +function GetTextWidthW(DC: HDC; const S: WideString; StripAccelChar: Boolean): Integer; +var + Size: TSize; + S2: WideString; +begin + if StripAccelChar then + begin + S2 := StripAccelCharsW(S); + GetTextExtentPoint32W(DC, PWideChar(S2), Length(S2), Size); + end + else GetTextExtentPoint32W(DC, PWideChar(S), Length(S), Size); + Result := Size.cx; +end; + +procedure DrawRotatedTextW(DC: HDC; AText: WideString; const ARect: TRect; const AFormat: Cardinal); +{ Like DrawText, but draws the text at a 270 degree angle. + The format flag this function respects are + DT_NOPREFIX, DT_HIDEPREFIX, DT_CENTER, DT_END_ELLIPSIS, DT_NOCLIP } +var + RotatedFont, SaveFont: HFONT; + TextMetrics: TTextMetricW; + X, Y, P, I, SU, FU, W: Integer; + SaveAlign: UINT; + Clip: Boolean; + + function GetSize(DC: HDC; const S: WideString): Integer; + var + Size: TSize; + begin + GetTextExtentPoint32W(DC, PWideChar(S), Length(S), Size); + Result := Size.cx; + end; + +begin + if Length(AText) = 0 then Exit; + + RotatedFont := CreateRotatedFont(DC); + SaveFont := SelectObject(DC, RotatedFont); + + GetTextMetricsW(DC, TextMetrics); + X := ARect.Left + ((ARect.Right - ARect.Left) - TextMetrics.tmHeight) div 2; + + Clip := AFormat and DT_NOCLIP = 0; + + { Find the index of the character that should be underlined. Delete '&' + characters from the string. Like DrawText, only the last prefixed character + will be underlined. } + P := 0; + I := 1; + if AFormat and DT_NOPREFIX = 0 then + while I <= Length(AText) do + begin + if AText[I] = '&' then + begin + Delete(AText, I, 1); + if PWideChar(AText)[I - 1] <> '&' then P := I; + end; + Inc(I); + end; + + if AFormat and DT_END_ELLIPSIS <> 0 then + begin + if (Length(AText) > 1) and (GetSize(DC, AText) > ARect.Bottom - ARect.Top) then + begin + W := ARect.Bottom - ARect.Top; + if W > 2 then + begin + Delete(AText, Length(AText), 1); + while (Length(AText) > 1) and (GetSize(DC, AText + '...') > W) do + Delete(AText, Length(AText), 1); + end + else AText := AText[1]; + if P > Length(AText) then P := 0; + AText := AText + '...'; + end; + end; + + if AFormat and DT_CENTER <> 0 then + Y := ARect.Top + ((ARect.Bottom - ARect.Top) - GetSize(DC, AText)) div 2 + else + Y := ARect.Top; + + if Clip then + begin + SaveDC(DC); + with ARect do IntersectClipRect(DC, Left, Top, Right, Bottom); + end; + + SaveAlign := SetTextAlign(DC, TA_BOTTOM); + TextOutW(DC, X, Y, PWideChar(AText), Length(AText)); + SetTextAlign(DC, SaveAlign); + + { Underline } + if (P > 0) and (AFormat and DT_HIDEPREFIX = 0) then + begin + SU := GetTextWidthW(DC, Copy(AText, 1, P - 1), False); + FU := SU + GetTextWidthW(DC, PWideChar(AText)[P - 1], False); + Inc(X, TextMetrics.tmDescent - 2); + DrawLineEx(DC, X, Y + SU, X, Y + FU, GetTextColor(DC)); + end; + + if Clip then RestoreDC(DC, -1); + + SelectObject(DC, SaveFont); + DeleteObject(RotatedFont); +end; + +function EscapeAmpersandsW(const S: WideString): WideString; +var + I: Integer; +begin + Result := S; + I := 1; + while I <= Length(Result) do + begin + if Result[I] = '&' then + begin + Inc(I); + Insert('&', Result, I); + end; + Inc(I); + end; +end; + +function FindAccelCharW(const S: WideString): WideChar; +var + PStart, P: PWideChar; +begin + { locate the last char with '&' prefix } + Result := #0; + if Length(S) > 0 then + begin + PStart := PWideChar(S); + P := PStart; + Inc(P, Length(S) - 2); + while P >= PStart do + begin + if P^ = '&' then + begin + if (P = PStart) or (PWideChar(Integer(P) - 2)^ <> '&') then + begin + Result := PWideChar(Integer(P) + 2)^; + Exit; + end + else Dec(P); + end; + Dec(P); + end; + end; +end; + +function StripAccelCharsW(const S: WideString): WideString; +var + I: Integer; +begin + Result := S; + I := 1; + while I <= Length(Result) do + begin + if Result[I] = '&' then + System.Delete(Result, I, 1); + Inc(I); + end; +end; + +function StripTrailingPunctuationW(const S: WideString): WideString; +var + L: Integer; +begin + Result := S; + L := Length(Result); + if (L > 1) and (Result[L] = ':') then SetLength(Result, L - 1) + else if (L > 3) and (Result[L - 2] = '.') and (Result[L - 1] = '.') and + (Result[L] = '.') then SetLength(Result, L - 3); +end; + +{$ENDIF} + + + +type + PPoints = ^TPoints; + TPoints = array [0..0] of TPoint; + +const + WeightR: single = 0.764706; + WeightG: single = 1.52941; + WeightB: single = 0.254902; + +procedure GetRGB(C: TColor; out R, G, B: Integer); +begin + if Integer(C) < 0 then C := GetSysColor(C and $000000FF); + R := C and $FF; + G := C shr 8 and $FF; + B := C shr 16 and $FF; +end; + +function MixColors(C1, C2: TColor; W1: Integer): TColor; +var + W2: Cardinal; +begin + Assert(W1 in [0..255]); + W2 := W1 xor 255; + if Integer(C1) < 0 then C1 := GetSysColor(C1 and $000000FF); + if Integer(C2) < 0 then C2 := GetSysColor(C2 and $000000FF); + Result := Integer( + ((Cardinal(C1) and $FF00FF) * Cardinal(W1) + + (Cardinal(C2) and $FF00FF) * W2) and $FF00FF00 + + ((Cardinal(C1) and $00FF00) * Cardinal(W1) + + (Cardinal(C2) and $00FF00) * W2) and $00FF0000) shr 8; +end; + +function SameColors(C1, C2: TColor): Boolean; +begin + if C1 < 0 then C1 := GetSysColor(C1 and $000000FF); + if C2 < 0 then C2 := GetSysColor(C2 and $000000FF); + Result := C1 = C2; +end; + +function Lighten(C: TColor; Amount: Integer): TColor; +var + R, G, B: Integer; +begin + if C < 0 then C := GetSysColor(C and $000000FF); + R := C and $FF + Amount; + G := C shr 8 and $FF + Amount; + B := C shr 16 and $FF + Amount; + if R < 0 then R := 0 else if R > 255 then R := 255; + if G < 0 then G := 0 else if G > 255 then G := 255; + if B < 0 then B := 0 else if B > 255 then B := 255; + Result := R or (G shl 8) or (B shl 16); +end; + +function NearestLighten(C: TColor; Amount: Integer): TColor; +begin + Result := GetNearestColor(StockCompatibleBitmap.Canvas.Handle, Lighten(C, Amount)); +end; + +function NearestMixedColor(C1, C2: TColor; W1: Integer): TColor; +begin + Result := MixColors(C1, C2, W1); + Result := GetNearestColor(StockCompatibleBitmap.Canvas.Handle, Result); +end; + +function ColorIntensity(C: TColor): Integer; +begin + if C < 0 then C := GetSysColor(C and $FF); + Result := ((C shr 16 and $FF) * 30 + (C shr 8 and $FF) * 150 + (C and $FF) * 76) shr 8; +end; + +function IsDarkColor(C: TColor; Threshold: Integer = 100): Boolean; +begin + if C < 0 then C := GetSysColor(C and $FF); + Threshold := Threshold shl 8; + Result := ((C and $FF) * 76 + (C shr 8 and $FF) * 150 + (C shr 16 and $FF) * 30 ) < Threshold; +end; + +function Blend(C1, C2: TColor; W1: Integer): TColor; +var + W2, A1, A2, D, F, G: Integer; +begin + if C1 < 0 then C1 := GetSysColor(C1 and $FF); + if C2 < 0 then C2 := GetSysColor(C2 and $FF); + + if W1 >= 100 then D := 1000 + else D := 100; + + W2 := D - W1; + F := D div 2; + + A2 := C2 shr 16 * W2; + A1 := C1 shr 16 * W1; + G := (A1 + A2 + F) div D and $FF; + Result := G shl 16; + + A2 := (C2 shr 8 and $FF) * W2; + A1 := (C1 shr 8 and $FF) * W1; + G := (A1 + A2 + F) div D and $FF; + Result := Result or G shl 8; + + A2 := (C2 and $FF) * W2; + A1 := (C1 and $FF) * W1; + G := (A1 + A2 + F) div D and $FF; + Result := Result or G; +end; + +function ColorDistance(C1, C2: Integer): Single; +var + DR, DG, DB: Integer; +begin + DR := (C1 and $FF) - (C2 and $FF); + Result := Sqr(DR * WeightR); + DG := (C1 shr 8 and $FF) - (C2 shr 8 and $FF); + Result := Result + Sqr(DG * WeightG); + DB := (C1 shr 16) - (C2 shr 16); + Result := Result + Sqr(DB * WeightB); + Result := SqRt(Result); +end; + +function GetAdjustedThreshold(BkgndIntensity, Threshold: Single): Single; +begin + if BkgndIntensity < 220 then Result := (2 - BkgndIntensity / 220) * Threshold + else Result := Threshold; +end; + +function IsContrastEnough(AColor, ABkgndColor: Integer; + DoAdjustThreshold: Boolean; Threshold: Single): Boolean; +begin + if DoAdjustThreshold then + Threshold := GetAdjustedThreshold(ColorDistance(ABkgndColor, $000000), Threshold); + Result := ColorDistance(ABkgndColor, AColor) > Threshold; +end; + +procedure AdjustContrast(var AColor: Integer; ABkgndColor: Integer; Threshold: Single); +var + x, y, z: Single; + r, g, b: Single; + RR, GG, BB: Integer; + i1, i2, s, q, w: Single; + DoInvert: Boolean; +begin + i1 := ColorDistance(AColor, $000000); + i2 := ColorDistance(ABkgndColor, $000000); + Threshold := GetAdjustedThreshold(i2, Threshold); + + if i1 > i2 then DoInvert := i2 < 442 - Threshold + else DoInvert := i2 < Threshold; + + x := (ABkgndColor and $FF) * WeightR; + y := (ABkgndColor shr 8 and $FF) * WeightG; + z := (ABkgndColor shr 16) * WeightB; + + r := (AColor and $FF) * WeightR; + g := (AColor shr 8 and $FF) * WeightG; + b := (AColor shr 16) * WeightB; + + if DoInvert then + begin + r := 195 - r; + g := 390 - g; + b := 65 - b; + x := 195 - x; + y := 390 - y; + z := 65 - z; + end; + + s := Sqrt(Sqr(b) + Sqr(g) + Sqr(r)); + if s < 0.01 then s := 0.01; + + q := (r * x + g * y + b * z) / S; + + x := Q / S * r - x; + y := Q / S * g - y; + z := Q / S * b - z; + + w := Sqrt(Sqr(Threshold) - Sqr(x) - Sqr(y) - Sqr(z)); + + r := (q - w) * r / s; + g := (q - w) * g / s; + b := (q - w) * b / s; + + if DoInvert then + begin + r := 195 - r; + g := 390 - g; + b := 65 - b; + end; + + if r < 0 then r := 0 else if r > 195 then r := 195; + if g < 0 then g := 0 else if g > 390 then g := 390; + if b < 0 then b := 0 else if b > 65 then b := 65; + + RR := Trunc(r * (1 / WeightR) + 0.5); + GG := Trunc(g * (1 / WeightG) + 0.5); + BB := Trunc(b * (1 / WeightB) + 0.5); + + if RR > $FF then RR := $FF else if RR < 0 then RR := 0; + if GG > $FF then GG := $FF else if GG < 0 then GG := 0; + if BB > $FF then BB := $FF else if BB < 0 then BB := 0; + + AColor := (BB and $FF) shl 16 or (GG and $FF) shl 8 or (RR and $FF); +end; + +procedure SetContrast(var Color: TColor; BkgndColor: TColor; Threshold: Integer); +var + t: Single; +begin + if Color < 0 then Color := GetSysColor(Color and $FF); + if BkgndColor < 0 then BkgndColor := GetSysColor(BkgndColor and $FF); + t := Threshold; + if not IsContrastEnough(Color, BkgndColor, True, t) then + AdjustContrast(Integer(Color), BkgndColor, t); +end; + +procedure RGBtoHSL(RGB: TColor; out H, S, L : Single); +var + R, G, B, D, Cmax, Cmin: Single; +begin + if RGB < 0 then RGB := GetSysColor(RGB and $FF); + R := GetRValue(RGB) / 255; + G := GetGValue(RGB) / 255; + B := GetBValue(RGB) / 255; + Cmax := Max(R, Max(G, B)); + Cmin := Min(R, Min(G, B)); + L := (Cmax + Cmin) / 2; + + if Cmax = Cmin then + begin + H := 0; + S := 0 + end + else + begin + D := Cmax - Cmin; + if L < 0.5 then S := D / (Cmax + Cmin) + else S := D / (2 - Cmax - Cmin); + if R = Cmax then H := (G - B) / D + else + if G = Cmax then H := 2 + (B - R) / D + else H := 4 + (R - G) / D; + H := H / 6; + if H < 0 then H := H + 1 + end; +end; + +function HSLtoRGB(H, S, L: Single): TColor; +const + OneOverThree = 1 / 3; +var + M1, M2: Single; + R, G, B: Byte; + + function HueToColor(Hue: Single): Byte; + var + V: Double; + begin + Hue := Hue - Floor(Hue); + if 6 * Hue < 1 then V := M1 + (M2 - M1) * Hue * 6 + else if 2 * Hue < 1 then V := M2 + else if 3 * Hue < 2 then V := M1 + (M2 - M1) * (2 / 3 - Hue) * 6 + else V := M1; + Result := Round(255 * V); + end; + +begin + if S = 0 then + begin + R := Round(255 * L); + G := R; + B := R; + end + else + begin + if L <= 0.5 then M2 := L * (1 + S) + else M2 := L + S - L * S; + M1 := 2 * L - M2; + R := HueToColor(H + OneOverThree); + G := HueToColor(H); + B := HueToColor(H - OneOverThree) + end; + Result := RGB(R, G, B); +end; + +{ Drawing routines } + +function GetBGR(C: TColorRef): Cardinal; +asm + MOV ECX,EAX // this function swaps R and B bytes in ABGR + SHR EAX,16 + XCHG AL,CL + MOV AH,$00 // and writes $FF into A component + SHL EAX,16 + MOV AX,CX +end; + +procedure SetPixelEx(DC: HDC; X, Y: Integer; C: TColorRef; Alpha: Longword = $FF); +var + W2: Cardinal; + B: TColorRef; +begin + if Alpha <= 0 then Exit + else if Alpha >= 255 then SetPixelV(DC, X, Y, C) + else + begin + B := GetPixel(DC, X, Y); + if B <> CLR_INVALID then + begin + Inc(Alpha, Integer(Alpha > 127)); + W2 := 256 - Alpha; + B := + ((C and $FF00FF) * Alpha + (B and $FF00FF) * W2 + $007F007F) and $FF00FF00 + + ((C and $00FF00) * Alpha + (B and $00FF00) * W2 + $00007F00) and $00FF0000; + SetPixelV(DC, X, Y, B shr 8); + end; + end; +end; + +function CreatePenEx(Color: TColor): HPen; +begin + if Color = clNone then Result := CreatePen(PS_NULL, 1, 0) + else if Color < 0 then Result := CreatePen(PS_SOLID, 1, GetSysColor(Color and $000000FF)) + else Result := CreatePen(PS_SOLID, 1, Color); +end; + +function CreateBrushEx(Color: TColor): HBrush; +var + LB: TLogBrush; +begin + if Color = clNone then + begin + LB.lbStyle := BS_HOLLOW; + Result := CreateBrushIndirect(LB); + end + else if Color < 0 then Result := GetSysColorBrush(Color and $000000FF) + else Result := CreateSolidBrush(Color); +end; + +function FillRectEx(DC: HDC; const Rect: TRect; Color: TColor): Boolean; +var + Brush: HBRUSH; +begin + Result := Color <> clNone; + if Result then + begin + if Color < 0 then Brush := GetSysColorBrush(Color and $000000FF) + else Brush := CreateSolidBrush(Color); + Windows.FillRect(DC, Rect, Brush); + DeleteObject(Brush); + end; +end; + +function FrameRectEx(DC: HDC; var Rect: TRect; Color: TColor; Adjust: Boolean): Boolean; +var + Brush: HBRUSH; +begin + Result := Color <> clNone; + if Result then + begin + if Color < 0 then Brush := GetSysColorBrush(Color and $000000FF) + else Brush := CreateSolidBrush(Color); + Windows.FrameRect(DC, Rect, Brush); + DeleteObject(Brush); + end; + if Adjust then with Rect do + begin + Inc(Left); Dec(Right); + Inc(Top); Dec(Bottom); + end; +end; + +procedure DrawLineEx(DC: HDC; X1, Y1, X2, Y2: Integer; Color: TColor); +var + OldPen, Pen: HPen; +begin + Pen := CreatePen(PS_SOLID, 1, ColorToRGB(Color)); + OldPen := SelectObject(DC, Pen); + Windows.MoveToEx(DC, X1, Y1, nil); + Windows.LineTo(DC, X2, Y2); + SelectObject(DC, OldPen); + DeleteObject(Pen); +end; + +function PolyLineEx(DC: HDC; const Points: array of TPoint; Color: TColor): Boolean; overload; +var + Pen, OldPen: HPEN; +begin + Result := Color <> clNone; + if Result then + begin + if Color < 0 then Color := GetSysColor(Color and $FF); + Pen := CreatePen(PS_SOLID, 1, Color); + OldPen := SelectObject(DC, Pen); + Windows.Polyline(DC, PPoints(@Points[0])^, Length(Points)); + SelectObject(DC, OldPen); + DeleteObject(Pen); + end; +end; + +procedure PolygonEx(DC: HDC; const Points: array of TPoint; OutlineColor, FillColor: TColor); +var + OldBrush, Brush: HBrush; + OldPen, Pen: HPen; +begin + if (OutlineColor = clNone) and (FillColor = clNone) then Exit; + Pen := CreatePenEx(OutlineColor); + Brush := CreateBrushEx(FillColor); + OldPen := SelectObject(DC, Pen); + OldBrush := SelectObject(DC, Brush); + Windows.Polygon(DC, PPoints(@Points[0])^, Length(Points)); + SelectObject(DC, OldBrush); + SelectObject(DC, OldPen); + DeleteObject(Brush); + DeleteObject(Pen); +end; + +function CreateDitheredBrush(C1, C2: TColor): HBrush; +var + B: TBitmap; +begin + B := AllocPatternBitmap(C1, C2); + B.HandleType := bmDDB; + Result := CreatePatternBrush(B.Handle); +end; + +procedure DitherRect(DC: HDC; const R: TRect; C1, C2: TColor); +var + Brush: HBRUSH; +begin + Brush := CreateDitheredBrush(C1, C2); + FillRect(DC, R, Brush); + DeleteObject(Brush); +end; + +procedure Frame3D(DC: HDC; var Rect: TRect; TopColor, BottomColor: TColor; Adjust: Boolean); +var + TopRight, BottomLeft: TPoint; +begin + with Rect do + begin + Dec(Bottom); Dec(Right); + TopRight.X := Right; + TopRight.Y := Top; + BottomLeft.X := Left; + BottomLeft.Y := Bottom; + PolyLineEx(DC, [BottomLeft, TopLeft, TopRight], TopColor); + Dec(BottomLeft.X); + PolyLineEx(DC, [TopRight, BottomRight, BottomLeft], BottomColor); + if Adjust then + begin + Inc(Left); + Inc(Top); + end + else + begin + Dec(Right); + Dec(Bottom); + end; + end; +end; + + +{$IFDEF COMPATIBLE_GFX} +procedure DitherRect(Canvas: TCanvas; const R: TRect; C1, C2: TColor); +begin + DitherRect(Canvas.Handle, R, C1, C2); +end; + +procedure Frame3D(Canvas: TCanvas; var Rect: TRect; TopColor, BottomColor: TColor); +var + TopRight, BottomLeft: TPoint; +begin + with Canvas, Rect do + begin + Pen.Width := 1; + Dec(Bottom); Dec(Right); + TopRight.X := Right; + TopRight.Y := Top; + BottomLeft.X := Left; + BottomLeft.Y := Bottom; + Pen.Color := TopColor; + PolyLine([BottomLeft, TopLeft, TopRight]); + Pen.Color := BottomColor; + Dec(BottomLeft.X); + PolyLine([TopRight, BottomRight, BottomLeft]); + Inc(Left); Inc(Top); + end; +end; + +function FillRectEx(Canvas: TCanvas; const Rect: TRect; Color: TColor): Boolean; +begin + Result := FillRectEx(Canvas.Handle, Rect, Color); +end; + +function FillRectEx2(DC: HDC; const Rect: TRect; Color: TColor): Boolean; deprecated; +begin + Result := FillRectEx(DC, Rect, Color); +end; + +function FrameRectEx(Canvas: TCanvas; var Rect: TRect; Color: TColor; Adjust: Boolean = False): Boolean; +begin + Result := FrameRectEx(Canvas.Handle, Rect, Color, Adjust); +end; + +function FrameRectEx2(DC: HDC; var Rect: TRect; Color: TColor; Adjust: Boolean = False): Boolean; deprecated; +begin + Result := FrameRectEx(DC, Rect, Color, Adjust); +end; + +procedure DrawLineEx(Canvas: TCanvas; X1, Y1, X2, Y2: Integer; Color: TColor); +begin + DrawLineEx(Canvas.Handle, X1, Y1, X2, Y2, Color); +end; +{$ENDIF} + +procedure DrawDraggingOutline(DC: HDC; const NewRect, OldRect: TRect); +var + Sz: TSize; +begin + Sz.CX := 3; Sz.CY := 2; + DrawHalftoneInvertRect(DC, @NewRect, @OldRect, Sz, Sz); +end; + +procedure FillLongword(var X; Count: Integer; Value: Longword); +asm +// EAX = X; EDX = Count; ECX = Value + PUSH EDI + MOV EDI,EAX // Point EDI to destination + MOV EAX,ECX + MOV ECX,EDX + TEST ECX,ECX + JS @exit + REP STOSD // Fill count dwords +@exit: + POP EDI +end; + +procedure MoveLongword(const Source; var Dest; Count: Integer); +asm +// EAX = Source; EDX = Dest; ECX = Count + PUSH ESI + PUSH EDI + MOV ESI,EAX // Source + MOV EDI,EDX // Destination + MOV EAX,ECX // Counter + CMP EDI,ESI + JE @exit + REP MOVSD +@exit: + POP EDI + POP ESI +end; + +procedure DrawTBXIcon(Canvas: TCanvas; const R: TRect; + ImageList: TCustomImageList; ImageIndex: Integer; HiContrast: Boolean); +const + CWeirdColor = $00203241; +var + ImageWidth, ImageHeight: Integer; + I, J: Integer; + Src, Dst: PColor; + S, C: TColor; +begin + if not HiContrast then + begin + ImageList.Draw(Canvas, R.Left, R.Top, ImageIndex); + Exit; + end; + + ImageWidth := R.Right - R.Left; + ImageHeight := R.Bottom - R.Top; + with ImageList do + begin + if Width < ImageWidth then ImageWidth := Width; + if Height < ImageHeight then ImageHeight := Height; + end; + + StockBitmap1.Width := ImageWidth; + StockBitmap1.Height := ImageHeight; + StockBitmap2.Width := ImageWidth; + StockBitmap2.Height := ImageHeight; + + BitBlt(StockBitmap1.Canvas.Handle, 0, 0, ImageWidth, ImageHeight, + Canvas.Handle, R.Left, R.Top, SRCCOPY); + for J := 0 to ImageHeight - 1 do + FillLongWord(StockBitmap2.ScanLine[J]^, ImageWidth, CWeirdColor); + ImageList.Draw(StockBitmap2.Canvas, 0, 0, ImageIndex); + + for J := 0 to ImageHeight - 1 do + begin + Src := StockBitmap2.ScanLine[J]; + Dst := StockBitmap1.ScanLine[J]; + for I := 0 to ImageWidth - 1 do + begin + S := Src^ and $00FFFFFF; + if S <> CWeirdColor then + begin + C := (S and $FF0000) shr 16 * 76 + (S and $00FF00) shr 8 * 150 + + (S and $0000FF) * 29; + if C > $FD00 then S := $000000 + else if C < $6400 then S := $FFFFFF; + Dst^ := Lighten(S, 32); + end; + Inc(Src); + Inc(Dst); + end; + end; + BitBlt(Canvas.Handle, R.Left, R.Top, ImageWidth, ImageHeight, + StockBitmap1.Canvas.Handle, 0, 0, SRCCOPY); +end; + +procedure BlendTBXIcon(Canvas: TCanvas; const R: TRect; + ImageList: TCustomImageList; ImageIndex: Integer; Opacity: Byte); +const + CWeirdColor = $00203241; +var + ImageWidth, ImageHeight: Integer; + I, J: Integer; + Src, Dst: ^Cardinal; + S, C, CBRB, CBG: Cardinal; + Wt1, Wt2: Cardinal; +begin + Wt2 := Opacity; + Wt1 := 255 - Wt2; + ImageWidth := R.Right - R.Left; + ImageHeight := R.Bottom - R.Top; + with ImageList do + begin + if Width < ImageWidth then ImageWidth := Width; + if Height < ImageHeight then ImageHeight := Height; + end; + + StockBitmap1.Width := ImageWidth; + StockBitmap1.Height := ImageHeight; + StockBitmap2.Width := ImageWidth; + StockBitmap2.Height := ImageHeight; + + BitBlt(StockBitmap1.Canvas.Handle, 0, 0, ImageWidth, ImageHeight, + Canvas.Handle, R.Left, R.Top, SRCCOPY); + BitBlt(StockBitmap2.Canvas.Handle, 0, 0, ImageWidth, ImageHeight, + StockBitmap1.Canvas.Handle, 0, 0, SRCCOPY); + ImageList.Draw(StockBitmap2.Canvas, 0, 0, ImageIndex, True); + + for J := 0 to ImageHeight - 1 do + begin + Src := StockBitmap2.ScanLine[J]; + Dst := StockBitmap1.ScanLine[J]; + for I := 0 to ImageWidth - 1 do + begin + S := Src^; + if S <> Dst^ then + begin + CBRB := (Dst^ and $00FF00FF) * Wt1; + CBG := (Dst^ and $0000FF00) * Wt1; + C := ((S and $FF00FF) * Wt2 + CBRB) and $FF00FF00 + ((S and $00FF00) * Wt2 + CBG) and $00FF0000; + Dst^ := C shr 8; + end; + Inc(Src); + Inc(Dst); + end; + end; + BitBlt(Canvas.Handle, R.Left, R.Top, ImageWidth, ImageHeight, + StockBitmap1.Canvas.Handle, 0, 0, SRCCOPY); +end; + +procedure HighlightTBXIcon(Canvas: TCanvas; const R: TRect; + ImageList: TCustomImageList; ImageIndex: Integer; HighlightColor: TColor; Amount: Byte); +const + CWeirdColor = $00203241; +var + ImageWidth, ImageHeight: Integer; + I, J: Integer; + Src, Dst: PColor; + S, C: Cardinal; + CBRB, CBG: Cardinal; + W1, W2: Cardinal; +begin + ImageWidth := R.Right - R.Left; + ImageHeight := R.Bottom - R.Top; + with ImageList do + begin + if Width < ImageWidth then ImageWidth := Width; + if Height < ImageHeight then ImageHeight := Height; + end; + + StockBitmap1.Width := ImageWidth; + StockBitmap1.Height := ImageHeight; + StockBitmap2.Width := ImageWidth; + StockBitmap2.Height := ImageHeight; + + BitBlt(StockBitmap1.Canvas.Handle, 0, 0, ImageWidth, ImageHeight, + Canvas.Handle, R.Left, R.Top, SRCCOPY); + for J := 0 to ImageHeight - 1 do + FillLongWord(StockBitmap2.ScanLine[J]^, ImageWidth, CWeirdColor); + ImageList.Draw(StockBitmap2.Canvas, 0, 0, ImageIndex); + + W2 := Amount; + W1 := 255 - W2; + HighlightColor := GetBGR(ColorToRGB(HighlightColor)); + CBRB := (Cardinal(HighlightColor) and $00FF00FF) * W1; + CBG := (Cardinal(HighlightColor) and $0000FF00) * W1; + + for J := 0 to ImageHeight - 1 do + begin + Src := StockBitmap2.ScanLine[J]; + Dst := StockBitmap1.ScanLine[J]; + for I := 0 to ImageWidth - 1 do + begin + S := Src^ and $00FFFFFF; + if S <> CWeirdColor then + begin + C := ((S and $FF00FF) * W2 + CBRB) and $FF00FF00 + ((S and $00FF00) * W2 + CBG) and $00FF0000; + Dst^ := C shr 8; + end; + Inc(Src); + Inc(Dst); + end; + end; + BitBlt(Canvas.Handle, R.Left, R.Top, ImageWidth, ImageHeight, + StockBitmap1.Canvas.Handle, 0, 0, SRCCOPY); +end; + +procedure DrawTBXIconShadow(Canvas: TCanvas; const R: TRect; + ImageList: TCustomImageList; ImageIndex: Integer; Density: Integer); +const + D_DIV: array [0..2] of Cardinal = (3, 8, 20); + D_ADD: array [0..2] of Cardinal = (255 - 255 div 3, 255 - 255 div 8, 255 - 255 div 20); +var + ImageWidth, ImageHeight: Integer; + I, J: Integer; + Src, Dst: ^Cardinal; + S, C, CBRB, CBG: Cardinal; +begin + Assert(Density in [0..2]); + + ImageWidth := R.Right - R.Left; + ImageHeight := R.Bottom - R.Top; + with ImageList do + begin + if Width < ImageWidth then ImageWidth := Width; + if Height < ImageHeight then ImageHeight := Height; + end; + + StockBitmap1.Width := ImageWidth; + StockBitmap1.Height := ImageHeight; + StockBitmap2.Width := ImageWidth; + StockBitmap2.Height := ImageHeight; + + BitBlt(StockBitmap1.Canvas.Handle, 0, 0, ImageWidth, ImageHeight, + Canvas.Handle, R.Left, R.Top, SRCCOPY); + BitBlt(StockBitmap2.Canvas.Handle, 0, 0, ImageWidth, ImageHeight, + StockBitmap1.Canvas.Handle, 0, 0, SRCCOPY); + ImageList.Draw(StockBitmap2.Canvas, 0, 0, ImageIndex, True); + + for J := 0 to ImageHeight - 1 do + begin + Src := StockBitmap2.ScanLine[J]; + Dst := StockBitmap1.ScanLine[J]; + for I := 0 to ImageWidth - 1 do + begin + S := Src^; + if S <> Dst^ then + begin + CBRB := Dst^ and $00FF00FF; + CBG := Dst^ and $0000FF00; + C := ((S and $FF0000) shr 16 * 29 + (S and $00FF00) shr 8 * 150 + + (S and $0000FF) * 76) shr 8; + C := C div D_DIV[Density] + D_ADD[Density]; + Dst^ := ((CBRB * C and $FF00FF00) or (CBG * C and $00FF0000)) shr 8; + end; + Inc(Src); + Inc(Dst); + end; + end; + BitBlt(Canvas.Handle, R.Left, R.Top, ImageWidth, ImageHeight, + StockBitmap1.Canvas.Handle, 0, 0, SRCCOPY); +end; + +procedure DrawTBXIconFlatShadow(Canvas: TCanvas; const R: TRect; + ImageList: TCustomImageList; ImageIndex: Integer; ShadowColor: TColor); +const + CShadowThreshold = 180 * 256; +var + ImageWidth, ImageHeight: Integer; + I, J: Integer; + P: ^Cardinal; + C: Cardinal; + SrcDC, DstDC: HDC; +begin + ImageWidth := R.Right - R.Left; + ImageHeight := R.Bottom - R.Top; + with ImageList do + begin + if Width < ImageWidth then ImageWidth := Width; + if Height < ImageHeight then ImageHeight := Height; + end; + + StockBitmap2.Width := ImageWidth; + StockBitmap2.Height := ImageHeight; + StockBitmap2.Canvas.Brush.Color := clWhite; + StockBitmap2.Canvas.FillRect(Rect(0, 0, ImageWidth, ImageHeight)); + ImageList.Draw(StockBitmap2.Canvas, 0, 0, ImageIndex, True); + + for J := 0 to ImageHeight - 1 do + begin + P := StockBitmap2.ScanLine[J]; + for I := 0 to ImageWidth - 1 do + begin + C := P^ and $00FFFFFF; + if C <> $0 then + begin + C := (C and $FF0000) shr 16 * 76 + (C and $00FF00) shr 8 * 150 + (C and $0000FF) * 29; + if C > CShadowThreshold then P^ := $00FFFFFF + else P^ := $00000000; + end; + Inc(P); + end; + end; + + StockMonoBitmap.Width := ImageWidth; + StockMonoBitmap.Height := ImageHeight; + StockMonoBitmap.Canvas.Brush.Color := clBlack; + BitBlt(StockMonoBitmap.Canvas.Handle, 0, 0, ImageWidth, ImageHeight, + StockBitmap2.Canvas.Handle, 0, 0, SRCCOPY); + + SrcDC := StockMonoBitmap.Canvas.Handle; + Canvas.Brush.Color := ColorToRGB(ShadowColor); + DstDC := Canvas.Handle; + Windows.SetTextColor(DstDC, clWhite); + Windows.SetBkColor(DstDC, clBlack); + BitBlt(DstDC, R.Left, R.Top, ImageWidth, ImageHeight, SrcDC, 0, 0, ROP_DSPDxax); +end; + +procedure DrawTBXIconFullShadow(Canvas: TCanvas; const R: TRect; + ImageList: TCustomImageList; ImageIndex: Integer; ShadowColor: TColor); +const + CWeirdColor = $00203241; +var + ImageWidth, ImageHeight: Integer; + I, J: Integer; + P: ^Cardinal; + C: Cardinal; + SrcDC, DstDC: HDC; +begin + ImageWidth := R.Right - R.Left; + ImageHeight := R.Bottom - R.Top; + with ImageList do + begin + if Width < ImageWidth then ImageWidth := Width; + if Height < ImageHeight then ImageHeight := Height; + end; + + StockBitmap2.Width := ImageWidth; + StockBitmap2.Height := ImageHeight; + for J := 0 to ImageHeight - 1 do + FillLongWord(StockBitmap2.ScanLine[J]^, ImageWidth, CWeirdColor); + ImageList.Draw(StockBitmap2.Canvas, 0, 0, ImageIndex, True); + + for J := 0 to ImageHeight - 1 do + begin + P := StockBitmap2.ScanLine[J]; + for I := 0 to ImageWidth - 1 do + begin + C := P^ and $00FFFFFF; + if C <> CWeirdColor then P^ := $00000000 + else P^ := $00FFFFFF; + Inc(P); + end; + end; + + StockMonoBitmap.Width := ImageWidth; + StockMonoBitmap.Height := ImageHeight; + StockMonoBitmap.Canvas.Brush.Color := clBlack; + BitBlt(StockMonoBitmap.Canvas.Handle, 0, 0, ImageWidth, ImageHeight, + StockBitmap2.Canvas.Handle, 0, 0, SRCCOPY); + + SrcDC := StockMonoBitmap.Canvas.Handle; + Canvas.Brush.Color := ColorToRGB(ShadowColor); + DstDC := Canvas.Handle; + Windows.SetTextColor(DstDC, clWhite); + Windows.SetBkColor(DstDC, clBlack); + BitBlt(DstDC, R.Left, R.Top, ImageWidth, ImageHeight, SrcDC, 0, 0, ROP_DSPDxax); +end; + +procedure DrawGlyph(DC: HDC; X, Y: Integer; ImageList: TCustomImageList; ImageIndex: Integer; Color: TColor); +var + B: TBitmap; + OldTextColor, OldBkColor: Longword; + OldBrush, Brush: HBrush; +begin + if Color = clNone then Exit; + B := TBitmap.Create; + B.Monochrome := True; + ImageList.GetBitmap(ImageIndex, B); + OldTextColor := SetTextColor(DC, clBlack); + OldBkColor := SetBkColor(DC, clWhite); + if Color < 0 then Brush := GetSysColorBrush(Color and $FF) + else Brush := CreateSolidBrush(Color); + OldBrush := SelectObject(DC, Brush); + BitBlt(DC, X, Y, ImageList.Width, ImageList.Height, B.Canvas.Handle, 0, 0, ROP_DSPDxax); + SelectObject(DC, OldBrush); + if Color >= 0 then DeleteObject(Brush); + SetTextColor(DC, OldTextColor); + SetBkColor(DC, OldBkColor); + B.Free; +end; + +procedure DrawGlyph(DC: HDC; const R: TRect; ImageList: TCustomImageList; ImageIndex: Integer; Color: TColor); overload; +begin + DrawGlyph(DC, (R.Left + R.Right + 1 - ImageList.Width) div 2, (R.Top + R.Bottom + 1 - ImageList.Height) div 2, ImageList, ImageIndex, Color); +end; + +procedure DrawGlyph(DC: HDC; X, Y: Integer; const Bits; Color: TColor); overload; +var + B: TBitmap; + OldTextColor, OldBkColor: Longword; + OldBrush, Brush: HBrush; +begin + B := TBitmap.Create; + B.Handle := CreateBitmap(8, 8, 1, 1, @Bits); + OldTextColor := SetTextColor(DC, clBlack); + OldBkColor := SetBkColor(DC, clWhite); + if Color < 0 then Brush := GetSysColorBrush(Color and $FF) + else Brush := CreateSolidBrush(Color); + OldBrush := SelectObject(DC, Brush); + BitBlt(DC, X, Y, 8, 8, B.Canvas.Handle, 0, 0, ROP_DSPDxax); + SelectObject(DC, OldBrush); + if Color >= 0 then DeleteObject(Brush); + SetTextColor(DC, OldTextColor); + SetBkColor(DC, OldBkColor); + B.Free; +end; + +procedure DrawGlyph(DC: HDC; const R: TRect; Width, Height: Integer; const Bits; Color: TColor); overload; +var + B: TBitmap; + OldTextColor, OldBkColor: Longword; + OldBrush, Brush: HBrush; +begin + B := TBitmap.Create; + B.Handle := CreateBitmap(8, 8, 1, 1, @Bits); + OldTextColor := SetTextColor(DC, clBlack); + OldBkColor := SetBkColor(DC, clWhite); + if Color < 0 then Brush := GetSysColorBrush(Color and $FF) + else Brush := CreateSolidBrush(Color); + OldBrush := SelectObject(DC, Brush); + BitBlt(DC, (R.Left + R.Right + 1 - Width) div 2, (R.Top + R.Bottom + 1 - Height) div 2, Width, Height, B.Canvas.Handle, 0, 0, ROP_DSPDxax); + SelectObject(DC, OldBrush); + if Color >= 0 then DeleteObject(Brush); + SetTextColor(DC, OldTextColor); + SetBkColor(DC, OldBkColor); + B.Free; +end; + +type + TCustomFormAccess = class(TCustomForm); + +function GetClientSizeEx(Control: TWinControl): TPoint; +var + R: TRect; +begin + if (Control is TCustomForm) and (TCustomFormAccess(Control).FormStyle = fsMDIForm) + and not (csDesigning in Control.ComponentState) then + GetWindowRect(TCustomFormAccess(Control).ClientHandle, R) + else + R := Control.ClientRect; + Result.X := R.Right - R.Left; + Result.Y := R.Bottom - R.Top; +end; + +procedure InitializeStock; +var + NonClientMetrics: TNonClientMetrics; +begin + StockBitmap1 := TBitmap.Create; + StockBitmap1.PixelFormat := pf32bit; + StockBitmap2 := TBitmap.Create; + StockBitmap2.PixelFormat := pf32bit; + StockMonoBitmap := TBitmap.Create; + StockMonoBitmap.Monochrome := True; + StockCompatibleBitmap := TBitmap.Create; + StockCompatibleBitmap.Width := 8; + StockCompatibleBitmap.Height := 8; + SmCaptionFont := TFont.Create; + NonClientMetrics.cbSize := SizeOf(NonClientMetrics); + if SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, @NonClientMetrics, 0) then + SmCaptionFont.Handle := CreateFontIndirect(NonClientMetrics.lfSmCaptionFont); +end; + +procedure FinalizeStock; +begin + SmCaptionFont.Free; + SmCaptionFont := nil; + StockCompatibleBitmap.Free; + StockMonoBitmap.Free; + StockBitmap2.Free; + StockBitmap1.Free; +end; + +procedure RecreateStock; +begin + FinalizeStock; + InitializeStock; +end; + +{ TShadow } //////////////////////////////////////////////////////////////////// + +procedure TShadow.Clear(const R: TRect); +begin + FClearRect := R; +end; + +constructor TShadow.Create(const Bounds: TRect; Opacity: Byte; LoColor: Boolean; Edges: TShadowEdges); +begin + inherited Create(nil); + Hide; + ParentWindow := Application.Handle; + BoundsRect := Bounds; + Color := clBtnShadow; + FOpacity := Opacity; + FEdges := Edges; + FSaveBits := False; + + if LoColor then FStyle := ssFlat + else if (@UpdateLayeredWindow <> nil) and (@AlphaBlend <> nil) then + FStyle := ssLayered + else if @AlphaBlend <> nil then + FStyle := ssAlphaBlend + else + FStyle := ssFlat; +end; + +procedure TShadow.CreateParams(var Params: TCreateParams); +begin + inherited; + with Params do + begin + Style := (Style and not (WS_CHILD or WS_GROUP or WS_TABSTOP)) or WS_POPUP; + ExStyle := ExStyle or WS_EX_TOOLWINDOW; + if FSaveBits then WindowClass.Style := WindowClass.Style or CS_SAVEBITS; + end; +end; + +procedure TShadow.GradB(const R: TRect); +var + J, W, H: Integer; + V: Cardinal; + P: ^Cardinal; +begin + W := R.Right - R.Left; + H := R.Bottom - R.Top; + for J := 0 to H - 1 do + begin + P := FBuffer.ScanLine[J + R.Top]; + Inc(P, R.Left); + V := (255 - J shl 8 div H) shl 24; + FillLongword(P^, W, V); + end; +end; + +procedure TShadow.GradBL(const R: TRect); +var + I, J, W, H, CX, CY, D, DMax, A, B: Integer; + P: ^Cardinal; +begin + W := R.Right - R.Left; + H := R.Bottom - R.Top; + DMax := W; + if H > W then DMax := H; + CX := DMax - 1; + CY := H - DMax; + for J := 0 to H - 1 do + begin + P := FBuffer.ScanLine[J + R.Top]; + Inc(P, R.Left); + for I := 0 to W - 1 do + begin + A := Abs(I - CX); + B := Abs(J - CY); + D := A; + if B > A then D := B; + D := (A + B + D) * 128 div DMax; + if D < 255 then P^ := (255 - D) shl 24 + else P^ := 0; + Inc(P); + end; + end; +end; + +procedure TShadow.GradBR(const R: TRect); +var + I, J, W, H, CX, CY, D, DMax, A, B: Integer; + P: ^Cardinal; +begin + W := R.Right - R.Left; + H := R.Bottom - R.Top; + DMax := W; + if H > W then DMax := H; + CX := W - DMax; + CY := H - DMax; + for J := 0 to H - 1 do + begin + P := FBuffer.ScanLine[J + R.Top]; + Inc(P, R.Left); + for I := 0 to W - 1 do + begin + A := Abs(I - CX); + B := Abs(J - CY); + D := A; + if B > A then D := B; + D := (A + B + D) * 128 div DMax; + if D < 255 then P^ := (255 - D) shl 24 + else P^ := 0; + Inc(P); + end; + end; +end; + +procedure TShadow.GradR(const R: TRect); +var + I, J, W: Integer; + P: ^Cardinal; + ScanLine: array of Cardinal; +begin + W := R.Right - R.Left; + SetLength(ScanLine, W); + for I := 0 to W - 1 do + ScanLine[I] :=(255 - I shl 8 div W) shl 24; + + for J := R.Top to R.Bottom - 1 do + begin + P := FBuffer.ScanLine[J]; + Inc(P, R.Left); + MoveLongword(ScanLine[0], P^, W); + end; +end; + +procedure TShadow.GradTR(const R: TRect); +var + I, J, W, H, CX, CY, D, DMax, A, B: Integer; + P: ^Cardinal; +begin + W := R.Right - R.Left; + H := R.Bottom - R.Top; + DMax := W; + if H > W then DMax := H; + CX := W - DMax; + CY := DMax - 1; + for J := 0 to H - 1 do + begin + P := FBuffer.ScanLine[J + R.Top]; + Inc(P, R.Left); + for I := 0 to W - 1 do + begin + A := Abs(I - CX); + B := Abs(J - CY); + D := A; + if B > A then D := B; + D := (A + B + D) * 128 div DMax; + if D < 255 then P^ := (255 - D) shl 24 + else P^ := 0; + Inc(P); + end; + end; +end; + +procedure TShadow.Render; +var + DstDC: HDC; + SrcPos, DstPos: TPoint; + Size: TSize; + BlendFunc: TBlendFunction; +begin + if FStyle <> ssLayered then Exit; + Assert(Assigned(UpdateLayeredWindow)); + + SetWindowLong(Handle, GWL_EXSTYLE, GetWindowLong(Handle, GWL_EXSTYLE) or $00080000{WS_EX_LAYERED}); + DstDC := GetDC(0); + try + SrcPos := Point(0, 0); + with BoundsRect do + begin + DstPos := Point(Left, Top); + Size.cx := Right - Left; + Size.cy := Bottom - Top; + end; + BlendFunc.BlendOp := 0; + BlendFunc.BlendFlags := 0; + BlendFunc.SourceConstantAlpha := FOpacity; + BlendFunc.AlphaFormat := 1; + + FBuffer := TBitmap.Create; + FBuffer.PixelFormat := pf32bit; + FBuffer.Width := Size.cx; + FBuffer.Height := Size.cy; + + FillBuffer; + + UpdateLayeredWindow( + Handle, + DstDC, + @DstPos, + @Size, + FBuffer.Canvas.Handle, + @SrcPos, + 0, + @BlendFunc, + $00000002{ULW_ALPHA}); + + FBuffer.Free; + finally + ReleaseDC(0, DstDC); + end; +end; + +procedure TShadow.Show(ParentHandle: HWND); +begin + SetWindowPos(Handle, ParentHandle, 0, 0, 0, 0, + SWP_NOACTIVATE or SWP_NOSENDCHANGING or SWP_NOMOVE or + SWP_NOOWNERZORDER or SWP_NOSIZE or SWP_SHOWWINDOW); +end; + +procedure TShadow.WMEraseBkgnd(var Message: TWMEraseBkgnd); +var + SrcPos, DstPos: TPoint; + Size: TSize; + BlendFunc: TBlendFunction; +begin + if FStyle = ssAlphaBlend then + begin + Assert(Assigned(AlphaBlend)); + + { Dispatch all the painting messages } + ProcessPaintMessages; + + SrcPos := Point(0, 0); + with BoundsRect do + begin + DstPos := Point(Left, Top); + Size.cx := Right - Left; + Size.cy := Bottom - Top; + end; + + FBuffer := TBitmap.Create; + FBuffer.PixelFormat := pf32bit; + FBuffer.Width := Size.cx; + FBuffer.Height := Size.cy; + + FillBuffer; + + { Blend the buffer directly into the screen } + BlendFunc.BlendOp := 0; + BlendFunc.BlendFlags := 0; + BlendFunc.SourceConstantAlpha := FOpacity; + BlendFunc.AlphaFormat := 1; + AlphaBlend(Message.DC, 0, 0, Size.cx, Size.cy, + FBuffer.Canvas.Handle, 0, 0, Size.cx, Size.cy, BlendFunc); + FBuffer.Free; + + Message.Result := 1; + end + else inherited; +end; + +procedure TShadow.WMNCHitTest(var Message: TMessage); +begin + Message.Result := HTTRANSPARENT; +end; + +{ THorzShadow } + +procedure THorzShadow.FillBuffer; +var + R: TRect; + L1, L2, L3: Integer; +begin + if seTopLeft in FEdges then L1 := Height else L1 := 0; + if seBottomRight in FEdges then L3 := Height else L3 := 0; + if L1 + L3 > Width then + begin + if (L1 > 0) and (L3 > 0) then + begin + L1 := Width div 2; + L3 := L1; + end + else if L1 > 0 then L1 := Width + else if L3 > 0 then L3 := Width; + end; + L2 := Width - L1 - L3; + R := Rect(0, 0, Width, Height); + R.Right := R.Left + L1; + if L1 > 0 then GradBL(R); + R.Left := R.Right; + R.Right := R.Left + L2; + if L2 > 0 then GradB(R); + if L3 > 0 then + begin + R.Left := R.Right; + R.Right := R.Left + L3; + GradBR(R); + end; +end; + +{ TVertShadow } + +procedure TVertShadow.FillBuffer; +var + R: TRect; + L1, L2, L3: Integer; +begin + if seTopLeft in FEdges then L1 := Width else L1 := 0; + if seBottomRight in FEdges then L3 := Width else L3 := 0; + if L1 + L3 > Height then + begin + if (L1 > 0) and (L3 > 0) then + begin + L1 := Height div 2; + L3 := L1; + end + else if L1 > 0 then L1 := Height + else if L3 > 0 then L3 := Height; + end; + L2 := Height - L1 - L3; + + R := Rect(0, 0, Width, Height); + R.Bottom := R.Top + L1; + if L1 > 0 then GradTR(R); + R.Top := R.Bottom; + R.Bottom := R.Top + L2; + if L2 > 0 then GradR(R); + if L3 > 0 then + begin + R.Top := R.Bottom; + R.Bottom := R.Top + L3; + GradBR(R); + end; +end; + +{ TShadows } + +constructor TShadows.Create(R1, R2: TRect; Size: Integer; Opacity: Byte; LoColor: Boolean); +var + R: TRect; + R1Valid, R2Valid: Boolean; +begin + if LoColor or + ((@UpdateLayeredWindow = nil) and (@AlphaBlend = nil)) then + begin + Size := Size div 2; + end; + + R1Valid := not IsRectEmpty(R1); + R2Valid := not IsRectEmpty(R2); + if not (R1Valid or R2Valid) then Exit; + + if R1Valid xor R2Valid then + begin + { A simple square shadow } + if R1Valid then R := R1 else R:= R2; + with R do + begin + V1 := TVertShadow.Create(Rect(Right, Top + Size, Right + Size, Bottom), Opacity, LoColor, [seTopLeft]); + H1 := THorzShadow.Create(Rect(Left + Size, Bottom, Right + Size, Bottom + Size), Opacity, LoColor, [seTopLeft, seBottomRight]) + end; + end + else + begin + + if (R1.Bottom <= R2.Top + 2) or (R1.Top >= R2.Bottom - 2) then + begin + if R1.Top > R2.Top then + begin + R := R2; + R2 := R1; + R1 := R; + end; + if R1.Left + Size < R2.Left then + H1 := THorzShadow.Create(Rect(R1.Left + Size, R1.Bottom, R2.Left, R1.Bottom + Size), Opacity, LoColor, [seTopLeft]); + H2 := THorzShadow.Create(Rect(R2.Left + Size, R2.Bottom, R2.Right + Size, R2.Bottom + Size), Opacity, LoColor, [seTopLeft, seBottomRight]); + V1 := TVertShadow.Create(Rect(R1.Right, R1.Top + Size, R1.Right + Size, R1.Bottom), Opacity, LoColor, [seTopLeft]); + if R1.Right > R2.Right then + H3 := THorzShadow.Create(Rect(R2.Right, R1.Bottom, R1.Right + Size, R1.Bottom + Size), Opacity, LoColor, [seTopLeft, seBottomRight]); + if R1.Right + Size < R2.Right then + V2 := TVertShadow.Create(Rect(R2.Right, R2.Top + Size, R2.Right + Size, R2.Bottom), Opacity, LoColor, [seTopLeft]) + else + V2 := TVertShadow.Create(Rect(R2.Right, R2.Top + 1, R2.Right + Size, R2.Bottom), Opacity, LoColor, []); + end + else if (R1.Right <= R2.Left + 2) or (R1.Left >= R2.Right - 2) then + begin + if R1.Left > R2.Left then + begin + R := R2; + R2 := R1; + R1 := R; + end; + if R1.Top + Size < R2.Top then + V1 := TVertShadow.Create(Rect(R1.Right, R1.Top + Size, R1.Right + Size, R2.Top), Opacity, LoColor, [seTopLeft]); + V2 := TVertShadow.Create(Rect(R2.Right, R2.Top + Size, R2.Right + Size, R2.Bottom + Size), Opacity, LoColor, [seTopLeft, seBottomRight]); + H1 := THorzShadow.Create(Rect(R1.Left + Size, R1.Bottom, R1.Right, R1.Bottom + Size), Opacity, LoColor, [seTopLeft]); + if R1.Bottom > R2.Bottom then + V3 := TVertShadow.Create(Rect(R1.Right, R2.Bottom, R1.Right + Size, R1.Bottom + Size), Opacity, LoColor, [seTopLeft, seBottomRight]); + if R1.Bottom + Size < R2.Bottom then + H2 := THorzShadow.Create(Rect(R2.Left + Size, R2.Bottom, R2.Right, R2.Bottom + Size), Opacity, LoColor, [seTopLeft]) + else + H2 := THorzShadow.Create(Rect(R2.Left, R2.Bottom, R2.Right, R2.Bottom + Size), Opacity, LoColor, []); + end; + end; + + if V1 <> nil then V1.Render; + if H1 <> nil then H1.Render; + if V2 <> nil then V2.Render; + if H2 <> nil then H2.Render; + if V3 <> nil then V3.Render; + if H3 <> nil then H3.Render; + + SetSaveBits(True); +end; + +destructor TShadows.Destroy; +begin + H3.Free; + V3.Free; + H2.Free; + V2.Free; + H1.Free; + V1.Free; + inherited; +end; + +procedure TShadows.SetSaveBits(Value: Boolean); +begin + FSaveBits := Value; + if V1 <> nil then V1.FSaveBits := Value; + if H1 <> nil then H1.FSaveBits := Value; + if V2 <> nil then V2.FSaveBits := Value; + if H2 <> nil then H2.FSaveBits := Value; + if V3 <> nil then V3.FSaveBits := Value; + if H3 <> nil then H3.FSaveBits := Value; +end; + +procedure TShadows.Show(ParentHandle: HWND); +begin + if V1 <> nil then V1.Show(ParentHandle); + if H1 <> nil then H1.Show(ParentHandle); + if V2 <> nil then V2.Show(ParentHandle); + if H2 <> nil then H2.Show(ParentHandle); + if V3 <> nil then V3.Show(ParentHandle); + if H3 <> nil then H3.Show(ParentHandle); +end; + +{ Gradients } ////////////////////////////////////////////////////////////////// + +const + GRADIENT_CACHE_SIZE = 16; + +type + PRGBQuad = ^TRGBQuad; + TRGBQuad = Integer; + PRGBQuadArray = ^TRGBQuadArray; + TRGBQuadArray = array [0..0] of TRGBQuad; + + +var + GradientCache: array [0..GRADIENT_CACHE_SIZE] of array of TRGBQuad; + NextCacheIndex: Integer = 0; + +function FindGradient(Size: Integer; CL, CR: TRGBQuad): Integer; +begin + Assert(Size > 0); + Result := GRADIENT_CACHE_SIZE - 1; + while Result >= 0 do + begin + if (Length(GradientCache[Result]) = Size) and + (GradientCache[Result][0] = CL) and + (GradientCache[Result][Length(GradientCache[Result]) - 1] = CR) then Exit; + Dec(Result); + end; +end; + +function MakeGradient(Size: Integer; CL, CR: TRGBQuad): Integer; +var + R1, G1, B1: Integer; + R2, G2, B2: Integer; + R, G, B: Integer; + I: Integer; + Bias: Integer; +begin + Assert(Size > 0); + Result := NextCacheIndex; + Inc(NextCacheIndex); + if NextCacheIndex >= GRADIENT_CACHE_SIZE then NextCacheIndex := 0; + R1 := CL and $FF; + G1 := CL shr 8 and $FF; + B1 := CL shr 16 and $FF; + R2 := CR and $FF - R1; + G2 := CR shr 8 and $FF - G1; + B2 := CR shr 16 and $FF - B1; + SetLength(GradientCache[Result], Size); + Dec(Size); + Bias := Size div 2; + if Size > 0 then + for I := 0 to Size do + begin + R := R1 + (R2 * I + Bias) div Size; + G := G1 + (G2 * I + Bias) div Size; + B := B1 + (B2 * I + Bias) div Size; + GradientCache[Result][I] := R + G shl 8 + B shl 16; + end + else + begin + R := R1 + R2 div 2; + G := G1 + G2 div 2; + B := B1 + B2 div 2; + GradientCache[Result][0] := R + G shl 8 + B shl 16; + end; +end; + +function GetGradient(Size: Integer; CL, CR: TRGBQuad): Integer; +begin + Result := FindGradient(Size, CL, CR); + if Result < 0 then Result := MakeGradient(Size, CL, CR); +end; + +{ GradFill function } + +procedure GradFill(DC: HDC; ARect: TRect; ClrTopLeft, ClrBottomRight: TColor; Kind: TGradientKind); +const + GRAD_MODE: array [TGradientKind] of DWORD = (GRADIENT_FILL_RECT_H, GRADIENT_FILL_RECT_V); + W: array [TGradientKind] of Integer = (2, 1); + H: array [TGradientKind] of Integer = (1, 2); +type + TriVertex = packed record + X, Y: Longint; + R, G, B, A: Word; + end; +var + V: array [0..1] of TriVertex; + GR: GRADIENT_RECT; + Size, I, Start, Finish: Integer; + GradIndex: Integer; + R, CR: TRect; + Brush: HBRUSH; +begin + if not RectVisible(DC, ARect) then Exit; + + ClrTopLeft := ColorToRGB(ClrTopLeft); + ClrBottomRight := ColorToRGB(ClrBottomRight); + if @GradientFill <> nil then + begin + { Use msimg32.dll } + with V[0] do + begin + X := ARect.Left; + Y := ARect.Top; + R := ClrTopLeft shl 8 and $FF00; + G := ClrTopLeft and $FF00; + B := ClrTopLeft shr 8 and $FF00; + A := 0; + end; + with V[1] do + begin + X := ARect.Right; + Y := ARect.Bottom; + R := ClrBottomRight shl 8 and $FF00; + G := ClrBottomRight and $FF00; + B := ClrBottomRight shr 8 and $FF00; + A := 0; + end; + GR.UpperLeft := 0; GR.LowerRight := 1; + GradientFill(DC, @V, 2, @GR, 1, GRAD_MODE[Kind]); + end + else + begin + { Have to do it manually if msimg32.dll is not available } + GetClipBox(DC, CR); + + if Kind = gkHorz then + begin + Size := ARect.Right - ARect.Left; + if Size <= 0 then Exit; + Start := 0; Finish := Size - 1; + if CR.Left > ARect.Left then Inc(Start, CR.Left - ARect.Left); + if CR.Right < ARect.Right then Dec(Finish, ARect.Right - CR.Right); + R := ARect; Inc(R.Left, Start); R.Right := R.Left + 1; + end + else + begin + Size := ARect.Bottom - ARect.Top; + if Size <= 0 then Exit; + Start := 0; Finish := Size - 1; + if CR.Top > ARect.Top then Inc(Start, CR.Top - ARect.Top); + if CR.Bottom < ARect.Bottom then Dec(Finish, ARect.Bottom - CR.Bottom); + R := ARect; Inc(R.Top, Start); R.Bottom := R.Top + 1; + end; + GradIndex := GetGradient(Size, ClrTopLeft, ClrBottomRight); + for I := Start to Finish do + begin + Brush := CreateSolidBrush(GradientCache[GradIndex][I]); + Windows.FillRect(DC, R, Brush); + OffsetRect(R, Integer(Kind = gkHorz), Integer(Kind = gkVert)); + DeleteObject(Brush); + end; + end; +end; + +{ Brushed Fill } /////////////////////////////////////////////////////////////// + +{ Templates } + +const + NUM_TEMPLATES = 8; + MIN_TEMPLATE_SIZE = 100; + MAX_TEMPLATE_SIZE = 200; + +var + ThreadTemplates: array [0..NUM_TEMPLATES - 1] of array of Integer; + RandThreadIndex: array [0..1023] of Integer; + RandThreadPositions: array [0..1023] of Integer; + +procedure InitializeBrushedFill; +const + Pi = 3.14159265358987; +var + TemplateIndex, Size, I, V, V1, V2: Integer; + T, R12, R13, R14, R21, R22, R23, R24: Single; +begin + { Make thread templates } + for TemplateIndex := 0 to NUM_TEMPLATES - 1 do + begin + Size := (MIN_TEMPLATE_SIZE + Random(MAX_TEMPLATE_SIZE - MIN_TEMPLATE_SIZE + 1)) div 2; + SetLength(ThreadTemplates[TemplateIndex], Size * 2); + R12 := Random * 2 * Pi; + R13 := Random * 2 * Pi; + R14 := Random * 2 * Pi; + R21 := Random * 2 * Pi; + R22 := Random * 2 * Pi; + R23 := Random * 2 * Pi; + R24 := Random * 2 * Pi; + for I := 0 to Size - 1 do + begin + T := 2 * Pi * I / Size; + V1 := Round(150 * Sin(T) + 100 * Sin(2 * T + R12) + 50 * Sin(3 * T + R13) + 20 * Sin(4 * T + R14)); + if V1 > 255 then V1 := 255; + if V1 < -255 then V1 := -255; + + V2 := Round(150 * Sin(T + R21) + 100 * Sin(2 * T + R22) + 50 * Sin(3 * T + R23) + 20 * Sin(4 * T + R24)); + if V2 > 255 then V2 := 255; + if V2 < -255 then V2 := -255; + + if Abs(V2 - V1) > 300 then + begin + V := (V1 + V2) div 2; + V1 := V - 150; + V2 := V + 150; + end; + + ThreadTemplates[TemplateIndex][I * 2] := Min(V1, V2); + ThreadTemplates[TemplateIndex][I * 2 + 1] := Max(V1, V2); + end; + end; + + { Initialize Rand arrays } + for I := 0 to 1023 do + begin + RandThreadIndex[I] := Random(NUM_TEMPLATES); + V1 := Random(Length(ThreadTemplates[RandThreadIndex[I]])) and not $1; + if Odd(I) then Inc(V1); + RandThreadPositions[I] := V1; + end; +end; + +{ Cache } + +const + THREAD_CACHE_SIZE = 16; + +type + TThreadCacheItem = record + BaseColor: TColorRef; + Roughness: Integer; + Bitmaps: array [0..NUM_TEMPLATES - 1] of HBITMAP; + end; + +var + ThreadCache: array [0..THREAD_CACHE_SIZE] of TThreadCacheItem; + NextCacheEntry: Integer = 0; + +procedure ClearCacheItem(var CacheItem: TThreadCacheItem); +var + I: Integer; +begin + for I := NUM_TEMPLATES - 1 downto 0 do + begin + CacheItem.BaseColor := $FFFFFFFF; + CacheItem.Roughness := -1; + if CacheItem.Bitmaps[I] <> 0 then DeleteObject(CacheItem.Bitmaps[I]); + CacheItem.Bitmaps[I] := 0; + end; +end; + +procedure ResetBrushedFillCache; +var + I: Integer; +begin + { Should be called each time the screen parameters change } + for I := THREAD_CACHE_SIZE - 1 downto 0 do ClearCacheItem(ThreadCache[I]); +end; + +procedure FinalizeBrushedFill; +begin + ResetBrushedFillCache; +end; + +procedure MakeCacheItem(var CacheItem: TThreadCacheItem; Color: TColorRef; Roughness: Integer); +var + TemplateIndex, Size, I, V: Integer; + CR, CG, CB: Integer; + R, G, B: Integer; + ScreenDC: HDC; + BMI: TBitmapInfo; + Bits: PRGBQuadArray; + DIBSection: HBITMAP; + DIBDC, CacheDC: HDC; +begin + ScreenDC := GetDC(0); + FillChar(BMI, SizeOf(TBitmapInfo), 0); + with BMI.bmiHeader do + begin + biSize := SizeOf(TBitmapInfoHeader); + biPlanes := 1; + biCompression := BI_RGB; + biWidth := MAX_TEMPLATE_SIZE; + biHeight := -1; + biBitCount := 32; + end; + DIBSection := CreateDIBSection(0, BMI, DIB_RGB_COLORS, Pointer(Bits), 0, 0); + DIBDC := CreateCompatibleDC(0); + SelectObject(DIBDC, DIBSection); + CacheDC := CreateCompatibleDC(0); + + CR := Color shl 8 and $FF00; + CG := Color and $FF00; + CB := Color shr 8 and $FF00; + + try + for TemplateIndex := 0 to NUM_TEMPLATES - 1 do + begin + CacheItem.BaseColor := Color; + CacheItem.Roughness := Roughness; + Size := Length(ThreadTemplates[TemplateIndex]); + + if CacheItem.Bitmaps[TemplateIndex] = 0 then + CacheItem.Bitmaps[TemplateIndex] := CreateCompatibleBitmap(ScreenDC, Size, 1); + SelectObject(CacheDC, CacheItem.Bitmaps[TemplateIndex]); + + for I := 0 to Size - 1 do + begin + V := ThreadTemplates[TemplateIndex][I]; + R := CR + V * Roughness; + G := CG + V * Roughness; + B := CB + V * Roughness; + if R < 0 then R := 0; + if G < 0 then G := 0; + if B < 0 then B := 0; + if R > $EF00 then R := $EF00; + if G > $EF00 then G := $EF00; + if B > $EF00 then B := $EF00; + Bits^[I] := (R and $FF00 + (G and $FF00) shl 8 + (B and $FF00) shl 16) shr 8; + end; + + BitBlt(CacheDC, 0, 0, Size, 1, DIBDC, 0, 0, SRCCOPY); + end; + + finally + DeleteDC(CacheDC); + DeleteDC(DIBDC); + DeleteObject(DIBSection); + ReleaseDC(0, ScreenDC); + end; +end; + +function FindCacheItem(Color: TColorRef; Roughness: Integer): Integer; +begin + Result := THREAD_CACHE_SIZE - 1; + while Result >= 0 do + if (ThreadCache[Result].BaseColor = Color) and (ThreadCache[Result].Roughness = Roughness) then Exit + else Dec(Result); +end; + +function GetCacheItem(Color: TColorRef; Roughness: Integer): Integer; +begin + Result := FindCacheItem(Color, Roughness); + if Result >= 0 then Exit + else + begin + Result := NextCacheEntry; + MakeCacheItem(ThreadCache[Result], Color, Roughness); + NextCacheEntry := (NextCacheEntry + 1) mod THREAD_CACHE_SIZE; + end; +end; + +procedure BrushedFill(DC: HDC; Origin: PPoint; ARect: TRect; Color: TColor; Roughness: Integer); +const + ZeroOrigin: TPoint = (X: 0; Y: 0); +var + CR: TColorRef; + X, Y: Integer; + CacheIndex: Integer; + TemplateIndex: Integer; + CacheDC: HDC; + Size: Integer; + BoxR: TRect; +begin + if (Color = clNone) or not RectVisible(DC, ARect) then Exit; + CR := GetBGR(ColorToRGB(Color)); + if Origin = nil then Origin := @ZeroOrigin; + CacheIndex := GetCacheItem(CR, Roughness); + GetClipBox(DC, BoxR); + IntersectRect(ARect, ARect, BoxR); + SaveDC(DC); + with ARect do IntersectClipRect(DC, Left, Top, Right, Bottom); + + CacheDC := CreateCompatibleDC(0); + for Y := ARect.Top to ARect.Bottom - 1 do + begin + TemplateIndex := RandThreadIndex[(65536 + Y - Origin.Y) mod 1024]; + Size := Length(ThreadTemplates[TemplateIndex]); + X := -RandThreadPositions[(65536 + Y - Origin.Y) mod 1024] + Origin.X; + SelectObject(CacheDC, ThreadCache[CacheIndex].Bitmaps[TemplateIndex]); + while X < ARect.Right do + begin + if X + Size >= ARect.Left then BitBlt(DC, X, Y, Size, 1, CacheDC, 0, 0, SRCCOPY); + Inc(X, Size); + end; + end; + DeleteDC(CacheDC); + + RestoreDC(DC, -1); +end; + +var + hUser, hMSImg: HModule; + +initialization + +hUser := LoadLibrary('user32.dll'); +hMSImg := LoadLibrary('msimg32.dll'); +@UpdateLayeredWindow := GetProcAddress(hUser, 'UpdateLayeredWindow'); +@AlphaBlend := GetProcAddress(hMSImg, 'AlphaBlend'); +@GradientFill := GetProcAddress(hMSImg, 'GradientFill'); + +InitializeStock; +InitializeBrushedFill; +ResetBrushedFillCache; + +finalization + +FinalizeBrushedFill; +FinalizeStock; + +FreeLibrary(hMSImg); +FreeLibrary(hUser); + +end. diff --git a/official/2.1.6+2.1.beta1/TBX/TBXUxThemes.pas b/official/2.1.6+2.1.beta1/TBX/TBXUxThemes.pas new file mode 100644 index 0000000..97b38e6 --- /dev/null +++ b/official/2.1.6+2.1.beta1/TBX/TBXUxThemes.pas @@ -0,0 +1,2091 @@ +unit TBXUxThemes; + +// TBX Package +// Copyright 2001-2004 Alex A. Denisov. All Rights Reserved +// See TBX.chm for license and installation instructions +// +// Conversion of original visual styles API tmschema.h and +// uxtheme.h (Copyright Microsoft Corporation 1991-2000) +// +// $Id: TBXUxThemes.pas 7 2004-02-21 06:07:53Z $ + +interface + +{$I ..\..\Source\TB2Ver.inc} +{$I TBX.inc} + +uses + Windows; + +function InitXPThemes: Boolean; +procedure FreeXPThemes; +function CanUseXPThemes: Boolean; + +{$DEFINE TMSCHEMA_H} + +const + THEMEMGR_VERSION = 1; + WM_THEMECHANGED = $031A; + +{ Enumerators } + +const + { BGTYPE } + BT_IMAGEFILE = 0; + BT_BORDERFILL = 1; + BT_NONE = 2; + + { IMAGELAYOUT } + IL_VERTICAL = 0; + IL_HORIZONTAL = 1; + + { BORDERTYPE } + BT_RECT = 0; + BT_ROUNDRECT = 1; + BT_ELLIPSE = 2; + + { FILLTYPE } + FT_SOLID = 0; + FT_VERTGRADIENT = 1; + FT_HORZGRADIENT = 2; + FT_RADIALGRADIENT = 3; + FT_TILEIMAGE = 4; + + { SIZINGTYPE } + ST_TRUESIZE = 0; + ST_STRETCH = 1; + ST_TILE = 2; + + { HALIGN } + HA_LEFT = 0; + HA_CENTER = 1; + HA_RIGHT = 2; + + { CONTENTALIGNMENT } + CA_LEFT = 0; + CA_CENTER = 1; + CA_RIGHT = 2; + + { VALIGN } + VA_TOP = 0; + VA_CENTER = 1; + VA_BOTTOM = 2; + + { OFFSETTYPE } + OT_TOPLEFT = 0; + OT_TOPRIGHT = 1; + OT_TOPMIDDLE = 2; + OT_BOTTOMLEFT = 3; + OT_BOTTOMRIGHT = 4; + OT_BOTTOMMIDDLE = 5; + OT_MIDDLELEFT = 6; + OT_MIDDLERIGHT = 7; + OT_LEFTOFCAPTION = 8; + OT_RIGHTOFCAPTION = 9; + OT_LEFTOFLASTBUTTON = 10; + OT_RIGHTOFLASTBUTTON = 11; + OT_ABOVELASTBUTTON = 12; + OT_BELOWLASTBUTTON = 13; + + { ICONEFFECT } + ICE_NONE = 0; + ICE_GLOW = 1; + ICE_SHADOW = 2; + ICE_PULSE = 3; + ICE_ALPHA = 4; + + { TEXTSHADOWTYPE } + TST_NONE = 0; + TST_SINGLE = 1; + TST_CONTINUOUS = 2; + + { GLYPHTYPE } + GT_NONE = 0; + GT_IMAGEGLYPH = 1; + GT_FONTGLYPH = 2; + + { IMAGESELECTTYPE } + IST_NONE = 0; + IST_SIZE = 1; + IST_DPI = 2; + + { TRUESIZESCALINGTYPE } + TSST_NONE = 0; + TSST_SIZE = 1; + TSST_DPI = 2; + + { GLYPHFONTSIZINGTYPE } + GFST_NONE = 0; + GFST_SIZE = 1; + GFST_DPI = 2; + + + +{ PROPERTIES - used by uxtheme rendering and controls } + +const + { primitive types } + TMT_STRING = 201; + TMT_INT = 202; + TMT_BOOL = 203; + TMT_COLOR = 204; + TMT_MARGINS = 205; + TMT_FILENAME = 206; + TMT_SIZE = 207; + TMT_POSITION = 208; + TMT_RECT = 209; + TMT_FONT = 210; + TMT_INTLIST = 211; + + { special misc. properties } + TMT_COLORSCHEMES = 401; + TMT_SIZES = 402; + TMT_CHARSET = 403; + + { [documentation] properties } + TMT_DISPLAYNAME = 601; + TMT_TOOLTIP = 602; + TMT_COMPANY = 603; + TMT_AUTHOR = 604; + TMT_COPYRIGHT = 605; + TMT_URL = 606; + TMT_VERSION = 607; + TMT_DESCRIPTION = 608; + + { theme metrics: fonts } + TMT_CAPTIONFONT = 801; + TMT_SMALLCAPTIONFONT = 802; + TMT_MENUFONT = 803; + TMT_STATUSFONT = 804; + TMT_MSGBOXFONT = 805; + TMT_ICONTITLEFONT = 806; + + { theme metrics: bools } + TMT_FLATMENUS = 1001; + + { theme metrics: sizes } + TMT_SIZINGBORDERWIDTH = 1201; + TMT_SCROLLBARWIDTH = 1202; + TMT_SCROLLBARHEIGHT = 1203; + TMT_CAPTIONBARWIDTH = 1204; + TMT_CAPTIONBARHEIGHT = 1205; + TMT_SMCAPTIONBARWIDTH = 1206; + TMT_SMCAPTIONBARHEIGHT = 1207; + TMT_MENUBARWIDTH = 1208; + TMT_MENUBARHEIGHT = 1209; + + { theme metrics: ints } + TMT_MINCOLORDEPTH = 1301; + + + { theme metrics: strings } + TMT_CSSNAME = 1401; + TMT_XMLNAME = 1402; + + { theme metrics: colors } + TMT_SCROLLBAR = 1601; + TMT_BACKGROUND = 1602; + TMT_ACTIVECAPTION = 1603; + TMT_INACTIVECAPTION = 1604; + TMT_MENU = 1605; + TMT_WINDOW = 1606; + TMT_WINDOWFRAME = 1607; + TMT_MENUTEXT = 1608; + TMT_WINDOWTEXT = 1609; + TMT_CAPTIONTEXT = 1610; + TMT_ACTIVEBORDER = 1611; + TMT_INACTIVEBORDER = 1612; + TMT_APPWORKSPACE = 1613; + TMT_HIGHLIGHT = 1614; + TMT_HIGHLIGHTTEXT = 1615; + TMT_BTNFACE = 1616; + TMT_BTNSHADOW = 1617; + TMT_GRAYTEXT = 1618; + TMT_BTNTEXT = 1619; + TMT_INACTIVECAPTIONTEXT = 1620; + TMT_BTNHIGHLIGHT = 1621; + TMT_DKSHADOW3D = 1622; + TMT_LIGHT3D = 1623; + TMT_INFOTEXT = 1624; + TMT_INFOBK = 1625; + TMT_BUTTONALTERNATEFACE = 1626; + TMT_HOTTRACKING = 1627; + TMT_GRADIENTACTIVECAPTION = 1628; + TMT_GRADIENTINACTIVECAPTION = 1629; + TMT_MENUHILIGHT = 1630; + TMT_MENUBAR = 1631; + + { hue substitutions } + TMT_FROMHUE1 = 1801; + TMT_FROMHUE2 = 1802; + TMT_FROMHUE3 = 1803; + TMT_FROMHUE4 = 1804; + TMT_FROMHUE5 = 1805; + TMT_TOHUE1 = 1806; + TMT_TOHUE2 = 1807; + TMT_TOHUE3 = 1808; + TMT_TOHUE4 = 1809; + TMT_TOHUE5 = 1810; + + { color substitutions } + TMT_FROMCOLOR1 = 2001; + TMT_FROMCOLOR2 = 2002; + TMT_FROMCOLOR3 = 2003; + TMT_FROMCOLOR4 = 2004; + TMT_FROMCOLOR5 = 2005; + TMT_TOCOLOR1 = 2006; + TMT_TOCOLOR2 = 2007; + TMT_TOCOLOR3 = 2008; + TMT_TOCOLOR4 = 2009; + TMT_TOCOLOR5 = 2010; + + { rendering BOOL properties } + TMT_TRANSPARENT = 2201; + TMT_AUTOSIZE = 2202; + TMT_BORDERONLY = 2203; + TMT_COMPOSITED = 2204; + TMT_BGFILL = 2205; + TMT_GLYPHTRANSPARENT = 2206; + TMT_GLYPHONLY = 2207; + TMT_ALWAYSSHOWSIZINGBAR = 2208; + TMT_MIRRORIMAGE = 2209; + TMT_UNIFORMSIZING = 2210; + TMT_INTEGRALSIZING = 2211; + TMT_SOURCEGROW = 2212; + TMT_SOURCESHRINK = 2213; + + { rendering INT properties } + TMT_IMAGECOUNT = 2401; + TMT_ALPHALEVEL = 2402; + TMT_BORDERSIZE = 2403; + TMT_ROUNDCORNERWIDTH = 2404; + TMT_ROUNDCORNERHEIGHT = 2405; + TMT_GRADIENTRATIO1 = 2406; + TMT_GRADIENTRATIO2 = 2407; + TMT_GRADIENTRATIO3 = 2408; + TMT_GRADIENTRATIO4 = 2409; + TMT_GRADIENTRATIO5 = 2410; + TMT_PROGRESSCHUNKSIZE = 2411; + TMT_PROGRESSSPACESIZE = 2412; + TMT_SATURATION = 2413; + TMT_TEXTBORDERSIZE = 2414; + TMT_ALPHATHRESHOLD = 2415; + TMT_WIDTH = 2416; + TMT_HEIGHT = 2417; + TMT_GLYPHINDEX = 2418; + TMT_TRUESIZESTRETCHMARK = 2419; + TMT_MINDPI1 = 2420; + TMT_MINDPI2 = 2421; + TMT_MINDPI3 = 2422; + TMT_MINDPI4 = 2423; + TMT_MINDPI5 = 2424; + + { rendering FONT properties } + TMT_GLYPHFONT = 2601; + + { rendering INTLIST properties } + TMT_FILESIZES = 2801; + + { rendering FILENAME properties } + TMT_IMAGEFILE = 3001; + TMT_IMAGEFILE1 = 3002; + TMT_IMAGEFILE2 = 3003; + TMT_IMAGEFILE3 = 3004; + TMT_IMAGEFILE4 = 3005; + TMT_IMAGEFILE5 = 3006; + TMT_STOCKIMAGEFILE = 3007; + TMT_GLYPHIMAGEFILE = 3008; + + { rendering STRING properties } + TMT_TEXT = 3201; + + { rendering POSITION (x and y values) properties } + TMT_OFFSET = 3401; + TMT_TEXTSHADOWOFFSET = 3402; + TMT_MINSIZE = 3403; + TMT_MINSIZE1 = 3404; + TMT_MINSIZE2 = 3405; + TMT_MINSIZE3 = 3406; + TMT_MINSIZE4 = 3407; + TMT_MINSIZE5 = 3408; + TMT_NORMALSIZE = 3409; + + { rendering MARGIN properties } + TMT_SIZINGMARGINS = 3601; + TMT_CONTENTMARGINS = 3602; + TMT_CAPTIONMARGINS = 3603; + + { rendering COLOR properties } + TMT_BORDERCOLOR = 3801; + TMT_FILLCOLOR = 3802; + TMT_TEXTCOLOR = 3803; + TMT_EDGELIGHTCOLOR = 3804; + TMT_EDGEHIGHLIGHTCOLOR = 3805; + TMT_EDGESHADOWCOLOR = 3806; + TMT_EDGEDKSHADOWCOLOR = 3807; + TMT_EDGEFILLCOLOR = 3808; + TMT_TRANSPARENTCOLOR = 3809; + TMT_GRADIENTCOLOR1 = 3810; + TMT_GRADIENTCOLOR2 = 3811; + TMT_GRADIENTCOLOR3 = 3812; + TMT_GRADIENTCOLOR4 = 3813; + TMT_GRADIENTCOLOR5 = 3814; + TMT_SHADOWCOLOR = 3815; + TMT_GLOWCOLOR = 3816; + TMT_TEXTBORDERCOLOR = 3817; + TMT_TEXTSHADOWCOLOR = 3818; + TMT_GLYPHTEXTCOLOR = 3819; + TMT_GLYPHTRANSPARENTCOLOR = 3820; + TMT_FILLCOLORHINT = 3821; + TMT_BORDERCOLORHINT = 3822; + TMT_ACCENTCOLORHINT = 3823; + + { rendering enum properties } + TMT_BGTYPE = 4001; + TMT_BORDERTYPE = 4002; + TMT_FILLTYPE = 4003; + TMT_SIZINGTYPE = 4004; + TMT_HALIGN = 4005; + TMT_CONTENTALIGNMENT = 4006; + TMT_VALIGN = 4007; + TMT_OFFSETTYPE = 4008; + TMT_ICONEFFECT = 4009; + TMT_TEXTSHADOWTYPE = 4010; + TMT_IMAGELAYOUT = 4011; + TMT_GLYPHTYPE = 4012; + TMT_IMAGESELECTTYPE = 4013; + TMT_GLYPHFONTSIZINGTYPE = 4014; + TMT_TRUESIZESCALINGTYPE = 4015; + + { custom properties (used only by controls/shell) } + TMT_USERPICTURE = 5001; + TMT_DEFAULTPANESIZE = 5002; + TMT_BLENDCOLOR = 5003; + + +{ "Window" (i.e., non-client) Parts & States } + + { WINDOWPARTS } + WP_CAPTION = 1; + WP_SMALLCAPTION = 2; + WP_MINCAPTION = 3; + WP_SMALLMINCAPTION = 4; + WP_MAXCAPTION = 5; + WP_SMALLMAXCAPTION = 6; + WP_FRAMELEFT = 7; + WP_FRAMERIGHT = 8; + WP_FRAMEBOTTOM = 9; + WP_SMALLFRAMELEFT = 10; + WP_SMALLFRAMERIGHT = 11; + WP_SMALLFRAMEBOTTOM = 12; + WP_SYSBUTTON = 13; + WP_MDISYSBUTTON = 14; + WP_MINBUTTON = 15; + WP_MDIMINBUTTON = 16; + WP_MAXBUTTON = 17; + WP_CLOSEBUTTON = 18; + WP_SMALLCLOSEBUTTON = 19; + WP_MDICLOSEBUTTON = 20; + WP_RESTOREBUTTON = 21; + WP_MDIRESTOREBUTTON = 22; + WP_HELPBUTTON = 23; + WP_MDIHELPBUTTON = 24; + WP_HORZSCROLL = 25; + WP_HORZTHUMB = 26; + WP_VERTSCROLL = 27; + WP_VERTTHUMB = 28; + WP_DIALOG = 29; + WP_CAPTIONSIZINGTEMPLATE = 30; + WP_SMALLCAPTIONSIZINGTEMPLATE = 31; + WP_FRAMELEFTSIZINGTEMPLATE = 32; + WP_SMALLFRAMELEFTSIZINGTEMPLATE = 33; + WP_FRAMERIGHTSIZINGTEMPLATE = 34; + WP_SMALLFRAMERIGHTSIZINGTEMPLATE = 35; + WP_FRAMEBOTTOMSIZINGTEMPLATE = 36; + WP_SMALLFRAMEBOTTOMSIZINGTEMPLATE = 37; + + { FRAMESTATES } + FS_ACTIVE = 1; + FS_INACTIVE = 2; + + { CAPTIONSTATES } + CS_ACTIVE = 1; + CS_INACTIVE = 2; + CS_DISABLED = 3; + + { MAXCAPTIONSTATES } + MXCS_ACTIVE = 1; + MXCS_INACTIVE = 2; + MXCS_DISABLED = 3; + + { MINCAPTIONSTATES } + MNCS_ACTIVE = 1; + MNCS_INACTIVE = 2; + MNCS_DISABLED = 3; + + { HORZSCROLLSTATES } + HSS_NORMAL = 1; + HSS_HOT = 2; + HSS_PUSHED = 3; + HSS_DISABLED = 4; + + { HORZTHUMBSTATES } + HTS_NORMAL = 1; + HTS_HOT = 2; + HTS_PUSHED = 3; + HTS_DISABLED = 4; + + { VERTSCROLLSTATES } + VSS_NORMAL = 1; + VSS_HOT = 2; + VSS_PUSHED = 3; + VSS_DISABLED = 4; + + { VERTTHUMBSTATES } + VTS_NORMAL = 1; + VTS_HOT = 2; + VTS_PUSHED = 3; + VTS_DISABLED = 4; + + { SYSBUTTONSTATES } + SBS_NORMAL = 1; + SBS_HOT = 2; + SBS_PUSHED = 3; + SBS_DISABLED = 4; + + { MINBUTTONSTATES } + MINBS_NORMAL = 1; + MINBS_HOT = 2; + MINBS_PUSHED = 3; + MINBS_DISABLED = 4; + + { MAXBUTTONSTATES } + MAXBS_NORMAL = 1; + MAXBS_HOT = 2; + MAXBS_PUSHED = 3; + MAXBS_DISABLED = 4; + + { RESTOREBUTTONSTATES } + RBS_NORMAL = 1; + RBS_HOT = 2; + RBS_PUSHED = 3; + RBS_DISABLED = 4; + + { HELPBUTTONSTATES } + HBS_NORMAL = 1; + HBS_HOT = 2; + HBS_PUSHED = 3; + HBS_DISABLED = 4; + + { CLOSEBUTTONSTATES } + CBS_NORMAL = 1; + CBS_HOT = 2; + CBS_PUSHED = 3; + CBS_DISABLED = 4; + + +{ "Button" Parts & States } + + + { BUTTONPARTS } + BP_PUSHBUTTON = 1; + BP_RADIOBUTTON = 2; + BP_CHECKBOX = 3; + BP_GROUPBOX = 4; + BP_USERBUTTON = 5; + + { PUSHBUTTONSTATES } + PBS_NORMAL = 1; + PBS_HOT = 2; + PBS_PRESSED = 3; + PBS_DISABLED = 4; + PBS_DEFAULTED = 5; + + { RADIOBUTTONSTATES } + RBS_UNCHECKEDNORMAL = 1; + RBS_UNCHECKEDHOT = 2; + RBS_UNCHECKEDPRESSED = 3; + RBS_UNCHECKEDDISABLED = 4; + RBS_CHECKEDNORMAL = 5; + RBS_CHECKEDHOT = 6; + RBS_CHECKEDPRESSED = 7; + RBS_CHECKEDDISABLED = 8; + + { CHECKBOXSTATES } + CBS_UNCHECKEDNORMAL = 1; + CBS_UNCHECKEDHOT = 2; + CBS_UNCHECKEDPRESSED = 3; + CBS_UNCHECKEDDISABLED = 4; + CBS_CHECKEDNORMAL = 5; + CBS_CHECKEDHOT = 6; + CBS_CHECKEDPRESSED = 7; + CBS_CHECKEDDISABLED = 8; + CBS_MIXEDNORMAL = 9; + CBS_MIXEDHOT = 10; + CBS_MIXEDPRESSED = 11; + CBS_MIXEDDISABLED = 12; + + { GROUPBOXSTATES } + GBS_NORMAL = 1; + GBS_DISABLED = 2; + + +{ "Rebar" Parts & States } + + { REBARPARTS } + RP_GRIPPER = 1; + RP_GRIPPERVERT = 2; + RP_BAND = 3; + RP_CHEVRON = 4; + RP_CHEVRONVERT = 5; + + { CHEVRONSTATES } + CHEVS_NORMAL = 1; + CHEVS_HOT = 2; + CHEVS_PRESSED = 3; + + +{ "Toolbar" Parts & States } + + { TOOLBARPARTS } + TP_BUTTON = 1; + TP_DROPDOWNBUTTON = 2; + TP_SPLITBUTTON = 3; + TP_SPLITBUTTONDROPDOWN = 4; + TP_SEPARATOR = 5; + TP_SEPARATORVERT = 6; + + { TOOLBARSTATES } + TS_NORMAL = 1; + TS_HOT = 2; + TS_PRESSED = 3; + TS_DISABLED = 4; + TS_CHECKED = 5; + TS_HOTCHECKED = 6; + + +{ "Status" Parts & States } + + { STATUSPARTS } + SP_PANE = 1; + SP_GRIPPERPANE = 2; + SP_GRIPPER = 3; + + +{ "Menu" Parts & States } + + { MENUPARTS } + MP_MENUITEM = 1; + MP_MENUDROPDOWN = 2; + MP_MENUBARITEM = 3; + MP_MENUBARDROPDOWN = 4; + MP_CHEVRON = 5; + MP_SEPARATOR = 6; + + { MENUSTATES } + MS_NORMAL = 1; + MS_SELECTED = 2; + MS_DEMOTED = 3; + + +{ "ListView" Parts & States } + + { LISTVIEWPARTS } + LVP_LISTITEM = 1; + LVP_LISTGROUP = 2; + LVP_LISTDETAIL = 3; + LVP_LISTSORTEDDETAIL = 4; + LVP_EMPTYTEXT = 5; + + { LISTITEMSTATES } + LIS_NORMAL = 1; + LIS_HOT = 2; + LIS_SELECTED = 3; + LIS_DISABLED = 4; + LIS_SELECTEDNOTFOCUS = 5; + + +{ "Header" Parts & States } + + { HEADERPARTS } + HP_HEADERITEM = 1; + HP_HEADERITEMLEFT = 2; + HP_HEADERITEMRIGHT = 3; + HP_HEADERSORTARROW = 4; + + { HEADERITEMSTATES } + HIS_NORMAL = 1; + HIS_HOT = 2; + HIS_PRESSED = 3; + + { HEADERITEMLEFTSTATES } + HILS_NORMAL = 1; + HILS_HOT = 2; + HILS_PRESSED = 3; + + { HEADERITEMRIGHTSTATES } + HIRS_NORMAL = 1; + HIRS_HOT = 2; + HIRS_PRESSED = 3; + + { HEADERSORTARROWSTATES } + HSAS_SORTEDUP = 1; + HSAS_SORTEDDOWN = 2; + + +{ "Progress" Parts & States } + + { PROGRESSPARTS } + PP_BAR = 1; + PP_BARVERT = 2; + PP_CHUNK = 3; + PP_CHUNKVERT = 4; + + +{ "Tab" Parts & States } + + { TABPARTS } + TABP_TABITEM = 1; + TABP_TABITEMLEFTEDGE = 2; + TABP_TABITEMRIGHTEDGE = 3; + TABP_TABITEMBOTHEDGE = 4; + TABP_TOPTABITEM = 5; + TABP_TOPTABITEMLEFTEDGE = 6; + TABP_TOPTABITEMRIGHTEDGE = 7; + TABP_TOPTABITEMBOTHEDGE = 8; + TABP_PANE = 9; + TABP_BODY = 10; + + { TABITEMSTATES } + TIS_NORMAL = 1; + TIS_HOT = 2; + TIS_SELECTED = 3; + TIS_DISABLED = 4; + TIS_FOCUSED = 5; + + { TABITEMLEFTEDGESTATES } + TILES_NORMAL = 1; + TILES_HOT = 2; + TILES_SELECTED = 3; + TILES_DISABLED = 4; + TILES_FOCUSED = 5; + + { TABITEMRIGHTEDGESTATES } + TIRES_NORMAL = 1; + TIRES_HOT = 2; + TIRES_SELECTED = 3; + TIRES_DISABLED = 4; + TIRES_FOCUSED = 5; + + { TABITEMBOTHEDGESSTATES } + TIBES_NORMAL = 1; + TIBES_HOT = 2; + TIBES_SELECTED = 3; + TIBES_DISABLED = 4; + TIBES_FOCUSED = 5; + + { TOPTABITEMSTATES } + TTIS_NORMAL = 1; + TTIS_HOT = 2; + TTIS_SELECTED = 3; + TTIS_DISABLED = 4; + TTIS_FOCUSED = 5; + + { TOPTABITEMLEFTEDGESTATES } + TTILES_NORMAL = 1; + TTILES_HOT = 2; + TTILES_SELECTED = 3; + TTILES_DISABLED = 4; + TTILES_FOCUSED = 5; + + { TOPTABITEMRIGHTEDGESTATES } + TTIRES_NORMAL = 1; + TTIRES_HOT = 2; + TTIRES_SELECTED = 3; + TTIRES_DISABLED = 4; + TTIRES_FOCUSED = 5; + + { TOPTABITEMBOTHEDGESSTATES } + TTIBES_NORMAL = 1; + TTIBES_HOT = 2; + TTIBES_SELECTED = 3; + TTIBES_DISABLED = 4; + TTIBES_FOCUSED = 5; + + +{"Trackbar" Parts & States } + + { TRACKBARPARTS } + TKP_TRACK = 1; + TKP_TRACKVERT = 2; + TKP_THUMB = 3; + TKP_THUMBBOTTOM = 4; + TKP_THUMBTOP = 5; + TKP_THUMBVERT = 6; + TKP_THUMBLEFT = 7; + TKP_THUMBRIGHT = 8; + TKP_TICS = 9; + TKP_TICSVERT = 10; + + { TRACKBARSTATES } + TKS_NORMAL = 1; + + { TRACKSTATES } + TRS_NORMAL = 1; + + { TRACKVERTSTATES } + TRVS_NORMAL = 1; + + { THUMBSTATES } + TUS_NORMAL = 1; + TUS_HOT = 2; + TUS_PRESSED = 3; + TUS_FOCUSED = 4; + TUS_DISABLED = 5; + + { THUMBBOTTOMSTATES } + TUBS_NORMAL = 1; + TUBS_HOT = 2; + TUBS_PRESSED = 3; + TUBS_FOCUSED = 4; + TUBS_DISABLED = 5; + + { THUMBTOPSTATES } + TUTS_NORMAL = 1; + TUTS_HOT = 2; + TUTS_PRESSED = 3; + TUTS_FOCUSED = 4; + TUTS_DISABLED = 5; + + { THUMBVERTSTATES } + TUVS_NORMAL = 1; + TUVS_HOT = 2; + TUVS_PRESSED = 3; + TUVS_FOCUSED = 4; + TUVS_DISABLED = 5; + + { THUMBLEFTSTATES } + TUVLS_NORMAL = 1; + TUVLS_HOT = 2; + TUVLS_PRESSED = 3; + TUVLS_FOCUSED = 4; + TUVLS_DISABLED = 5; + + { THUMBRIGHTSTATES } + TUVRS_NORMAL = 1; + TUVRS_HOT = 2; + TUVRS_PRESSED = 3; + TUVRS_FOCUSED = 4; + TUVRS_DISABLED = 5; + + { TICSSTATES } + TSS_NORMAL = 1; + + { TICSVERTSTATES } + TSVS_NORMAL = 1; + + +{ "Tooltips" Parts & States } + + { TOOLTIPPARTS } + TTP_STANDARD = 1; + TTP_STANDARDTITLE = 2; + TTP_BALLOON = 3; + TTP_BALLOONTITLE = 4; + TTP_CLOSE = 5; + + { CLOSESTATES } + TTCS_NORMAL = 1; + TTCS_HOT = 2; + TTCS_PRESSED = 3; + + { STANDARDSTATES } + TTSS_NORMAL = 1; + TTSS_LINK = 2; + + { BALLOONSTATES } + TTBS_NORMAL = 1; + TTBS_LINK = 2; + + +{ "TreeView" Parts & States } + + { TREEVIEWPARTS } + TVP_TREEITEM = 1; + TVP_GLYPH = 2; + TVP_BRANCH = 3; + + { TREEITEMSTATES } + TREIS_NORMAL = 1; + TREIS_HOT = 2; + TREIS_SELECTED = 3; + TREIS_DISABLED = 4; + TREIS_SELECTEDNOTFOCUS = 5; + + { GLYPHSTATES } + GLPS_CLOSED = 1; + GLPS_OPENED = 2; + + +{ "Spin" Parts & States } + + { SPINPARTS } + SPNP_UP = 1; + SPNP_DOWN = 2; + SPNP_UPHORZ = 3; + SPNP_DOWNHORZ = 4; + + { UPSTATES } + UPS_NORMAL = 1; + UPS_HOT = 2; + UPS_PRESSED = 3; + UPS_DISABLED = 4; + + { DOWNSTATES } + DNS_NORMAL = 1; + DNS_HOT = 2; + DNS_PRESSED = 3; + DNS_DISABLED = 4; + + { UPHORZSTATES } + UPHZS_NORMAL = 1; + UPHZS_HOT = 2; + UPHZS_PRESSED = 3; + UPHZS_DISABLED = 4; + + { DOWNHORZSTATES } + DNHZS_NORMAL = 1; + DNHZS_HOT = 2; + DNHZS_PRESSED = 3; + DNHZS_DISABLED = 4; + + +{ "Page" Parts & States } + + { PAGEPARTS } + PGRP_UP = 1; + PGRP_DOWN = 2; + PGRP_UPHORZ = 3; + PGRP_DOWNHORZ = 4; + +{ Pager uses same states as Spin } + + +{ "Scrollbar" Parts & States } + + { SCROLLBARPARTS } + SBP_ARROWBTN = 1; + SBP_THUMBBTNHORZ = 2; + SBP_THUMBBTNVERT = 3; + SBP_LOWERTRACKHORZ = 4; + SBP_UPPERTRACKHORZ = 5; + SBP_LOWERTRACKVERT = 6; + SBP_UPPERTRACKVERT = 7; + SBP_GRIPPERHORZ = 8; + SBP_GRIPPERVERT = 9; + SBP_SIZEBOX = 10; + + { ARROWBTNSTATES } + ABS_UPNORMAL = 1; + ABS_UPHOT = 2; + ABS_UPPRESSED = 3; + ABS_UPDISABLED = 4; + ABS_DOWNNORMAL = 5; + ABS_DOWNHOT = 6; + ABS_DOWNPRESSED = 7; + ABS_DOWNDISABLED = 8; + ABS_LEFTNORMAL = 9; + ABS_LEFTHOT = 10; + ABS_LEFTPRESSED = 11; + ABS_LEFTDISABLED = 12; + ABS_RIGHTNORMAL = 13; + ABS_RIGHTHOT = 14; + ABS_RIGHTPRESSED = 15; + ABS_RIGHTDISABLED = 16; + + { SCROLLBARSTATES } + SCRBS_NORMAL = 1; + SCRBS_HOT = 2; + SCRBS_PRESSED = 3; + SCRBS_DISABLED = 4; + + { SIZEBOXSTATES } + SZB_RIGHTALIGN = 1; + SZB_LEFTALIGN = 2; + + +{ "Edit" Parts & States } + + { EDITPARTS } + EP_EDITTEXT = 1; + EP_CARET = 2; + + { EDITTEXTSTATES } + ETS_NORMAL = 1; + ETS_HOT = 2; + ETS_SELECTED = 3; + ETS_DISABLED = 4; + ETS_FOCUSED = 5; + ETS_READONLY = 6; + ETS_ASSIST = 7; + +{ "ComboBox" Parts & States } + + { COMBOBOXPARTS } + CP_DROPDOWNBUTTON = 1; + + { COMBOBOXSTATES } + CBXS_NORMAL = 1; + CBXS_HOT = 2; + CBXS_PRESSED = 3; + CBXS_DISABLED = 4; + +{ "Taskbar Clock" Parts & States } + + { CLOCKPARTS } + CLP_TIME = 1; + + { CLOCKSTATES } + CLS_NORMAL = 1; + + +{ "Tray Notify" Parts & States } + + { TRAYNOTIFYPARTS } + TNP_BACKGROUND = 1; + TNP_ANIMBACKGROUND = 2; + + +{ "TaskBar" Parts & States } + + { TASKBARPARTS } + TBP_BACKGROUNDBOTTOM = 1; + TBP_BACKGROUNDRIGHT = 2; + TBP_BACKGROUNDTOP = 3; + TBP_BACKGROUNDLEFT = 4; + TBP_SIZINGBARBOTTOM = 5; + TBP_SIZINGBARRIGHT = 6; + TBP_SIZINGBARTOP = 7; + TBP_SIZINGBARLEFT = 8; + + +{ "TaskBand" Parts & States } + + { TASKBANDPARTS } + TDP_GROUPCOUNT = 1; + TDP_FLASHBUTTON = 2; + TDP_FLASHBUTTONGROUPMENU = 3; + + +{ "StartPanel" Parts & States } + + { STARTPANELPARTS } + SPP_USERPANE = 1; + SPP_MOREPROGRAMS = 2; + SPP_MOREPROGRAMSARROW = 3; + SPP_PROGLIST = 4; + SPP_PROGLISTSEPARATOR = 5; + SPP_PLACESLIST = 6; + SPP_PLACESLISTSEPARATOR = 7; + SPP_LOGOFF = 8; + SPP_LOGOFFBUTTONS = 9; + SPP_USERPICTURE = 10; + SPP_PREVIEW = 11; + + { MOREPROGRAMSARROWSTATES } + SPS_NORMAL = 1; + SPS_HOT = 2; + SPS_PRESSED = 3; + + { LOGOFFBUTTONSSTATES } + SPLS_NORMAL = 1; + SPLS_HOT = 2; + SPLS_PRESSED = 3; + + +{ "ExplorerBar" Parts & States } + + { EXPLORERBARPARTS } + EBP_HEADERBACKGROUND = 1; + EBP_HEADERCLOSE = 2; + EBP_HEADERPIN = 3; + EBP_IEBARMENU = 4; + EBP_NORMALGROUPBACKGROUND = 5; + EBP_NORMALGROUPCOLLAPSE = 6; + EBP_NORMALGROUPEXPAND = 7; + EBP_NORMALGROUPHEAD = 8; + EBP_SPECIALGROUPBACKGROUND = 9; + EBP_SPECIALGROUPCOLLAPSE = 10; + EBP_SPECIALGROUPEXPAND = 11; + EBP_SPECIALGROUPHEAD = 12; + + { HEADERCLOSESTATES } + EBHC_NORMAL = 1; + EBHC_HOT = 2; + EBHC_PRESSED = 3; + + { HEADERPINSTATES } + EBHP_NORMAL = 1; + EBHP_HOT = 2; + EBHP_PRESSED = 3; + EBHP_SELECTEDNORMAL = 4; + EBHP_SELECTEDHOT = 5; + EBHP_SELECTEDPRESSED = 6; + + { IEBARMENUSTATES } + EBM_NORMAL = 1; + EBM_HOT = 2; + EBM_PRESSED = 3; + + { NORMALGROUPCOLLAPSESTATES } + EBNGC_NORMAL = 1; + EBNGC_HOT = 2; + EBNGC_PRESSED = 3; + + { NORMALGROUPEXPANDSTATES } + EBNGE_NORMAL = 1; + EBNGE_HOT = 2; + EBNGE_PRESSED = 3; + + { SPECIALGROUPCOLLAPSESTATES } + EBSGC_NORMAL = 1; + EBSGC_HOT = 2; + EBSGC_PRESSED = 3; + + { SPECIALGROUPEXPANDSTATES } + EBSGE_NORMAL = 1; + EBSGE_HOT = 2; + EBSGE_PRESSED = 3; + + +{ "TaskBand" Parts & States } + + { MENUBANDPARTS } + MDP_NEWAPPBUTTON = 1; + MDP_SEPERATOR = 2; + + { MENUBANDSTATES } + MDS_NORMAL = 1; + MDS_HOT = 2; + MDS_PRESSED = 3; + MDS_DISABLED = 4; + MDS_CHECKED = 5; + MDS_HOTCHECKED = 6; + + + +{ Access to uxtheme.dll } + +type + HIMAGELIST = THandle; + HTHEME = THandle; + +const + DTT_GRAYED = $1; + + HTTB_BACKGROUNDSEG = $0000; + HTTB_FIXEDBORDER = $0002; + HTTB_CAPTION = $0004; + HTTB_RESIZINGBORDER_LEFT = $0010; + HTTB_RESIZINGBORDER_TOP = $0020; + HTTB_RESIZINGBORDER_RIGHT = $0040; + HTTB_RESIZINGBORDER_BOTTOM = $0080; + HTTB_SIZINGTEMPLATE = $0100; + HTTB_SYSTEMSIZINGMARGINS = $0200; + HTTB_RESIZINGBORDER = HTTB_RESIZINGBORDER_LEFT or HTTB_RESIZINGBORDER_TOP or + HTTB_RESIZINGBORDER_RIGHT or HTTB_RESIZINGBORDER_BOTTOM; + + + + +//------------------------------------------------------------------------------ +// OpenThemeData() - Open the theme data for the specified HWND and +// semi-colon separated list of class names. +// +// OpenThemeData() will try each class name, one at +// a time, and use the first matching theme info +// found. If a match is found, a theme handle +// to the data is returned. If no match is found, +// a "NULL" handle is returned. +// +// When the window is destroyed or a WM_THEMECHANGED +// msg is received, "CloseThemeData()" should be +// called to close the theme handle. +// +// hwnd - window handle of the control/window to be themed +// +// pszClassList - class name (or list of names) to match to theme data +// section. if the list contains more than one name, +// the names are tested one at a time for a match. +// If a match is found, OpenThemeData() returns a +// theme handle associated with the matching class. +// This param is a list (instead of just a single +// class name) to provide the class an opportunity +// to get the "best" match between the class and +// the current theme. For example, a button might +// pass L"OkButton, Button" if its ID=ID_OK. If +// the current theme has an entry for OkButton, +// that will be used. Otherwise, we fall back on +// the normal Button entry. +//------------------------------------------------------------------------------ + +var + OpenThemeData: function(hwnd: HWND; pszClassList: LPCWSTR): HTHEME; stdcall; + + +//------------------------------------------------------------------------------ +// CloseThemeData() - closes the theme data handle. This should be done +// when the window being themed is destroyed or +// whenever a WM_THEMECHANGED msg is received +// (followed by an attempt to create a new Theme data +// handle). +// +// hTheme - open theme data handle (returned from prior call +// to OpenThemeData() API). +//------------------------------------------------------------------------------ + + CloseThemeData: function(hTheme: HTHEME): HRESULT; stdcall; + + +//------------------------------------------------------------------------------ +// functions for basic drawing support +//------------------------------------------------------------------------------ +// The following methods are the theme-aware drawing services. +// Controls/Windows are defined in drawable "parts" by their author: a +// parent part and 0 or more child parts. Each of the parts can be +// described in "states" (ex: disabled, hot, pressed). +//------------------------------------------------------------------------------ +// For the list of all themed classes and the definition of all +// parts and states, see the file "tmschmea.h". +//------------------------------------------------------------------------------ +// Each of the below methods takes a "iPartId" param to specify the +// part and a "iStateId" to specify the state of the part. +// "iStateId=0" refers to the root part. "iPartId" = "0" refers to +// the root class. +//------------------------------------------------------------------------------ +// Note: draw operations are always scaled to fit (and not to exceed) +// the specified "Rect". +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +// DrawThemeBackground() +// - draws the theme-specified border and fill for +// the "iPartId" and "iStateId". This could be +// based on a bitmap file, a border and fill, or +// other image description. +// +// hTheme - theme data handle +// hdc - HDC to draw into +// iPartId - part number to draw +// iStateId - state number (of the part) to draw +// pRect - defines the size/location of the part +// pClipRect - optional clipping rect (don't draw outside it) +//------------------------------------------------------------------------------ + + DrawThemeBackground: function(hTheme: HTHEME; hdc: HDC; iPartId, iStateId: Integer; + const Rect: TRect; pClipRect: PRect): HRESULT; stdcall; + + +//------------------------------------------------------------------------------ +// DrawThemeText() - draws the text using the theme-specified +// color and font for the "iPartId" and +// "iStateId". +// +// hTheme - theme data handle +// hdc - HDC to draw into +// iPartId - part number to draw +// iStateId - state number (of the part) to draw +// pszText - actual text to draw +// dwCharCount - number of chars to draw (-1 for all) +// dwTextFlags - same as DrawText() "uFormat" param +// dwTextFlags2 - additional drawing options +// pRect - defines the size/location of the part +//------------------------------------------------------------------------------ + + DrawThemeText: function(hTheme: HTHEME; hdc: HDC; iPartId, iStateId: Integer; pszText: LPCWSTR; iCharCount: Integer; + dwTextFlags, dwTextFlags2: DWORD; const pRect: TRect): HRESULT; stdcall; + + +//------------------------------------------------------------------------------ +// GetThemeBackgroundContentRect() +// - gets the size of the content for the theme-defined +// background. This is usually the area inside +// the borders or Margins. +// +// hTheme - theme data handle +// hdc - (optional) device content to be used for drawing +// iPartId - part number to draw +// iStateId - state number (of the part) to draw +// pBoundingRect - the outer RECT of the part being drawn +// pContentRect - RECT to receive the content area +//------------------------------------------------------------------------------ + + GetThemeBackgroundContentRect: function(hTheme: HTHEME; hdc: HDC; iPartId, iStateId: Integer; + const pBoundingRect: TRect; pContentRect: PRECT): HRESULT; stdcall; + + +//------------------------------------------------------------------------------ +// GetThemeBackgroundExtent() - calculates the size/location of the theme- +// specified background based on the +// "pContentRect". +// +// hTheme - theme data handle +// hdc - (optional) device content to be used for drawing +// iPartId - part number to draw +// iStateId - state number (of the part) to draw +// pContentRect - RECT that defines the content area +// pBoundingRect - RECT to receive the overall size/location of part +//------------------------------------------------------------------------------ + + GetThemeBackgroundExtent: function(hTheme: HTHEME; hdc: HDC; iPartId, iStateId: Integer; const pContentRect: TRect; + var pExtentRect: TRect): HRESULT; stdcall; + +//------------------------------------------------------------------------------ +// GetThemePartSize() - returns the specified size of the theme part +// +// hTheme - theme data handle +// hdc - HDC to select font into & measure against +// iPartId - part number to retrieve size for +// iStateId - state number (of the part) +// prc - (optional) rect for part drawing destination +// eSize - the type of size to be retreived +// psz - receives the specified size of the part +//------------------------------------------------------------------------------ + +type + THEMESIZE = ( + TS_MIN, // minimum size of a visual style part + TS_TRUE, // size of the visual style part that will best fit the available space + TS_DRAW); // size that the theme manager uses to draw a part + TThemeSize = THEMESIZE; + +var + GetThemePartSize: function(hTheme: HTHEME; hdc: HDC; iPartId, iStateId: Integer; prc: PRECT; eSize: THEMESIZE; + var psz: TSize): HRESULT; stdcall; + +//------------------------------------------------------------------------------ +// GetThemeTextExtent() - calculates the size/location of the specified +// text when rendered in the Theme Font. +// +// hTheme - theme data handle +// hdc - HDC to select font & measure into +// iPartId - part number to draw +// iStateId - state number (of the part) +// pszText - the text to be measured +// dwCharCount - number of chars to draw (-1 for all) +// dwTextFlags - same as DrawText() "uFormat" param +// pszBoundingRect - optional: to control layout of text +// pszExtentRect - receives the RECT for text size/location +//------------------------------------------------------------------------------ + + GetThemeTextExtent: function(hTheme: HTHEME; hdc: HDC; iPartId, iStateId: Integer; pszText: LPCWSTR; + iCharCount: Integer; dwTextFlags: DWORD; pBoundingRect: PRECT; var pExtentRect: TRect): HRESULT; stdcall; + + +//------------------------------------------------------------------------------ +// GetThemeTextMetrics() +// - returns info about the theme-specified font +// for the part/state passed in. +// +// hTheme - theme data handle +// hdc - optional: HDC for screen context +// iPartId - part number to draw +// iStateId - state number (of the part) +// ptm - receives the font info +//------------------------------------------------------------------------------ + + GetThemeTextMetrics: function(hTheme: HTHEME; hdc: HDC; iPartId, iStateId: Integer; + var ptm: TEXTMETRIC): HRESULT; stdcall; + + +//------------------------------------------------------------------------------ +// GetThemeBackgroundRegion() +// - computes the region for a regular or partially +// transparent theme-specified background that is +// bound by the specified "pRect". +// If the rectangle is empty, sets the HRGN to NULL +// and return S_FALSE. +// +// hTheme - theme data handle +// hdc - optional HDC to draw into (DPI scaling) +// iPartId - part number to draw +// iStateId - state number (of the part) +// pRect - the RECT used to draw the part +// pRegion - receives handle to calculated region +//------------------------------------------------------------------------------ + + GetThemeBackgroundRegion: function(hTheme: HTHEME; hdc: HDC; iPartId, iStateId: Integer; const pRect: TRect; + var pRegion: HRGN): HRESULT; stdcall; + + +//------------------------------------------------------------------------------ +// HitTestThemeBackground() +// - returns a HitTestCode (a subset of the values +// returned by WM_NCHITTEST) for the point "ptTest" +// within the theme-specified background +// (bound by pRect). "pRect" and "ptTest" should +// both be in the same coordinate system +// (client, screen, etc). +// +// hTheme - theme data handle +// hdc - HDC to draw into +// iPartId - part number to test against +// iStateId - state number (of the part) +// pRect - the RECT used to draw the part +// hrgn - optional region to use; must be in same coordinates as +// - pRect and pTest. +// ptTest - the hit point to be tested +// dwOptions - HTTB_xxx constants +// pwHitTestCode - receives the returned hit test code - one of: +// +// HTNOWHERE, HTLEFT, HTTOPLEFT, HTBOTTOMLEFT, +// HTRIGHT, HTTOPRIGHT, HTBOTTOMRIGHT, +// HTTOP, HTBOTTOM, HTCLIENT +//------------------------------------------------------------------------------ + + HitTestThemeBackground: function(hTheme: HTHEME; hdc: HDC; iPartId, iStateId: Integer; dwOptions: DWORD; + const pRect: TRect; hrgn: HRGN; ptTest: TPoint; var pwHitTestCode: WORD): HRESULT; stdcall; + + +//------------------------------------------------------------------------------ +// DrawThemeEdge() - Similar to the DrawEdge() API, but uses part colors +// and is high-DPI aware +// hTheme - theme data handle +// hdc - HDC to draw into +// iPartId - part number to draw +// iStateId - state number of part +// pDestRect - the RECT used to draw the line(s) +// uEdge - Same as DrawEdge() API +// uFlags - Same as DrawEdge() API +// pContentRect - Receives the interior rect if (uFlags & BF_ADJUST) +//------------------------------------------------------------------------------ + + DrawThemeEdge: function(hTheme: HTHEME; hdc: HDC; iPartId, iStateId: Integer; const pDestRect: TRect; uEdge, + uFlags: UINT; pContentRect: PRECT): HRESULT; stdcall; + + +//------------------------------------------------------------------------------ +// DrawThemeIcon() - draws an image within an imagelist based on +// a (possible) theme-defined effect. +// +// hTheme - theme data handle +// hdc - HDC to draw into +// iPartId - part number to draw +// iStateId - state number of part +// pRect - the RECT to draw the image within +// himl - handle to IMAGELIST +// iImageIndex - index into IMAGELIST (which icon to draw) +//------------------------------------------------------------------------------ + + DrawThemeIcon: function(hTheme: HTHEME; hdc: HDC; iPartId, iStateId: Integer; const pRect: TRect; himl: HIMAGELIST; + iImageIndex: Integer): HRESULT; stdcall; + + +//------------------------------------------------------------------------------ +// IsThemePartDefined() - returns TRUE if the theme has defined parameters +// for the specified "iPartId" and "iStateId". +// +// hTheme - theme data handle +// iPartId - part number to find definition for +// iStateId - state number of part +//------------------------------------------------------------------------------ + + IsThemePartDefined: function(hTheme: HTHEME; iPartId, iStateId: Integer): BOOL; stdcall; + + +//------------------------------------------------------------------------------ +// IsThemeBackgroundPartiallyTransparent() +// - returns TRUE if the theme specified background for +// the part/state has transparent pieces or +// alpha-blended pieces. +// +// hTheme - theme data handle +// iPartId - part number +// iStateId - state number of part +//------------------------------------------------------------------------------ + + IsThemeBackgroundPartiallyTransparent: function(hTheme: HTHEME; iPartId, iStateId: Integer): BOOL; stdcall; + + +//------------------------------------------------------------------------------ +// lower-level theme information services +//------------------------------------------------------------------------------ +// The following methods are getter routines for each of the Theme Data types. +// Controls/Windows are defined in drawable "parts" by their author: a +// parent part and 0 or more child parts. Each of the parts can be +// described in "states" (ex: disabled, hot, pressed). +//------------------------------------------------------------------------------ +// Each of the below methods takes a "iPartId" param to specify the +// part and a "iStateId" to specify the state of the part. +// "iStateId=0" refers to the root part. "iPartId" = "0" refers to +// the root class. +//------------------------------------------------------------------------------ +// Each method also take a "iPropId" param because multiple instances of +// the same primitive type can be defined in the theme schema. +//------------------------------------------------------------------------------ + + +//------------------------------------------------------------------------------ +// GetThemeColor() - Get the value for the specified COLOR property +// +// hTheme - theme data handle +// iPartId - part number +// iStateId - state number of part +// iPropId - the property number to get the value for +// pColor - receives the value of the property +//------------------------------------------------------------------------------ + +var + GetThemeColor: function(hTheme: HTHEME; iPartId, iStateId, iPropId: Integer; var pColor: COLORREF): HRESULT; stdcall; + +//------------------------------------------------------------------------------ +// GetThemeMetric() - Get the value for the specified metric/size +// property +// +// hTheme - theme data handle +// hdc - (optional) hdc to be drawn into (DPI scaling) +// iPartId - part number +// iStateId - state number of part +// iPropId - the property number to get the value for +// piVal - receives the value of the property +//------------------------------------------------------------------------------ + + GetThemeMetric: function(hTheme: HTHEME; hdc: HDC; iPartId, iStateId, iPropId: Integer; + var piVal: Integer): HRESULT; stdcall; + +//------------------------------------------------------------------------------ +// GetThemeString() - Get the value for the specified string property +// +// hTheme - theme data handle +// iPartId - part number +// iStateId - state number of part +// iPropId - the property number to get the value for +// pszBuff - receives the string property value +// cchMaxBuffChars - max. number of chars allowed in pszBuff +//------------------------------------------------------------------------------ + + GetThemeString: function(hTheme: HTHEME; iPartId, iStateId, iPropId: Integer; pszBuff: LPWSTR; + cchMaxBuffChars: Integer): HRESULT; stdcall; + +//------------------------------------------------------------------------------ +// GetThemeBool() - Get the value for the specified BOOL property +// +// hTheme - theme data handle +// iPartId - part number +// iStateId - state number of part +// iPropId - the property number to get the value for +// pfVal - receives the value of the property +//------------------------------------------------------------------------------ + + GetThemeBool: function(hTheme: HTHEME; iPartId, iStateId, iPropId: Integer; var pfVal: BOOL): HRESULT; stdcall; + +//------------------------------------------------------------------------------ +// GetThemeInt() - Get the value for the specified int property +// +// hTheme - theme data handle +// iPartId - part number +// iStateId - state number of part +// iPropId - the property number to get the value for +// piVal - receives the value of the property +//------------------------------------------------------------------------------ + + GetThemeInt: function(hTheme: HTHEME; iPartId, iStateId, iPropId: Integer; var piVal: Integer): HRESULT; stdcall; + +//------------------------------------------------------------------------------ +// GetThemeEnumValue() - Get the value for the specified ENUM property +// +// hTheme - theme data handle +// iPartId - part number +// iStateId - state number of part +// iPropId - the property number to get the value for +// piVal - receives the value of the enum (cast to int*) +//------------------------------------------------------------------------------ + + GetThemeEnumValue: function(hTheme: HTHEME; iPartId, iStateId, iPropId: Integer; var piVal: Integer): HRESULT; stdcall; + +//------------------------------------------------------------------------------ +// GetThemePosition() - Get the value for the specified position +// property +// +// hTheme - theme data handle +// iPartId - part number +// iStateId - state number of part +// iPropId - the property number to get the value for +// pPoint - receives the value of the position property +//------------------------------------------------------------------------------ + + GetThemePosition: function(hTheme: HTHEME; iPartId, iStateId, iPropId: Integer;var pPoint: TPoint): HRESULT; stdcall; + +//------------------------------------------------------------------------------ +// GetThemeFont() - Get the value for the specified font property +// +// hTheme - theme data handle +// hdc - (optional) hdc to be drawn to (DPI scaling) +// iPartId - part number +// iStateId - state number of part +// iPropId - the property number to get the value for +// pFont - receives the value of the LOGFONT property +// (scaled for the current logical screen dpi) +//------------------------------------------------------------------------------ + + GetThemeFont: function(hTheme: HTHEME; hdc: HDC; iPartId, iStateId, iPropId: Integer; + var pFont: LOGFONT): HRESULT; stdcall; + +//------------------------------------------------------------------------------ +// GetThemeRect() - Get the value for the specified RECT property +// +// hTheme - theme data handle +// iPartId - part number +// iStateId - state number of part +// iPropId - the property number to get the value for +// pRect - receives the value of the RECT property +//------------------------------------------------------------------------------ + + GetThemeRect: function(hTheme: HTHEME; iPartId, iStateId, iPropId: Integer; var pRect: TRect): HRESULT; stdcall; + +//------------------------------------------------------------------------------ +// GetThemeMargins() - Get the value for the specified MARGINS property +// +// hTheme - theme data handle +// hdc - (optional) hdc to be used for drawing +// iPartId - part number +// iStateId - state number of part +// iPropId - the property number to get the value for +// prc - RECT for area to be drawn into +// pMargins - receives the value of the MARGINS property +//------------------------------------------------------------------------------ + +type + _MARGINS = record + cxLeftWidth: Integer; // width of left border that retains its size + cxRightWidth: Integer; // width of right border that retains its size + cyTopHeight: Integer; // height of top border that retains its size + cyBottomHeight: Integer; // height of bottom border that retains its size + end; + MARGINS = _MARGINS; + PMARGINS = ^MARGINS; + TMargins = MARGINS; + +var + GetThemeMargins: function(hTheme: HTHEME; hdc: HDC; iPartId, iStateId, iPropId: Integer; prc: PRECT; + var pMargins: MARGINS): HRESULT; stdcall; + + +//------------------------------------------------------------------------------ +// GetThemeIntList() - Get the value for the specified INTLIST struct +// +// hTheme - theme data handle +// iPartId - part number +// iStateId - state number of part +// iPropId - the property number to get the value for +// pIntList - receives the value of the INTLIST property +//------------------------------------------------------------------------------ + +const + MAX_INTLIST_COUNT = 10; + +type + _INTLIST = record + iValueCount: Integer; + iValues: array [0..MAX_INTLIST_COUNT - 1] of Integer; + end; + INTLIST = _INTLIST; + PINTLIST = ^INTLIST; + TIntList = INTLIST; + +var + GetThemeIntList: function(hTheme: HTHEME; iPartId, iStateId, iPropId: Integer; var pIntList: INTLIST): HRESULT; stdcall; + + +//------------------------------------------------------------------------------ +// GetThemePropertyOrigin() +// - searches for the specified theme property +// and sets "pOrigin" to indicate where it was +// found (or not found) +// +// hTheme - theme data handle +// iPartId - part number +// iStateId - state number of part +// iPropId - the property number to search for +// pOrigin - receives the value of the property origin +//------------------------------------------------------------------------------ + +type + PROPERTYORIGIN = ( + PO_STATE, // property was found in the state section + PO_PART, // property was found in the part section + PO_CLASS, // property was found in the class section + PO_GLOBAL, // property was found in [globals] section + PO_NOTFOUND); // property was not found + TPropertyOrigin = PROPERTYORIGIN; + +var + GetThemePropertyOrigin: function(hTheme: HTHEME; iPartId, iStateId, iPropId: Integer; + var pOrigin: PROPERTYORIGIN): HRESULT; stdcall; + +//------------------------------------------------------------------------------ +// SetWindowTheme() +// - redirects an existing Window to use a different +// section of the current theme information than its +// class normally asks for. +// +// hwnd - the handle of the window (cannot be NULL) +// +// pszSubAppName - app (group) name to use in place of the calling +// app's name. If NULL, the actual calling app +// name will be used. +// +// pszSubIdList - semicolon separated list of class Id names to +// use in place of actual list passed by the +// window's class. if NULL, the id list from the +// calling class is used. +//------------------------------------------------------------------------------ +// The Theme Manager will remember the "pszSubAppName" and the +// "pszSubIdList" associations thru the lifetime of the window (even +// if themes are subsequently changed). The window is sent a +// "WM_THEMECHANGED" msg at the end of this call, so that the new +// theme can be found and applied. +//------------------------------------------------------------------------------ +// When "pszSubAppName" or "pszSubIdList" are NULL, the Theme Manager +// removes the previously remember association. To turn off theme-ing for +// the specified window, you can pass an empty string (L"") so it +// won't match any section entries. +//------------------------------------------------------------------------------ + + SetWindowTheme: function(hwnd: HWND; pszSubAppName: LPCWSTR; pszSubIdList: LPCWSTR): HRESULT; stdcall; + +//------------------------------------------------------------------------------ +// GetThemeFilename() - Get the value for the specified FILENAME property. +// +// hTheme - theme data handle +// iPartId - part number +// iStateId - state number of part +// iPropId - the property number to search for +// pszThemeFileName - output buffer to receive the filename +// cchMaxBuffChars - the size of the return buffer, in chars +//------------------------------------------------------------------------------ + + GetThemeFilename: function(hTheme: HTHEME; iPartId, iStateId, iPropId: Integer; pszThemeFileName: LPWSTR; + cchMaxBuffChars: Integer): HRESULT; stdcall; + +//------------------------------------------------------------------------------ +// GetThemeSysColor() - Get the value of the specified System color. +// +// hTheme - the theme data handle. if non-NULL, will return +// color from [SysMetrics] section of theme. +// if NULL, will return the global system color. +// +// iColorId - the system color index defined in winuser.h +//------------------------------------------------------------------------------ + + GetThemeSysColor: function(hTheme: HTHEME; iColorId: Integer): COLORREF; stdcall; + +//------------------------------------------------------------------------------ +// GetThemeSysColorBrush() +// - Get the brush for the specified System color. +// +// hTheme - the theme data handle. if non-NULL, will return +// brush matching color from [SysMetrics] section of +// theme. if NULL, will return the brush matching +// global system color. +// +// iColorId - the system color index defined in winuser.h +//------------------------------------------------------------------------------ + + GetThemeSysColorBrush: function(hTheme: HTHEME; iColorId: Integer): HBRUSH; stdcall; + +//------------------------------------------------------------------------------ +// GetThemeSysBool() - Get the boolean value of specified System metric. +// +// hTheme - the theme data handle. if non-NULL, will return +// BOOL from [SysMetrics] section of theme. +// if NULL, will return the specified system boolean. +// +// iBoolId - the TMT_XXX BOOL number (first BOOL +// is TMT_FLATMENUS) +//------------------------------------------------------------------------------ + + GetThemeSysBool: function(hTheme: HTHEME; iBoolId: Integer): BOOL; stdcall; + +//------------------------------------------------------------------------------ +// GetThemeSysSize() - Get the value of the specified System size metric. +// (scaled for the current logical screen dpi) +// +// hTheme - the theme data handle. if non-NULL, will return +// size from [SysMetrics] section of theme. +// if NULL, will return the global system metric. +// +// iSizeId - the following values are supported when +// hTheme is non-NULL: +// +// SM_CXBORDER (border width) +// SM_CXVSCROLL (scrollbar width) +// SM_CYHSCROLL (scrollbar height) +// SM_CXSIZE (caption width) +// SM_CYSIZE (caption height) +// SM_CXSMSIZE (small caption width) +// SM_CYSMSIZE (small caption height) +// SM_CXMENUSIZE (menubar width) +// SM_CYMENUSIZE (menubar height) +// +// when hTheme is NULL, iSizeId is passed directly +// to the GetSystemMetrics() function +//------------------------------------------------------------------------------ + + GetThemeSysSize: function(hTheme: HTHEME; iSizeId: Integer): Integer; stdcall; + +//------------------------------------------------------------------------------ +// GetThemeSysFont() - Get the LOGFONT for the specified System font. +// +// hTheme - the theme data handle. if non-NULL, will return +// font from [SysMetrics] section of theme. +// if NULL, will return the specified system font. +// +// iFontId - the TMT_XXX font number (first font +// is TMT_CAPTIONFONT) +// +// plf - ptr to LOGFONT to receive the font value. +// (scaled for the current logical screen dpi) +//------------------------------------------------------------------------------ + + GetThemeSysFont: function(hTheme: HTHEME; iFontId: Integer; var plf: LOGFONT): HRESULT; stdcall; + +//------------------------------------------------------------------------------ +// GetThemeSysString() - Get the value of specified System string metric. +// +// hTheme - the theme data handle (required) +// +// iStringId - must be one of the following values: +// +// TMT_CSSNAME +// TMT_XMLNAME +// +// pszStringBuff - the buffer to receive the string value +// +// cchMaxStringChars - max. number of chars that pszStringBuff can hold +//------------------------------------------------------------------------------ + + GetThemeSysString: function(hTheme: HTHEME; iStringId: Integer; pszStringBuff: LPWSTR; + cchMaxStringChars: Integer): HRESULT; stdcall; + +//------------------------------------------------------------------------------ +// GetThemeSysInt() - Get the value of specified System int. +// +// hTheme - the theme data handle (required) +// +// iIntId - must be one of the following values: +// +// TMT_DPIX +// TMT_DPIY +// TMT_MINCOLORDEPTH +// +// piValue - ptr to int to receive value +//------------------------------------------------------------------------------ + + GetThemeSysInt: function(hTheme: HTHEME; iIntId: Integer; var piValue: Integer): HRESULT; stdcall; + +//------------------------------------------------------------------------------ +// IsThemeActive() - can be used to test if a system theme is active +// for the current user session. +// +// use the API "IsAppThemed()" to test if a theme is +// active for the calling process. +//------------------------------------------------------------------------------ + + IsThemeActive: function: BOOL; stdcall; + +//------------------------------------------------------------------------------ +// IsAppThemed() - returns TRUE if a theme is active and available to +// the current process +//------------------------------------------------------------------------------ + + IsAppThemed: function: BOOL; stdcall; + +//------------------------------------------------------------------------------ +// GetWindowTheme() - if window is themed, returns its most recent +// HTHEME from OpenThemeData() - otherwise, returns +// NULL. +// +// hwnd - the window to get the HTHEME of +//------------------------------------------------------------------------------ + + GetWindowTheme: function(hwnd: HWND): HTHEME; stdcall; + +//------------------------------------------------------------------------------ +// EnableThemeDialogTexture() +// +// - Enables/disables dialog background theme. This method can be used to +// tailor dialog compatibility with child windows and controls that +// may or may not coordinate the rendering of their client area backgrounds +// with that of their parent dialog in a manner that supports seamless +// background texturing. +// +// hdlg - the window handle of the target dialog +// dwFlags - ETDT_ENABLE to enable the theme-defined dialog background texturing, +// ETDT_DISABLE to disable background texturing, +// ETDT_ENABLETAB to enable the theme-defined background +// texturing using the Tab texture +//------------------------------------------------------------------------------ + +const + ETDT_DISABLE = $00000001; + ETDT_ENABLE = $00000002; + ETDT_USETABTEXTURE = $00000004; + ETDT_ENABLETAB = ETDT_ENABLE or ETDT_USETABTEXTURE; + +var + EnableThemeDialogTexture: function(hwnd: HWND; dwFlags: DWORD): HRESULT; stdcall; + +//------------------------------------------------------------------------------ +// IsThemeDialogTextureEnabled() +// +// - Reports whether the dialog supports background texturing. +// +// hdlg - the window handle of the target dialog +//------------------------------------------------------------------------------ + +var + IsThemeDialogTextureEnabled: function(hwnd: HWND): BOOL; stdcall; + +//------------------------------------------------------------------------------ +// GetThemeAppProperties() +// - returns the app property flags that control theming +//------------------------------------------------------------------------------ + +const + STAP_ALLOW_NONCLIENT = 1; + STAP_ALLOW_CONTROLS = 2; + STAP_ALLOW_WEBCONTENT = 4; + +var + GetThemeAppProperties: function: DWORD; stdcall; + +//------------------------------------------------------------------------------ +// SetThemeAppProperties() +// - sets the flags that control theming within the app +// +// dwFlags - the flag values to be set +//------------------------------------------------------------------------------ + +var + SetThemeAppProperties: procedure(dwFlags: DWORD); stdcall; + +//------------------------------------------------------------------------------ +// GetCurrentThemeName() +// - Get the name of the current theme in-use. +// Optionally, return the ColorScheme name and the +// Size name of the theme. +// +// pszThemeFileName - receives the theme path & filename +// cchMaxNameChars - max chars allowed in pszNameBuff +// +// pszColorBuff - (optional) receives the canonical color scheme name +// (not the display name) +// cchMaxColorChars - max chars allowed in pszColorBuff +// +// pszSizeBuff - (optional) receives the canonical size name +// (not the display name) +// cchMaxSizeChars - max chars allowed in pszSizeBuff +//------------------------------------------------------------------------------ + +var + GetCurrentThemeName: function(pszThemeFileName: LPWSTR; cchMaxNameChars: Integer; pszColorBuff: LPWSTR; + cchMaxColorChars: Integer; pszSizeBuff: LPWSTR; cchMaxSizeChars: Integer): HRESULT; stdcall; + +//------------------------------------------------------------------------------ +// GetThemeDocumentationProperty() +// - Get the value for the specified property name from +// the [documentation] section of the themes.ini file +// for the specified theme. If the property has been +// localized in the theme files string table, the +// localized version of the property value is returned. +// +// pszThemeFileName - filename of the theme file to query +// pszPropertyName - name of the string property to retreive a value for +// pszValueBuff - receives the property string value +// cchMaxValChars - max chars allowed in pszValueBuff +//------------------------------------------------------------------------------ + +{ commented out for D4 compatibility +const + SZ_THDOCPROP_DISPLAYNAME = WideString('DisplayName'); + SZ_THDOCPROP_CANONICALNAME = WideString('ThemeName'); + SZ_THDOCPROP_TOOLTIP = WideString('ToolTip'); + SZ_THDOCPROP_AUTHOR = WideString('author'); } + +var + GetThemeDocumentationProperty: function(pszThemeName, pszPropertyName: LPCWSTR; pszValueBuff: LPWSTR; + cchMaxValChars: Integer): HRESULT; stdcall; + +//------------------------------------------------------------------------------ +// Theme API Error Handling +// +// All functions in the Theme API not returning an HRESULT (THEMEAPI_) +// use the WIN32 function "SetLastError()" to record any call failures. +// +// To retreive the error code of the last failure on the +// current thread for these type of API's, use the WIN32 function +// "GetLastError()". +// +// All Theme API error codes (HRESULT's and GetLastError() values) +// should be normal win32 errors which can be formatted into +// strings using the Win32 API FormatMessage(). +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +// DrawThemeParentBackground() +// - used by partially-transparent or alpha-blended +// child controls to draw the part of their parent +// that they appear in front of. +// +// hwnd - handle of the child control +// hdc - hdc of the child control +// prc - (optional) rect that defines the area to be +// drawn (CHILD coordinates) +//------------------------------------------------------------------------------ + +var + DrawThemeParentBackground: function(hwnd: HWND; hdc: HDC; prc: PRECT): HRESULT; stdcall; + +//------------------------------------------------------------------------------ +// EnableTheming() - enables or disables themeing for the current user +// in the current and future sessions. +// +// fEnable - if FALSE, disable theming & turn themes off. +// - if TRUE, enable themeing and, if user previously +// had a theme active, make it active now. +//------------------------------------------------------------------------------ + +var + EnableTheming: function(fEnable: BOOL): HRESULT; stdcall; + +implementation + +const + UXTHEME_DLL = 'uxtheme.dll'; + +var + DllHandle: THandle; + +function InitXPThemes: Boolean; +begin + if DllHandle = 0 then + begin + DllHandle := LoadLibrary(UXTHEME_DLL); + if DllHandle > 0 then + begin + OpenThemeData := GetProcAddress(DllHandle, 'OpenThemeData'); + CloseThemeData := GetProcAddress(DllHandle, 'CloseThemeData'); + DrawThemeBackground := GetProcAddress(DllHandle, 'DrawThemeBackground'); + DrawThemeText := GetProcAddress(DllHandle, 'DrawThemeText'); + GetThemeBackgroundContentRect := GetProcAddress(DllHandle, 'GetThemeBackgroundContentRect'); + GetThemeBackgroundExtent := GetProcAddress(DllHandle, 'GetThemeBackgroundContentRect'); + GetThemePartSize := GetProcAddress(DllHandle, 'GetThemePartSize'); + GetThemeTextExtent := GetProcAddress(DllHandle, 'GetThemeTextExtent'); + GetThemeTextMetrics := GetProcAddress(DllHandle, 'GetThemeTextMetrics'); + GetThemeBackgroundRegion := GetProcAddress(DllHandle, 'GetThemeBackgroundRegion'); + HitTestThemeBackground := GetProcAddress(DllHandle, 'HitTestThemeBackground'); + DrawThemeEdge := GetProcAddress(DllHandle, 'DrawThemeEdge'); + DrawThemeIcon := GetProcAddress(DllHandle, 'DrawThemeIcon'); + IsThemePartDefined := GetProcAddress(DllHandle, 'IsThemePartDefined'); + IsThemeBackgroundPartiallyTransparent := GetProcAddress(DllHandle, 'IsThemeBackgroundPartiallyTransparent'); + GetThemeColor := GetProcAddress(DllHandle, 'GetThemeColor'); + GetThemeMetric := GetProcAddress(DllHandle, 'GetThemeMetric'); + GetThemeString := GetProcAddress(DllHandle, 'GetThemeString'); + GetThemeBool := GetProcAddress(DllHandle, 'GetThemeBool'); + GetThemeInt := GetProcAddress(DllHandle, 'GetThemeInt'); + GetThemeEnumValue := GetProcAddress(DllHandle, 'GetThemeEnumValue'); + GetThemePosition := GetProcAddress(DllHandle, 'GetThemePosition'); + GetThemeFont := GetProcAddress(DllHandle, 'GetThemeFont'); + GetThemeRect := GetProcAddress(DllHandle, 'GetThemeRect'); + GetThemeMargins := GetProcAddress(DllHandle, 'GetThemeMargins'); + GetThemeIntList := GetProcAddress(DllHandle, 'GetThemeIntList'); + GetThemePropertyOrigin := GetProcAddress(DllHandle, 'GetThemePropertyOrigin'); + SetWindowTheme := GetProcAddress(DllHandle, 'SetWindowTheme'); + GetThemeFilename := GetProcAddress(DllHandle, 'GetThemeFilename'); + GetThemeSysColor := GetProcAddress(DllHandle, 'GetThemeSysColor'); + GetThemeSysColorBrush := GetProcAddress(DllHandle, 'GetThemeSysColorBrush'); + GetThemeSysBool := GetProcAddress(DllHandle, 'GetThemeSysBool'); + GetThemeSysSize := GetProcAddress(DllHandle, 'GetThemeSysSize'); + GetThemeSysFont := GetProcAddress(DllHandle, 'GetThemeSysFont'); + GetThemeSysString := GetProcAddress(DllHandle, 'GetThemeSysString'); + GetThemeSysInt := GetProcAddress(DllHandle, 'GetThemeSysInt'); + IsThemeActive := GetProcAddress(DllHandle, 'IsThemeActive'); + IsAppThemed := GetProcAddress(DllHandle, 'IsAppThemed'); + GetWindowTheme := GetProcAddress(DllHandle, 'GetWindowTheme'); + EnableThemeDialogTexture := GetProcAddress(DllHandle, 'EnableThemeDialogTexture'); + IsThemeDialogTextureEnabled := GetProcAddress(DllHandle, 'IsThemeDialogTextureEnabled'); + GetThemeAppProperties := GetProcAddress(DllHandle, 'GetThemeAppProperties'); + SetThemeAppProperties := GetProcAddress(DllHandle, 'SetThemeAppProperties'); + GetCurrentThemeName := GetProcAddress(DllHandle, 'GetCurrentThemeName'); + GetThemeDocumentationProperty := GetProcAddress(DllHandle, 'GetThemeDocumentationProperty'); + DrawThemeParentBackground := GetProcAddress(DllHandle, 'DrawThemeParentBackground'); + EnableTheming := GetProcAddress(DllHandle, 'EnableTheming'); + end; + end; + Result := DllHandle > 0; +end; + +procedure FreeXPThemes; +begin + if DllHandle <> 0 then + begin + FreeLibrary(DllHandle); + DllHandle := 0; + + OpenThemeData := nil; + CloseThemeData := nil; + DrawThemeBackground := nil; + DrawThemeText := nil; + GetThemeBackgroundContentRect := nil; + GetThemeBackgroundExtent := nil; + GetThemePartSize := nil; + GetThemeTextExtent := nil; + GetThemeTextMetrics := nil; + GetThemeBackgroundRegion := nil; + HitTestThemeBackground := nil; + DrawThemeEdge := nil; + DrawThemeIcon := nil; + IsThemePartDefined := nil; + IsThemeBackgroundPartiallyTransparent := nil; + GetThemeColor := nil; + GetThemeMetric := nil; + GetThemeString := nil; + GetThemeBool := nil; + GetThemeInt := nil; + GetThemeEnumValue := nil; + GetThemePosition := nil; + GetThemeFont := nil; + GetThemeRect := nil; + GetThemeMargins := nil; + GetThemeIntList := nil; + GetThemePropertyOrigin := nil; + SetWindowTheme := nil; + GetThemeFilename := nil; + GetThemeSysColor := nil; + GetThemeSysColorBrush := nil; + GetThemeSysBool := nil; + GetThemeSysSize := nil; + GetThemeSysFont := nil; + GetThemeSysString := nil; + GetThemeSysInt := nil; + IsThemeActive := nil; + IsAppThemed := nil; + GetWindowTheme := nil; + EnableThemeDialogTexture := nil; + IsThemeDialogTextureEnabled := nil; + GetThemeAppProperties := nil; + SetThemeAppProperties := nil; + GetCurrentThemeName := nil; + GetThemeDocumentationProperty := nil; + DrawThemeParentBackground := nil; + EnableTheming := nil; + end; +end; + +function CanUseXPThemes: Boolean; +begin + Result := (DllHandle > 0) and IsAppThemed and IsThemeActive; +end; + +end. diff --git a/official/2.1.6+2.1.beta1/TBX/TBXWhidbeyTheme.pas b/official/2.1.6+2.1.beta1/TBX/TBXWhidbeyTheme.pas new file mode 100644 index 0000000..3399c6a --- /dev/null +++ b/official/2.1.6+2.1.beta1/TBX/TBXWhidbeyTheme.pas @@ -0,0 +1,2244 @@ +unit TBXWhidbeyTheme; + +// TBX Package +// Copyright 2001-2002 Alex A. Denisov. All Rights Reserved +// See TBX.chm for license and installation instructions +// +// "Whidbey" TBX theme 2004 Roy Magne Klever +// roymagne@rmklever.com +// +// Version for TBX version 2.1 +// Last updated: 02.12.2004 + +interface + +uses + Windows, Messages, Graphics, TBXThemes, ImgList; + +{$DEFINE ALTERNATIVE_DISABLED_STYLE} +{.$DEFINE ALT_HEADER_STYLE} +{.$DEFINE ALT_VISUAL_STYLE} + +type + TItemPart = (ipBody, ipText, ipFrame); + TBtnItemState = (bisNormal, bisDisabled, bisSelected, bisPressed, bisHot, + bisDisabledHot, bisSelectedHot, bisPopupParent); + TMenuItemState = (misNormal, misDisabled, misHot, misDisabledHot); + TWinFramePart = (wfpBorder, wfpCaption, wfpCaptionText); + TWinFrameState = (wfsActive, wfsInactive); + + TTBXWhidbeyTheme = class(TTBXTheme) + private + procedure TBXSysCommand(var Message: TMessage); message TBX_SYSCOMMAND; + protected + { View/Window Colors } + MenubarColor: TColor; + ToolbarColor: TColor; + PopupColor: TColor; + DockPanelColor: TColor; + + PopupFrameColor: TColor; + WinFrameColors: array[TWinFrameState, TWinFramePart] of TColor; + PnlFrameColors: array[TWinFrameState, TWinFramePart] of TColor; + MenuItemColors: array[TMenuItemState, TItemPart] of TColor; + BtnItemColors: array[TBtnItemState, TItemPart] of TColor; + + { Other Colors } + DragHandleColor: TColor; + PopupSeparatorColor: TColor; + ToolbarSeparatorColor: TColor; + IconShadowColor: TColor; + StatusPanelFrameColor: TColor; + + procedure SetupColorCache; virtual; + protected + { Internal Methods } + function GetPartColor(const ItemInfo: TTBXItemInfo; ItemPart: TItemPart): + TColor; + function GetBtnColor(const ItemInfo: TTBXItemInfo; ItemPart: TItemPart): + TColor; + public + constructor Create(const AName: string); override; + destructor Destroy; override; + + { Metrics access} + function GetBooleanMetrics(Index: Integer): Boolean; override; + function GetImageOffset(Canvas: TCanvas; const ItemInfo: TTBXItemInfo; + ImageList: TCustomImageList): TPoint; override; + function GetIntegerMetrics(Index: Integer): Integer; override; + function GetItemColor(const ItemInfo: TTBXItemInfo): TColor; override; + function GetItemTextColor(const ItemInfo: TTBXItemInfo): TColor; override; + function GetItemImageBackground(const ItemInfo: TTBXItemInfo): TColor; + override; + procedure GetMargins(MarginID: Integer; out Margins: TTBXMargins); override; + function GetPopupShadowType: Integer; override; + procedure GetViewBorder(ViewType: Integer; out Border: TPoint); override; + function GetViewColor(AViewType: Integer): TColor; override; + procedure GetViewMargins(ViewType: Integer; out Margins: TTBXMargins); + override; + + { Painting routines } + procedure PaintBackgnd(Canvas: TCanvas; const ADockRect, ARect, AClipRect: + TRect; AColor: TColor; Transparent: Boolean; AViewType: Integer); + override; + procedure PaintButton(Canvas: TCanvas; const ARect: TRect; const ItemInfo: + TTBXItemInfo); override; + procedure PaintCaption(Canvas: TCanvas; const ARect: TRect; const ItemInfo: + TTBXItemInfo; const ACaption: string; AFormat: Cardinal; Rotated: + Boolean); + override; + procedure PaintCheckMark(Canvas: TCanvas; ARect: TRect; const ItemInfo: + TTBXItemInfo); override; + procedure PaintChevron(Canvas: TCanvas; ARect: TRect; const ItemInfo: + TTBXItemInfo); override; + procedure PaintDock(Canvas: TCanvas; const ClientRect, DockRect: TRect; + DockPosition: Integer); override; + procedure PaintDockPanelNCArea(Canvas: TCanvas; R: TRect; const + DockPanelInfo: TTBXDockPanelInfo); override; + procedure PaintDropDownArrow(Canvas: TCanvas; const ARect: TRect; const + ItemInfo: TTBXItemInfo); override; + procedure PaintEditButton(Canvas: TCanvas; const ARect: TRect; var ItemInfo: + TTBXItemInfo; ButtonInfo: TTBXEditBtnInfo); override; + procedure PaintEditFrame(Canvas: TCanvas; const ARect: TRect; var ItemInfo: + TTBXItemInfo; const EditInfo: TTBXEditInfo); override; + procedure PaintFloatingBorder(Canvas: TCanvas; const ARect: TRect; const + WindowInfo: TTBXWindowInfo); override; + procedure PaintFrame(Canvas: TCanvas; const ARect: TRect; const ItemInfo: + TTBXItemInfo); override; + procedure PaintImage(Canvas: TCanvas; ARect: TRect; const ItemInfo: + TTBXItemInfo; ImageList: TCustomImageList; ImageIndex: Integer); override; + procedure PaintMDIButton(Canvas: TCanvas; ARect: TRect; const ItemInfo: + TTBXItemInfo; ButtonKind: Cardinal); override; + procedure PaintMenuItem(Canvas: TCanvas; const ARect: TRect; var ItemInfo: + TTBXItemInfo); override; + procedure PaintMenuItemFrame(Canvas: TCanvas; const ARect: TRect; const + ItemInfo: TTBXItemInfo); override; + procedure PaintPageScrollButton(Canvas: TCanvas; const ARect: TRect; + ButtonType: Integer; Hot: Boolean); override; + procedure PaintPopupNCArea(Canvas: TCanvas; R: TRect; const PopupInfo: + TTBXPopupInfo); override; + procedure PaintSeparator(Canvas: TCanvas; ARect: TRect; ItemInfo: + TTBXItemInfo; Horizontal, LineSeparator: Boolean); override; + procedure PaintToolbarNCArea(Canvas: TCanvas; R: TRect; const ToolbarInfo: + TTBXToolbarInfo); override; + procedure PaintFrameControl(Canvas: TCanvas; R: TRect; Kind, State: Integer; + Params: Pointer); override; + procedure PaintStatusBar(Canvas: TCanvas; R: TRect; Part: Integer); + override; + end; + +{$IFDEF DTM_Package} +function TBXThemeName: shortstring; stdcall; +procedure TBXRegisterTheme(RegisterTheme: boolean); stdcall; +{$ENDIF} + +implementation + +{.$R tbx_glyphs.res} + +uses + TBXUtils, TB2Common, TB2Item, Classes, Controls, Commctrl, Forms, rmkThemes; + +{$IFDEF DTM_Package} +exports + TBXThemeName, + TBXRegisterTheme; + +const + cThemeName = 'Whidbey'; + +function TBXThemeName: shortstring; stdcall; +begin + result := cThemeName; +end; + +procedure TBXRegisterTheme(RegisterTheme: boolean); stdcall; +begin + if RegisterTheme then + RegisterTBXTheme(cThemeName, TTBXWhidbeyTheme) + else + UnregisterTBXTheme(cThemeName); +end; +{$ENDIF} + +var + StockImgList: TImageList; + CounterLock: Integer; + GradientBmp: TBitmap; + gradCol1, gradCol2, gradHandle1, gradHandle2, gradHandle3, gradBL: TColor; + +procedure InitializeStock; +begin + StockImgList := TImageList.Create(nil); + StockImgList.Handle := ImageList_LoadBitmap(HInstance, 'TBXGLYPHS', 16, 0, + clWhite); + GradientBmp := TBitmap.Create; + GradientBmp.PixelFormat := pf24bit; +end; + +procedure FinalizeStock; +begin + GradientBmp.Free; + StockImgList.Free; +end; + +{ TTBXWhidbeyTheme } + +function TTBXWhidbeyTheme.GetBooleanMetrics(Index: Integer): Boolean; +begin + case Index of + TMB_OFFICEXPPOPUPALIGNMENT: Result := True; + TMB_EDITHEIGHTEVEN: Result := False; + TMB_PAINTDOCKBACKGROUND: Result := True; + TMB_SOLIDTOOLBARNCAREA: Result := True; + TMB_SOLIDTOOLBARCLIENTAREA: Result := True; + else + Result := False; + end; +end; + +function TTBXWhidbeyTheme.GetIntegerMetrics(Index: Integer): Integer; +const + DEFAULT = -1; +begin + case Index of + TMI_SPLITBTN_ARROWWIDTH: Result := 12; + + TMI_DROPDOWN_ARROWWIDTH: Result := 8; + TMI_DROPDOWN_ARROWMARGIN: Result := 3; + + TMI_MENU_IMGTEXTSPACE: Result := 3; + TMI_MENU_LCAPTIONMARGIN: Result := 8; + TMI_MENU_RCAPTIONMARGIN: Result := 3; + TMI_MENU_SEPARATORSIZE: Result := 3; + TMI_MENU_MDI_DW: Result := 2; + TMI_MENU_MDI_DH: Result := 2; + + TMI_TLBR_SEPARATORSIZE: Result := DEFAULT; + + TMI_EDIT_MENURIGHTINDENT: Result := 1; + TMI_EDIT_FRAMEWIDTH: Result := 1; + TMI_EDIT_TEXTMARGINHORZ: Result := 2; + TMI_EDIT_TEXTMARGINVERT: Result := 2; + TMI_EDIT_BTNWIDTH: Result := 14; + else + Result := DEFAULT; + end; +end; + +function TTBXWhidbeyTheme.GetViewColor(AViewType: Integer): TColor; +begin + Result := clBtnFace; + if (AViewType and VT_TOOLBAR) = VT_TOOLBAR then + begin + if (AViewType and TVT_MENUBAR) = TVT_MENUBAR then + Result := MenubarColor + else + Result := ToolbarColor; + end + else if (AViewType and VT_POPUP) = VT_POPUP then + begin + if (AViewType and PVT_LISTBOX) = PVT_LISTBOX then + Result := clWindow + else + Result := PopupColor; + end + else if (AViewType and VT_DOCKPANEL) = VT_DOCKPANEL then + Result := DockPanelColor; +end; + +function TTBXWhidbeyTheme.GetBtnColor(const ItemInfo: TTBXItemInfo; ItemPart: + TItemPart): TColor; +const + BFlags1: array[Boolean] of TBtnItemState = (bisDisabled, bisDisabledHot); + BFlags2: array[Boolean] of TBtnItemState = (bisSelected, bisSelectedHot); + BFlags3: array[Boolean] of TBtnItemState = (bisNormal, bisHot); +var + B: TBtnItemState; + Embedded: Boolean; +begin + with ItemInfo do + begin + Embedded := (ViewType and VT_TOOLBAR = VT_TOOLBAR) and + (ViewType and TVT_EMBEDDED = TVT_EMBEDDED); + if not Enabled then + B := BFlags1[HoverKind = hkKeyboardHover] + else if ItemInfo.IsPopupParent then + B := bisPopupParent + else if Pushed then + B := bisPressed + else if Selected then + B := BFlags2[HoverKind <> hkNone] + else + B := BFlags3[HoverKind <> hkNone]; + Result := BtnItemColors[B, ItemPart]; + if Embedded then + begin + if (ItemPart = ipBody) and (Result = clNone) then + Result := ToolbarColor; + if ItemPart = ipFrame then + begin + if Selected then + Result := clWindowFrame + else if (Result = clNone) then + Result := clBtnShadow; + end; + end; + end; +end; + +function TTBXWhidbeyTheme.GetPartColor(const ItemInfo: TTBXItemInfo; + ItemPart: TItemPart): TColor; +const + MFlags1: array[Boolean] of TMenuItemState = (misDisabled, misDisabledHot); + MFlags2: array[Boolean] of TMenuItemState = (misNormal, misHot); + BFlags1: array[Boolean] of TBtnItemState = (bisDisabled, bisDisabledHot); + BFlags2: array[Boolean] of TBtnItemState = (bisSelected, bisSelectedHot); + BFlags3: array[Boolean] of TBtnItemState = (bisNormal, bisHot); +var + IsMenuItem, Embedded: Boolean; + M: TMenuItemState; + B: TBtnItemState; +begin + with ItemInfo do + begin + IsMenuItem := ((ViewType and PVT_POPUPMENU) = PVT_POPUPMENU) and + ((ItemOptions and IO_TOOLBARSTYLE) = 0); + Embedded := ((ViewType and VT_TOOLBAR) = VT_TOOLBAR) and + ((ViewType and TVT_EMBEDDED) = TVT_EMBEDDED); + if IsMenuItem then + begin + if not Enabled then + M := MFlags1[HoverKind = hkKeyboardHover] + else + M := MFlags2[HoverKind <> hkNone]; + Result := MenuItemColors[M, ItemPart]; + end + else + begin + if not Enabled then + B := BFlags1[HoverKind = hkKeyboardHover] + else if ItemInfo.IsPopupParent then + B := bisPopupParent + else if Pushed then + B := bisPressed + else if Selected then + B := BFlags2[HoverKind <> hkNone] + else + B := BFlags3[HoverKind <> hkNone]; + Result := BtnItemColors[B, ItemPart]; + if Embedded and (Result = clNone) then + begin + if ItemPart = ipBody then + Result := ToolbarColor; + if ItemPart = ipFrame then + Result := clBtnShadow; + end; + end; + end; +end; + +{ +procedure GradientFill(const Canvas: TCanvas; const ARect: TRect; + const StartColor, EndColor: TColor; + const Direction: TGradDir); +var + rc1, rc2, gc1, gc2, + bc1, bc2, Counter, GSize: Integer; + Brush: HBrush; +begin + rc1 := GetRValue(ColorToRGB(StartColor)); + gc1 := GetGValue(ColorToRGB(StartColor)); + bc1 := GetBValue(ColorToRGB(StartColor)); + rc2 := GetRValue(ColorToRGB(EndColor)); + gc2 := GetGValue(ColorToRGB(EndColor)); + bc2 := GetBValue(ColorToRGB(EndColor)); + + if Direction = tGTopBottom then + begin + GSize := (ARect.Bottom - ARect.Top) - 1; + if GSize = 0 then + GSize := 1; + for Counter := 0 to GSize do + begin + Brush := CreateSolidBrush( + RGB(Byte(rc1 + (((rc2 - rc1) * (Counter)) div GSize)), + Byte(gc1 + (((gc2 - gc1) * (Counter)) div GSize)), + Byte(bc1 + (((bc2 - bc1) * (Counter)) div GSize)))); + Windows.FillRect(Canvas.Handle, Rect(ARect.Left, ARect.Bottom - Counter - + 1, ARect.Right, ARect.Bottom - Counter), Brush); + DeleteObject(Brush); + end; + end + else + begin + GSize := (ARect.Right - ARect.Left) - 1; + if GSize = 0 then + GSize := 1; + for Counter := 0 to GSize do + begin + Brush := CreateSolidBrush( + RGB(Byte(rc1 + (((rc2 - rc1) * (Counter)) div GSize)), + Byte(gc1 + (((gc2 - gc1) * (Counter)) div GSize)), + Byte(bc1 + (((bc2 - bc1) * (Counter)) div GSize)))); + Windows.FillRect(Canvas.Handle, Rect(ARect.Right - Counter - 1, ARect.Top, + ARect.Right - Counter, ARect.Bottom), Brush); + DeleteObject(Brush); + end; + end; +end; +} + +procedure DrawButtonBitmap(Canvas: TCanvas; R: TRect; Color: TColor); +const +{$IFNDEF SMALL_CLOSE_BUTTON} + Pattern: array[0..15] of Byte = + ($C3, 0, $66, 0, $3C, 0, $18, 0, $3C, 0, $66, 0, $C3, 0, 0, 0); +{$ELSE} + Pattern: array[0..15] of Byte = + (0, 0, $63, 0, $36, 0, $1C, 0, $1C, 0, $36, 0, $63, 0, 0, 0); +{$ENDIF} +var + Bmp: TBitmap; + W, H: Integer; + Index: Integer; +begin + Bmp := TBitmap.Create; + try + Bmp.Handle := CreateBitmap(8, 8, 1, 1, @Pattern); + Index := SaveDC(Canvas.Handle); + Canvas.Brush.Color := Color; + SetTextColor(Canvas.Handle, clBlack); + SetBkColor(Canvas.Handle, clWhite); + W := 8; + H := 7; + with R do + begin + BitBlt(Canvas.Handle, (Left + Right - W + 1) div 2, (Top + Bottom - H) div + 2, W, H, + Bmp.Canvas.Handle, 0, 0, ROP_DSPDxax); + end; + RestoreDC(Canvas.Handle, Index); + finally + Bmp.Free; + end; +end; + +function TTBXWhidbeyTheme.GetItemColor(const ItemInfo: TTBXItemInfo): TColor; +begin + Result := GetPartColor(ItemInfo, ipBody); + if Result = clNone then + Result := GetViewColor(ItemInfo.ViewType); +end; + +function TTBXWhidbeyTheme.GetItemTextColor(const ItemInfo: TTBXItemInfo): + TColor; +begin + Result := GetPartColor(ItemInfo, ipText); +end; + +function TTBXWhidbeyTheme.GetItemImageBackground(const ItemInfo: + TTBXItemInfo): TColor; +begin + Result := GetBtnColor(ItemInfo, ipBody); + if Result = clNone then + result := GetViewColor(ItemInfo.ViewType); +end; + +procedure TTBXWhidbeyTheme.GetViewBorder(ViewType: Integer; out Border: + TPoint); +const + XMetrics: array[Boolean] of Integer = (SM_CXDLGFRAME, SM_CXFRAME); + YMetrics: array[Boolean] of Integer = (SM_CYDLGFRAME, SM_CYFRAME); +var + Resizable: Boolean; + + procedure SetBorder(X, Y: Integer); + begin + Border.X := X; + Border.Y := Y; + end; + +begin + if (ViewType and VT_TOOLBAR) = VT_TOOLBAR then + begin + if (ViewType and TVT_FLOATING) = TVT_FLOATING then + begin + Resizable := (ViewType and TVT_RESIZABLE) = TVT_RESIZABLE; + Border.X := GetSystemMetrics(XMetrics[Resizable]) - 1; + Border.Y := GetSystemMetrics(YMetrics[Resizable]) - 1; + end + else + SetBorder(2, 2); + end + else if (ViewType and VT_POPUP) = VT_POPUP then + begin + if (ViewType and PVT_POPUPMENU) = PVT_POPUPMENU then + Border.X := 1 + else + Border.X := 2; + Border.Y := 2; + end + else if (ViewType and VT_DOCKPANEL) = VT_DOCKPANEL then + begin + if (ViewType and DPVT_FLOATING) = DPVT_FLOATING then + begin + Resizable := (ViewType and DPVT_RESIZABLE) = DPVT_RESIZABLE; + Border.X := GetSystemMetrics(XMetrics[Resizable]) - 1; + Border.Y := GetSystemMetrics(YMetrics[Resizable]) - 1; + end + else + SetBorder(2, 2); + end + else + SetBorder(0, 0); +end; + +procedure TTBXWhidbeyTheme.GetMargins(MarginID: Integer; out Margins: + TTBXMargins); +begin + with Margins do + case MarginID of + MID_TOOLBARITEM: + begin + LeftWidth := 2; + RightWidth := 2; + TopHeight := 2; + BottomHeight := 2; + end; + MID_STATUSPANE: + begin + LeftWidth := 3; + RightWidth := 3; + TopHeight := 1; + BottomHeight := 1; + end; + MID_MENUITEM: + begin + LeftWidth := 1; + RightWidth := 1; + TopHeight := 3; + BottomHeight := 3; + end; + else + LeftWidth := 0; + RightWidth := 0; + TopHeight := 0; + BottomHeight := 0; + end; +end; + +procedure TTBXWhidbeyTheme.PaintBackgnd(Canvas: TCanvas; const ADockRect, + ARect, AClipRect: TRect; + AColor: TColor; Transparent: Boolean; AViewType: Integer); +var + Brush: HBrush; + R: TRect; + IsHoriz: boolean; +begin + if not Transparent then + begin + if ((AViewType and TVT_NORMALTOOLBAR) = TVT_NORMALTOOLBAR) + and (not (AViewType and TVT_EMBEDDED = TVT_EMBEDDED)) + or ((AViewType and TVT_TOOLWINDOW) = TVT_TOOLWINDOW) then + begin + IntersectRect(R, ARect, AClipRect); + if (ADockRect.Top = 0) and + (ADockRect.Left = 0) and + (ADockRect.Right = 0) and + (ADockRect.Bottom = 0) then + IsHoriz := (ARect.Right > ARect.Bottom) + else + IsHoriz := Abs(R.Right - R.Left) > Abs(R.Bottom - R.Top); + if IsHoriz then + begin + R.Top := R.Top - 1; + R.Bottom := R.Bottom + 1; + GradientFill(Canvas, R, gradCol1, gradCol2, TGTopBottom); + R.Bottom := R.Bottom - 1; + R.Top := R.Top + 1; + end + else + begin + R.Left := R.Left - 1; + R.Right := R.Right + 1; + GradientFill(Canvas, R, gradCol1, gradCol2, TGLeftRight); + R.Right := R.Right - 1; + R.Left := R.Left + 1; + end; + end + else + begin + Brush := CreateSolidBrush(ColorToRGB(AColor)); + IntersectRect(R, ARect, AClipRect); + //The rects are compared to determine if we're drawing a toolbar, not a popup menu... + if (ADockRect.Left <> ARect.Left) or (ADockRect.Top <> ARect.Top) + or (ADockRect.Right <> ARect.Right) or (ADockRect.Bottom <> ARect.Bottom) + then + GradientFill(Canvas, R, gradCol2, clBtnFace, TGLeftRight) + else + FillRect(Canvas.Handle, R, Brush); + DeleteObject(Brush); + end; + end; +end; + +procedure TTBXWhidbeyTheme.PaintCaption(Canvas: TCanvas; + const ARect: TRect; const ItemInfo: TTBXItemInfo; const ACaption: string; + AFormat: Cardinal; Rotated: Boolean); +var + R: TRect; +begin + with ItemInfo, Canvas do + begin + R := ARect; + Brush.Style := bsClear; + if Font.Color = clNone then Font.Color := GetPartColor(ItemInfo, ipText); + //Font.Color := GetPartColor(ItemInfo, ipText); + if not Rotated then + Windows.DrawText(Handle, PChar(ACaption), Length(ACaption), R, AFormat) + else + DrawRotatedText(Handle, ACaption, R, AFormat); + Brush.Style := bsSolid; + end; +end; + +procedure TTBXWhidbeyTheme.PaintCheckMark(Canvas: TCanvas; ARect: TRect; const + ItemInfo: TTBXItemInfo); +var + X, Y: Integer; +begin + X := (ARect.Left + ARect.Right) div 2 - 2; + Y := (ARect.Top + ARect.Bottom) div 2 + 1; + Canvas.Pen.Color := GetBtnColor(ItemInfo, ipText); + Canvas.Polyline([Point(X - 2, Y - 2), Point(X, Y), Point(X + 4, Y - 4), + Point(X + 4, Y - 3), Point(X, Y + 1), Point(X - 2, Y - 1), Point(X - 2, Y - + 2)]); +end; + +procedure TTBXWhidbeyTheme.PaintChevron(Canvas: TCanvas; ARect: TRect; const + ItemInfo: TTBXItemInfo); +const + Pattern: array[Boolean, 0..15] of Byte = ( + ($CC, 0, $66, 0, $33, 0, $66, 0, $CC, 0, 0, 0, 0, 0, 0, 0), + ($88, 0, $D8, 0, $70, 0, $20, 0, $88, 0, $D8, 0, $70, 0, $20, 0)); +var + R2: TRect; + Bmp: TBitmap; +begin + R2 := ARect; + PaintButton(Canvas, ARect, ItemInfo); + if not ItemInfo.IsVertical then + begin + R2.Top := 4; + R2.Bottom := R2.Top + 5; + Inc(R2.Left, 2); + R2.Right := R2.Left + 8; + end + else + begin + R2.Left := R2.Right - 9; + R2.Right := R2.Left + 5; + Inc(R2.Top, 2); + R2.Bottom := R2.Top + 8; + end; + Bmp := TBitmap.Create; + try + Bmp.Handle := CreateBitmap(8, 8, 1, 1, @Pattern[ItemInfo.IsVertical]); + Canvas.Brush.Color := GetPartColor(ItemInfo, ipText); + SetTextColor(Canvas.Handle, clBlack); + SetBkColor(Canvas.Handle, clWhite); + with R2 do + BitBlt(Canvas.Handle, Left, Top, Right - Left, + Bottom - Top, Bmp.Canvas.Handle, 0, 0, ROP_DSPDxax); + finally + Bmp.Free; + end; +end; + +procedure TTBXWhidbeyTheme.PaintEditButton(Canvas: TCanvas; const ARect: + TRect; + var ItemInfo: TTBXItemInfo; ButtonInfo: TTBXEditBtnInfo); + +var + BtnDisabled, BtnHot, BtnPressed, Embedded: Boolean; + R, BR: TRect; + X, Y: Integer; + SaveItemInfoPushed: Boolean; + + procedure PaintEnabled(R: TRect; Pressed: Boolean); + var + C: TColor; + begin + if BtnDisabled then + C := GetBtnColor(ItemInfo, ipFrame) + else if BtnHot or BtnPressed then + C := BtnItemColors[bisHot, ipFrame] + else + begin + if Embedded then + c := blend(gradCol1, gradCol2, 90) + else + begin + if (ItemInfo.ViewType and VT_TOOLBAR) <> VT_TOOLBAR then + c := blend(gradCol1, gradCol2, 90) + else + c := clWindow; + end; + end; + if Embedded then + begin + if not (BtnPressed or BtnHot) then + FillRectEx(Canvas.Handle, R, ToolBarColor); + FrameRectEx(Canvas.Handle, R, C, True); + end + else + FrameRectEx(Canvas.Handle, R, C, True); + end; + +begin + R := ARect; + Embedded := ((ItemInfo.ViewType and VT_TOOLBAR) = VT_TOOLBAR) and + ((ItemInfo.ViewType and TVT_EMBEDDED) = TVT_EMBEDDED); + Inc(R.Left); + with Canvas do + if ButtonInfo.ButtonType = EBT_DROPDOWN then + begin + BtnDisabled := (ButtonInfo.ButtonState and EBDS_DISABLED) <> 0; + BtnHot := (ButtonInfo.ButtonState and EBDS_HOT) <> 0; + BtnPressed := (ButtonInfo.ButtonState and EBDS_PRESSED) <> 0; + if not BtnDisabled then + begin + if BtnPressed or BtnHot then + begin + InflateRect(R, 1, 1); + PaintButton(Canvas, R, ItemInfo); + PaintEnabled(R, BtnPressed); + end + else + PaintEnabled(R, BtnPressed); + end; + PaintDropDownArrow(Canvas, R, ItemInfo); + end + else if ButtonInfo.ButtonType = EBT_SPIN then + begin + BtnDisabled := (ButtonInfo.ButtonState and EBSS_DISABLED) <> 0; + BtnHot := (ButtonInfo.ButtonState and EBSS_HOT) <> 0; + BtnPressed := (ButtonInfo.ButtonState and EBSS_UP) <> 0; + + // Upper button + BR := R; + BR.Bottom := (R.Top + R.Bottom + 1) div 2; + SaveItemInfoPushed := ItemInfo.Pushed; + ItemInfo.Pushed := BtnPressed; + if not BtnDisabled then + begin + if BtnPressed or BtnHot then + begin + InflateRect(BR, 1, 1); + PaintButton(Canvas, BR, ItemInfo); + PaintEnabled(BR, BtnPressed); + end + else + PaintEnabled(BR, BtnPressed); + end; + X := (BR.Left + BR.Right) div 2; + Y := (BR.Top + BR.Bottom - 1) div 2; + if (not BtnPressed) then + Pen.Color := GetPartColor(ItemInfo, ipText) + else + Pen.Color := GetPartColor(ItemInfo, ipText); + Brush.Color := Pen.Color; + Polygon([Point(X - 2, Y + 1), Point(X + 2, Y + 1), Point(X, Y - 1)]); + + // Lower button + BR := R; + BR.Top := (R.Top + R.Bottom) div 2; + BtnPressed := (ButtonInfo.ButtonState and EBSS_DOWN) <> 0; + ItemInfo.Pushed := BtnPressed; + if not BtnDisabled then + begin + if BtnPressed or BtnHot then + begin + InflateRect(BR, 1, 1); + BR.Top := BR.Top + 1; + PaintButton(Canvas, BR, ItemInfo); + PaintEnabled(BR, BtnPressed); + end + else + begin + PaintEnabled(BR, BtnPressed); + end; + end; + X := (BR.Left + BR.Right) div 2; + Y := (BR.Top + BR.Bottom) div 2; + if (not BtnPressed) then + Pen.Color := GetPartColor(ItemInfo, ipText) + else + Pen.Color := GetPartColor(ItemInfo, ipText); + Brush.Color := Pen.Color; + Polygon([Point(X - 2, Y - 1), Point(X + 2, Y - 1), Point(X, Y + 1)]); + ItemInfo.Pushed := SaveItemInfoPushed; + end; +end; + +procedure TTBXWhidbeyTheme.PaintEditFrame(Canvas: TCanvas; + const ARect: TRect; var ItemInfo: TTBXItemInfo; const EditInfo: TTBXEditInfo); +var + R: TRect; + W: Integer; + Embedded: Boolean; +begin + R := ARect; + if ItemInfo.HoverKind <> hkNone then + FrameRectEx(Canvas.Handle, R, BtnItemColors[bisHot, ipFrame], true); + W := EditFrameWidth; + InflateRect(R, -W, -W); + Embedded := ((ItemInfo.ViewType and VT_TOOLBAR) = VT_TOOLBAR) and + ((ItemInfo.ViewType and TVT_EMBEDDED) = TVT_EMBEDDED); + if not (ItemInfo.Enabled or Embedded) then + FrameRectEx(Canvas.Handle, R, BtnItemColors[bisDisabled, ipText], true); + + with EditInfo do + if RightBtnWidth > 0 then + Dec(R.Right, RightBtnWidth - 2); + + if ItemInfo.Enabled then + begin + if ItemInfo.HoverKind = hkNone then + if Embedded then + FrameRectEx(Canvas.Handle, R, blend(gradCol1, gradCol2, 90), True) + else + FrameRectEx(Canvas.Handle, R, clWindow, True) + else + begin + Canvas.Brush.Color := clWindow; + Canvas.FrameRect(R); + end; + end; + if ItemInfo.Enabled then + begin + Canvas.Brush.Color := clWindow; + Canvas.FillRect(R); + if ((ItemInfo.ViewType and VT_TOOLBAR) <> VT_TOOLBAR) and + (GetPartColor(ItemInfo, ipFrame) = clNone) then + begin + Canvas.Brush.Color := blend(gradCol1, gradCol2, 90); + R := ARect; + InflateRect(R, -1, -1); + Canvas.FrameRect(R); + end; + end; + + if EditInfo.RightBtnWidth > 0 then + begin + R := ARect; + InflateRect(R, -W, -W); + R.Left := R.Right - EditInfo.RightBtnWidth; + PaintEditButton(Canvas, R, ItemInfo, EditInfo.RightBtnInfo); + end; +end; + +procedure TTBXWhidbeyTheme.PaintDropDownArrow(Canvas: TCanvas; + const ARect: TRect; const ItemInfo: TTBXItemInfo); +var + X, Y: Integer; +begin + with ARect, Canvas do + begin + X := (Left + Right) div 2; + Y := (Top + Bottom) div 2 - 1; + Pen.Color := GetPartColor(ItemInfo, ipText); + Brush.Color := Pen.Color; + if ItemInfo.IsVertical then + Polygon([Point(X, Y + 2), Point(X, Y - 2), Point(X - 2, Y)]) + else + Polygon([Point(X - 2, Y), Point(X + 2, Y), Point(X, Y + 2)]); + end; +end; + +procedure TTBXWhidbeyTheme.PaintButton(Canvas: TCanvas; const ARect: TRect; + const ItemInfo: TTBXItemInfo); +var + R: TRect; +begin + with ItemInfo, Canvas do + begin + R := ARect; + + if ((ItemOptions and IO_DESIGNING) <> 0) and not Selected then + begin + Brush.Color := clRed; + if ComboPart = cpSplitRight then + Dec(R.Left); + FrameRect(R); + end + else + begin + if ((ItemInfo.ViewType and TVT_EMBEDDED) <> 0) and (HoverKind = hkNone) + then + FrameRectEx(Canvas.Handle, R, GetBtnColor(ItemInfo, ipFrame), true) + else + FrameRectEx(Canvas.Handle, R, GetBtnColor(ItemInfo, ipFrame), true); + if (ComboPart = cpSplitLeft) and IsPopupParent then + Inc(R.Right); + if ComboPart = cpSplitRight then + Dec(R.Left); + + if (Selected) and ((ViewType and VT_TOOLBAR) = VT_TOOLBAR) then + begin + if (HoverKind <> hkNone) then + begin + if Pushed then + FillRectEx(Canvas.Handle, R, GetBtnColor(ItemInfo, ipBody)) + else +{$IFDEF ALT_VISUAL_STYLE} + FillRectEx(Canvas.Handle, R, Blend($0080E0FF, $002090E8, 50)); +{$ELSE} + FillRectEx(Canvas.Handle, R, GetBtnColor(ItemInfo, ipBody)); +{$ENDIF} + end + else +{$IFDEF ALT_VISUAL_STYLE} + GradientFill(Canvas, R, $0080E0FF, $002090E8, TGTopBottom); +{$ELSE} + FillRectEx(Canvas.Handle, R, GetBtnColor(ItemInfo, ipBody)); +{$ENDIF} + end + else + if ((ViewType and TVT_MENUBAR) = TVT_MENUBAR) and (HoverKind <> + hkNone) + then + begin + FillRectEx(Canvas.Handle, R, GetBtnColor(ItemInfo, ipBody)); + //GradientFill(Canvas, R, gradCol1, gradCol2, TGTopBottom); + end + else + FillRectEx(Canvas.Handle, R, GetBtnColor(ItemInfo, ipBody)); + end; + if ComboPart = cpSplitRight then + PaintDropDownArrow(Canvas, R, ItemInfo); + end; +end; + +procedure TTBXWhidbeyTheme.PaintFloatingBorder(Canvas: TCanvas; const ARect: + TRect; + const WindowInfo: TTBXWindowInfo); +const + WinStates: array[Boolean] of TWinFramestate = (wfsInactive, wfsActive); + + function GetBtnItemState(BtnState: Integer): TBtnItemState; + begin + if not WindowInfo.Active then + Result := bisDisabled + else if (BtnState and CDBS_PRESSED) <> 0 then + Result := bisPressed + else if (BtnState and CDBS_HOT) <> 0 then + Result := bisHot + else + Result := bisNormal; + end; + +var + WinState: TWinFrameState; + BtnItemState: TBtnItemState; + SaveIndex, X, Y: Integer; + Sz: TPoint; + R: TRect; + BodyColor, CaptionColor, CaptionText: TColor; + IsDockPanel: Boolean; + + procedure DrawGlyph(C: TColor); + var + Bmp: TBitmap; + DC: HDC; + begin + Bmp := TBitmap.Create; + try + Bmp.Monochrome := True; + StockImgList.GetBitmap(0, Bmp); + Canvas.Brush.Color := C; + DC := Canvas.Handle; + SetTextColor(DC, clBlack); + SetBkColor(DC, clWhite); + BitBlt(DC, X, Y, StockImgList.Width, StockImgList.Height, + Bmp.Canvas.Handle, 0, 0, ROP_DSPDxax); + finally + Bmp.Free; + end; + end; + +begin + with Canvas do + begin + WinState := WinStates[WindowInfo.Active]; + IsDockPanel := (WindowInfo.ViewType and VT_DOCKPANEL) = VT_DOCKPANEL; + BodyColor := Brush.Color; + + if (WRP_BORDER and WindowInfo.RedrawPart) <> 0 then + begin + R := ARect; + + if not IsDockPanel then + Brush.Color := WinFrameColors[WinState, wfpBorder] + else + Brush.Color := PnlFrameColors[WinState, wfpBorder]; + SaveIndex := SaveDC(Canvas.Handle); + Sz := WindowInfo.FloatingBorderSize; + with R, Sz do + ExcludeClipRect(Canvas.Handle, Left + X, Top + Y, Right - X, Bottom - + Y); + FillRect(R); + RestoreDC(Canvas.Handle, SaveIndex); + InflateRect(R, -Sz.X, -Sz.Y); + Pen.Color := BodyColor; + with R do + if not IsDockPanel then + Canvas.Polyline([ + Point(Left, Top - 1), Point(Right - 1, Top - 1), + Point(Right, Top), Point(Right, Bottom - 1), + Point(Right - 1, Bottom), + Point(Left, Bottom), Point(Left - 1, Bottom - 1), + Point(Left - 1, Top), Point(Left, Top - 1) + ]) + else + Canvas.Polyline([ + Point(Left, Top - 1), Point(Right - 1, Top - 1), + Point(Right, Top), Point(Right, Bottom), + Point(Left - 1, Bottom), + Point(Left - 1, Top), Point(Left, Top - 1) + ]); + end; + + if not WindowInfo.ShowCaption then + Exit; + + if (WindowInfo.ViewType and VT_TOOLBAR) = VT_TOOLBAR then + begin + CaptionColor := WinFrameColors[WinState, wfpCaption]; + CaptionText := WinFrameColors[WinState, wfpCaptionText]; + end + else + begin + CaptionColor := PnlFrameColors[WinState, wfpCaption]; + CaptionText := PnlFrameColors[WinState, wfpCaptionText]; + end; + + { Caption } + if (WRP_CAPTION and WindowInfo.RedrawPart) <> 0 then + begin + R := Rect(0, 0, WindowInfo.ClientWidth, GetSystemMetrics(SM_CYSMCAPTION) - + 1); + with WindowInfo.FloatingBorderSize do + OffsetRect(R, X, Y); + DrawLineEx(Canvas.Handle, R.Left, R.Bottom, R.Right, R.Bottom, BodyColor); + + if ((CDBS_VISIBLE and WindowInfo.CloseButtonState) <> 0) and + ((WRP_CLOSEBTN and WindowInfo.RedrawPart) <> 0) then + Dec(R.Right, GetSystemMetrics(SM_CYSMCAPTION) - 1); + + Brush.Color := CaptionColor; + FillRect(R); + InflateRect(R, -2, 0); + Font.Assign(SmCaptionFont); + Font.Color := CaptionText; + DrawText(Canvas.Handle, WindowInfo.Caption, -1, R, + DT_SINGLELINE or DT_VCENTER or DT_END_ELLIPSIS or DT_HIDEPREFIX); + end; + + { Close button } + if (CDBS_VISIBLE and WindowInfo.CloseButtonState) <> 0 then + begin + R := Rect(0, 0, WindowInfo.ClientWidth, GetSystemMetrics(SM_CYSMCAPTION) - + 1); + with WindowInfo.FloatingBorderSize do + OffsetRect(R, X, Y); + R.Left := R.Right - (R.Bottom - R.Top); + DrawLineEx(Canvas.Handle, R.Left - 1, R.Bottom, R.Right, R.Bottom, + BodyColor); + Brush.Color := CaptionColor; + FillRect(R); + with R do + begin + X := (Left + Right - StockImgList.Width + 1) div 2; + Y := (Top + Bottom - StockImgList.Height) div 2; + end; + BtnItemState := GetBtnItemState(WindowInfo.CloseButtonState); + FrameRectEx(Canvas.Handle, R, BtnItemColors[BtnItemState, ipFrame], True); + if FillRectEx(Canvas.Handle, R, BtnItemColors[BtnItemState, ipBody]) then + DrawGlyph(BtnItemColors[BtnItemState, ipText]) + else + DrawGlyph(CaptionText); + end; + end; +end; + +procedure TTBXWhidbeyTheme.PaintFrame(Canvas: TCanvas; const ARect: TRect; + const ItemInfo: TTBXItemInfo); +var + R: TRect; +begin + R := ARect; + with ItemInfo do + if Enabled and (HoverKind <> hkNone) then + FillRectEx(Canvas.Handle, R, GetPartColor(ItemInfo, ipBody)); + FrameRectEx(Canvas.Handle, R, GetPartColor(ItemInfo, ipFrame), True); +end; + +function TTBXWhidbeyTheme.GetImageOffset(Canvas: TCanvas; + const ItemInfo: TTBXItemInfo; ImageList: TCustomImageList): TPoint; +begin + Result.X := 0; + if not (ImageList is TTBCustomImageList) then + with ItemInfo do + if Enabled and (HoverKind <> hkNone) and + not (Selected or Pushed and not IsPopupParent) then + Result.X := -1; + Result.Y := Result.X +end; + +procedure TTBXWhidbeyTheme.PaintImage(Canvas: TCanvas; ARect: TRect; + const ItemInfo: TTBXItemInfo; ImageList: TCustomImageList; ImageIndex: + Integer); +var + HiContrast: Boolean; +begin + with ItemInfo do + begin + if ImageList is TTBCustomImageList then + begin + TTBCustomImageList(ImageList).DrawState(Canvas, ARect.Left, ARect.Top, + ImageIndex, Enabled, (HoverKind <> hkNone), Selected); + Exit; + end; + + HiContrast := ColorIntensity(GetItemImageBackground(ItemInfo)) < 80; + if not Enabled then + begin + if not HiContrast then + DrawTBXIconShadow(Canvas, ARect, ImageList, ImageIndex, 0) + else + DrawTBXIconFlatShadow(Canvas, ARect, ImageList, ImageIndex, + clBtnShadow); + end + else if Selected or Pushed or (HoverKind <> hkNone) then + begin + if not (Selected or Pushed and not IsPopupParent) then + begin + end; + DrawTBXIcon(Canvas, ARect, ImageList, ImageIndex, HiContrast); + end + else if HiContrast or TBXHiContrast or TBXLoColor then + DrawTBXIcon(Canvas, ARect, ImageList, ImageIndex, HiContrast) + else + HighlightTBXIcon(Canvas, ARect, ImageList, ImageIndex, clWindow, 255); + end; +end; + +procedure TTBXWhidbeyTheme.PaintMDIButton(Canvas: TCanvas; ARect: TRect; + const ItemInfo: TTBXItemInfo; ButtonKind: Cardinal); +var + Index: Integer; + X, Y: Integer; + Bmp: TBitmap; +begin + PaintButton(Canvas, ARect, ItemInfo); + with ARect do + begin + X := (Left + Right - StockImgList.Width) div 2; + Y := (Top + Bottom - StockImgList.Height) div 2; + end; + case ButtonKind of + DFCS_CAPTIONMIN: Index := 2; + DFCS_CAPTIONRESTORE: Index := 3; + DFCS_CAPTIONCLOSE: Index := 0; + else + Exit; + end; + Bmp := TBitmap.Create; + Bmp.Monochrome := True; + StockImgList.GetBitmap(Index, Bmp); + Canvas.Brush.Color := GetPartColor(ItemInfo, ipText); + SetTextColor(Canvas.Handle, clBlack); + SetBkColor(Canvas.Handle, clWhite); + BitBlt(Canvas.Handle, X, Y, StockImgList.Width, StockImgList.Height, + Bmp.Canvas.Handle, 0, 0, ROP_DSPDxax); + Bmp.Free; +end; + +procedure TTBXWhidbeyTheme.PaintMenuItemFrame(Canvas: TCanvas; + const ARect: TRect; const ItemInfo: TTBXItemInfo); +var + R: TRect; +begin + R := ARect; + if ((ItemInfo.ViewType and PVT_TOOLBOX) <> PVT_TOOLBOX) then + begin + R.Right := R.Left + ItemInfo.PopupMargin + 2; + GradientFill(Canvas, R, gradCol1, gradCol2, TGLeftRight); + Inc(R.Left); + R.Right := ARect.Right - 1; + end; + PaintFrame(Canvas, R, ItemInfo); +end; + +procedure TTBXWhidbeyTheme.PaintMenuItem(Canvas: TCanvas; const ARect: TRect; + var ItemInfo: TTBXItemInfo); +var + R, R2: TRect; + X, Y, I: Integer; + ArrowWidth: Integer; + ClrText: TColor; + + procedure DrawArrow(AColor: TColor); + begin + Canvas.Pen.Color := AColor; + Canvas.Brush.Color := AColor; + Canvas.Polygon([Point(X, Y - 3), Point(X, Y + 3), Point(X + 3, Y)]); + end; + +begin + with Canvas, ItemInfo do + begin + ArrowWidth := GetSystemMetrics(SM_CXMENUCHECK); + ClrText := GetPartColor(ItemInfo, ipText); + + R := ARect; + PaintMenuItemFrame(Canvas, R, ItemInfo); + if (ItemOptions and IO_COMBO) <> 0 then + begin + X := R.Right - ArrowWidth - 1; + if not ItemInfo.Enabled then + Pen.Color := ClrText + else if HoverKind = hkMouseHover then + Pen.Color := GetPartColor(ItemInfo, ipFrame) + else + Pen.Color := PopupSeparatorColor; + MoveTo(X, R.Top + 1); + LineTo(X, R.Bottom - 1); + end; + + if (ItemOptions and IO_SUBMENUITEM) <> 0 then + begin + Y := ARect.Bottom div 2; + X := ARect.Right - ArrowWidth * 2 div 3 - 1; + DrawArrow(ClrText); + end; + + if Selected and Enabled then + begin + R2 := ARect; + if HoverKind = hkNone then + begin + InflateRect(R2, -1, -1); + i := 2; + R := R2; + R.Left := R2.Left + 1; + R.Right := R.Left + ItemInfo.PopupMargin - i; + FrameRectEx(Canvas.Handle, R, GetBtnColor(ItemInfo, ipFrame), True); +{$IFDEF ALT_VISUAL_STYLE} + GradientFill(Canvas, R, $0080E0FF, $002090E8, TGTopBottom) +{$ELSE} + FillRectEx(Canvas.Handle, R, GetBtnColor(ItemInfo, ipBody)) +{$ENDIF} + end + else + begin +{$IFDEF ALT_VISUAL_STYLE} + i := 0; +{$ELSE} + InflateRect(R2, -1, -1); + i := 2; +{$ENDIF} + R := R2; + R.Left := R2.Left + 1; + R.Right := R.Left + ItemInfo.PopupMargin - i; + FrameRectEx(Canvas.Handle, R, GetBtnColor(ItemInfo, ipFrame), True); +{$IFDEF ALT_VISUAL_STYLE} + FillRectEx(Canvas.Handle, R, Blend($0080E0FF, $002090E8, 50)); +{$ELSE} + FillRectEx(Canvas.Handle, R, GetBtnColor(ItemInfo, ipBody)); +{$ENDIF} + end; + end; + end; +end; + +procedure TTBXWhidbeyTheme.PaintPopupNCArea(Canvas: TCanvas; R: TRect; const + PopupInfo: TTBXPopupInfo); +var + PR: TRect; +begin + with Canvas do + begin + Brush.Color := PopupFrameColor; + FrameRect(R); + InflateRect(R, -1, -1); + Brush.Color := PopupColor; + FillRect(R); + + if not IsRectEmpty(PopupInfo.ParentRect) then + begin + PR := PopupInfo.ParentRect; + if not IsRectEmpty(PR) then + with PR do + begin + Pen.Color := PopupColor;//ToolbarColor; + if Bottom = R.Top then + begin + if Left <= R.Left then + Left := R.Left - 1; + if Right >= R.Right then + Right := R.Right + 1; + MoveTo(Left + 1, Bottom - 1); + LineTo(Right - 1, Bottom - 1); + end + else if Top = R.Bottom then + begin + if Left <= R.Left then + Left := R.Left - 1; + if Right >= R.Right then + Right := R.Right + 1; + MoveTo(Left + 1, Top); + LineTo(Right - 1, Top); + end; + if Right = R.Left then + begin + if Top <= R.Top then + Top := R.Top - 1; + if Bottom >= R.Bottom then + Bottom := R.Bottom + 1; + MoveTo(Right - 1, Top + 1); + LineTo(Right - 1, Bottom - 1); + end + else if Left = R.Right then + begin + if Top <= R.Top then + Top := R.Top - 1; + if Bottom >= R.Bottom then + Bottom := R.Bottom + 1; + MoveTo(Left, Top + 1); + LineTo(Left, Bottom - 1); + end; + end; + end; + end; +end; + +procedure TTBXWhidbeyTheme.PaintSeparator(Canvas: TCanvas; ARect: TRect; + ItemInfo: TTBXItemInfo; Horizontal, LineSeparator: Boolean); +var + IsToolbox: Boolean; + R: TRect; +begin + with ItemInfo, ARect, Canvas do + begin + if Horizontal then + begin + IsToolbox := (ViewType and PVT_TOOLBOX) = PVT_TOOLBOX; + if ((ItemOptions and IO_TOOLBARSTYLE) = 0) and not IsToolBox then + begin + R := ARect; + R.Right := ItemInfo.PopupMargin + 2; + GradientFill(Canvas, R, gradCol1, gradCol2, TGLeftRight); + Inc(Left, ItemInfo.PopupMargin + 9); + Pen.Color := PopupSeparatorColor; + end + else + Pen.Color := ToolbarSeparatorColor; + + if not enabled then + exit; + + if (ItemInfo.ViewType and VT_TOOLBAR) = VT_TOOLBAR then + begin + Top := Bottom div 2; + Left := Left + 4; + Right := Right - 2; + Bottom := Top + 1; + DrawLineEx(Canvas.Handle, Left, Top, Right, Top, clBtnHighLight); + Top := Top - 1; + Left := Left - 1; + Right := Right - 1; + DrawLineEx(Canvas.Handle, Left, Top, Right, Top, + ToolbarSeparatorColor); + end + else + begin + Top := Bottom div 2; + Left := Left + 1; + Right := Right - 1; + Bottom := Top + 1; + DrawLineEx(Canvas.Handle, Left, Top, Right, Top, PopupSeparatorColor); + end; + end + else + if enabled then + begin + Top := Top + 4; + Bottom := Bottom - 2; + Left := Right div 2; + DrawLineEx(Canvas.Handle, Left, Top, Left, Bottom, clBtnHighLight); + Top := Top - 1; + Left := Left - 1; + Bottom := Bottom - 1; + DrawLineEx(Canvas.Handle, Left, Top, Left, Bottom, + ToolbarSeparatorColor); + end; + end; +end; + +procedure TTBXWhidbeyTheme.PaintToolbarNCArea(Canvas: TCanvas; R: TRect; + const ToolbarInfo: TTBXToolbarInfo); +const + DragHandleOffsets: array[Boolean, DHS_DOUBLE..DHS_SINGLE] of Integer = ((2, 0, + 1), (5, 0, 5)); + + function GetBtnItemState(BtnState: Integer): TBtnItemState; + begin + if (BtnState and CDBS_PRESSED) <> 0 then + Result := bisPressed + else if (BtnState and CDBS_HOT) <> 0 then + Result := bisHot + else + Result := bisNormal; + end; + +var + Sz: Integer; + R2: TRect; + C: TColor; + Hi1, Lo1, Hi2, Lo2, Hi3, Lo3, Hi4: TColor; + I: Integer; + BtnVisible, Horz: Boolean; + BtnItemState: TBtnItemState; +begin + with Canvas do + begin + if ((ToolbarInfo.ViewType and TVT_NORMALTOOLBAR) = TVT_NORMALTOOLBAR) + or (ToolbarInfo.ViewType = VT_TOOLBAR) + or ((ToolbarInfo.ViewType and TVT_TOOLWINDOW) = TVT_TOOLWINDOW) then + begin + with R do + begin + if (Toolbarinfo.IsVertical) then + begin + GradientFill(Canvas, R, gradCol1, gradCol2, TGLeftRight); + R2 := R; + R2.Top := R2.Bottom - 1; + + if ToolbarInfo.BorderStyle <> bsSingle then exit; + + GradientFill(Canvas, R2, gradCol1, gradCol2, TGLeftRight); + + Pen.Color := gradBL; + MoveTo(Right - 1, Top + 1); + LineTo(Right - 1, Bottom - 1); + + MoveTo(Left + 1, Bottom - 1); + LineTo(Right - 1, Bottom - 1); + + Pen.Color := gradCol1; + MoveTo(Left, Top); + LineTo(Left, Top + 1); + + MoveTo(Left, Bottom - 2); + LineTo(Left, Bottom); + end + else + begin + GradientFill(Canvas, R, gradCol1, gradCol2, TGTopBottom); + R2 := R; + R2.Top:= R.Top + 1; + R2.Left := R2.Right - 1; + + if ToolbarInfo.BorderStyle <> bsSingle then exit; + + GradientFill(Canvas, R2, GradBL, Blend(gradCol1, gradCol2, 50), TGTopBottom); + + + Pen.Color := gradBL; + MoveTo(Left + 1, Bottom - 1); + LineTo(Right - 1, Bottom - 1); + + Pixels[Left, Top]:= Blend(gradCol1, gradCol2, 60); + Pixels[Left, Bottom - 1]:= gradCol1; + Pixels[Left, Bottom - 2]:= Blend(gradCol1, gradBL, 50); + + Pixels[Right - 2, Top]:= Blend(gradCol1, gradCol2, 25); + Pixels[Right - 1, Bottom - 1]:= gradCol1; + Pixels[Right - 2, Bottom - 2]:= Blend(gradCol1, gradBL, 50); + end; + end; + InflateRect(R, -2, -2); + end + else + begin + GradientFill(Canvas, R, gradCol2, clBtnFace, TGLeftRight); + InflateRect(R, -2, -2); + end; + + if not ToolbarInfo.AllowDrag then + Exit; + + BtnVisible := (ToolbarInfo.CloseButtonState and CDBS_VISIBLE) <> 0; + Sz := GetTBXDragHandleSize(ToolbarInfo); + Horz := not ToolbarInfo.IsVertical; + if Horz then + R.Right := R.Left + Sz + else + R.Bottom := R.Top + Sz; + + // Drag Handle + c := gradHandle1; + Brush.Color := c; + Hi1 := GetNearestColor(Handle, MixColors(c, gradHandle2, 64)); + Lo1 := GetNearestColor(Handle, MixColors(c, gradHandle2, 48)); + Hi2 := GetNearestColor(Handle, MixColors(c, gradHandle2, 32)); + Lo2 := GetNearestColor(Handle, MixColors(c, gradHandle2, 16)); + Hi3 := GetNearestColor(Handle, MixColors(c, gradHandle3, 128)); + Lo3 := GetNearestColor(Handle, MixColors(c, gradHandle3, 96)); + Hi4 := GetNearestColor(Handle, MixColors(c, gradHandle3, 72)); + + if ToolbarInfo.DragHandleStyle <> DHS_NONE then + begin + R2 := R; + if ToolbarInfo.DragHandleStyle = DHS_DOUBLE then + if Horz then + OffsetRect(R2, -2, 0) + else + OffsetRect(R2, 0, -2); + if Horz then + begin + Inc(R2.Top, 4); + Dec(R2.Bottom, 2); + Inc(R2.Left, 1); + if BtnVisible then + begin + Inc(R2.Top, Sz - 2); + Inc(R2.Left, 4); + Dec(R2.Right, 4); + end; + i := R2.Top; + while (i < R2.Bottom - 3) do + begin + Pixels[R2.Left, i] := Hi1; + Pixels[R2.Left, i + 1] := Hi2; + Pixels[R2.Left + 1, i] := Lo1; + Pixels[R2.Left + 1, i + 1] := Lo2; + Pixels[R2.Left + 1, i + 2] := Hi4; + Pixels[R2.Left + 2, i + 2] := Hi3; + Pixels[R2.Left + 2, i + 1] := Lo3; + if ToolbarInfo.DragHandleStyle = DHS_DOUBLE then + begin + Pixels[R2.Left + 4, i] := Hi1; + Pixels[R2.Left + 4, i + 1] := Hi2; + Pixels[R2.Left + 4 + 1, i] := Lo1; + Pixels[R2.Left + 4 + 1, i + 1] := Lo2; + Pixels[R2.Left + 4 + 1, i + 2] := Hi4; + Pixels[R2.Left + 4 + 2, i + 2] := Hi3; + Pixels[R2.Left + 4 + 2, i + 1] := Lo3; + end; + Inc(i, 4); + end; + end + else + begin + Inc(R2.Left, 4); + Dec(R2.Right, 2); + Inc(R2.Top, 1); + if BtnVisible then + begin + Dec(R2.Right, Sz - 2); + Inc(R2.Top, 4); + Dec(R2.Bottom, 4); + end; + i := R2.Left; + while (i < R2.Right - 3) do + begin + Pixels[i, R2.Top] := Hi1; + Pixels[i, R2.Top + 1] := Hi2; + Pixels[i + 1, R2.Top] := Lo1; + Pixels[i + 1, R2.Top + 1] := Lo2; + Pixels[i + 1, R2.Top + 2] := Hi4; + Pixels[i + 2, R2.Top + 2] := Hi3; + Pixels[i + 2, R2.Top + 1] := Lo3; + if ToolbarInfo.DragHandleStyle = DHS_DOUBLE then + begin + Pixels[i, R2.Top + 4] := Hi1; + Pixels[i, R2.Top + 1 + 4] := Hi2; + Pixels[i + 1, R2.Top + 4] := Lo1; + Pixels[i + 1, R2.Top + 1 + 4] := Lo2; + Pixels[i + 1, R2.Top + 2 + 4] := Hi4; + Pixels[i + 2, R2.Top + 2 + 4] := Hi3; + Pixels[i + 2, R2.Top + 1 + 4] := Lo3; + end; + Inc(i, 4); + end; + end; + end; + + // Close button + if BtnVisible then + begin + R2 := R; + if Horz then + begin + Dec(R2.Right); + R2.Bottom := R2.Top + R2.Right - R2.Left; + end + else + begin + Dec(R2.Bottom); + R2.Left := R2.Right - R2.Bottom + R2.Top; + end; + + BtnItemState := GetBtnItemState(ToolbarInfo.CloseButtonState); + FrameRectEx(Canvas.Handle, R2, BtnItemColors[BtnItemState, ipFrame], + True); + FillRectEx(Canvas.Handle, R2, BtnItemColors[BtnItemState, ipBody]); + DrawButtonBitmap(Canvas, R2, BtnItemColors[BtnItemState, ipText]); + end; + end; +end; + +procedure TTBXWhidbeyTheme.PaintDockPanelNCArea(Canvas: TCanvas; R: TRect; + const DockPanelInfo: TTBXDockPanelInfo); + + function GetBtnItemState(BtnState: Integer): TBtnItemState; + begin + if (BtnState and CDBS_PRESSED) <> 0 then + Result := bisPressed + else if (BtnState and CDBS_HOT) <> 0 then + Result := bisHot + else + Result := bisNormal; + end; + +var + C: TColor; +{$IFDEF ALT_HEADER_STYLE} + Hi1, Lo1, Hi2, Lo2, Hi3, Lo3, Hi4: TColor; + i: integer; +{$ENDIF} + Sz, Flags: Integer; + R2: TRect; + BtnItemState: TBtnItemState; +begin + with Canvas, DockPanelInfo do + begin + C := Brush.Color; // Dock panel passes its body color in Canvas.Brush + R2 := R; + + FrameRectEx(Canvas.Handle, R, clBtnFace, True); + FrameRectEx(Canvas.Handle, R, C, True); + with R do + begin + Pixels[Left, Top] := clBtnFace; + if IsVertical then + Pixels[Right - 1, Top] := clBtnFace + else + Pixels[Left, Bottom - 1] := clBtnFace; + end; + + R := R2; + InflateRect(R, -BorderSize.X, -BorderSize.Y); + Sz := GetSystemMetrics(SM_CYSMCAPTION); +{$IFDEF ALT_HEADER_STYLE} + C := clBtnShadow; + if IsVertical then + begin + R.Bottom := R.Top + Sz - 1; + GradientFill(Canvas, R, gradCol1, gradCol2, TGTopBottom); + DrawLineEx(Canvas.Handle, R.Left, R.Bottom, R.Right, R.Bottom, C); + end + else + begin + R.Right := R.Left + Sz - 1; + GradientFill(Canvas, R, gradCol1, gradCol2, TGLeftRight); + DrawLineEx(Canvas.Handle, R.Right, R.Top, R.Right, R.Bottom, C); + end; +{$ELSE} + if IsVertical then + begin + R.Bottom := R.Top + Sz; + GradientFill(Canvas, R, gradCol2, clBtnFace, TGLeftRight); + end + else + begin + R.Right := R.Left + Sz; + GradientFill(Canvas, R, gradCol2, clBtnFace, TGTopBottom); + end; +{$ENDIF} + + if (CDBS_VISIBLE and CloseButtonState) <> 0 then + begin + R2 := R; + if IsVertical then + begin + R2.Left := R2.Right - Sz + 1; + R.Right := R2.Left; + end + else + begin + R2.Top := R2.Bottom - Sz + 1; + R.Bottom := R2.Top; + end; + BtnItemState := GetBtnItemState(CloseButtonState); + FrameRectEx(Canvas.Handle, R2, BtnItemColors[BtnItemState, ipFrame], + True); + FillRectEx(Canvas.Handle, R2, BtnItemColors[BtnItemState, ipBody]); + DrawButtonBitmap(Canvas, R2, BtnItemColors[BtnItemState, ipText]); + end; + +{$IFDEF ALT_HEADER_STYLE} + c := gradHandle1; + Hi1 := GetNearestColor(Handle, MixColors(c, gradHandle2, 64)); + Lo1 := GetNearestColor(Handle, MixColors(c, gradHandle2, 48)); + Hi2 := GetNearestColor(Handle, MixColors(c, gradHandle2, 32)); + Lo2 := GetNearestColor(Handle, MixColors(c, gradHandle2, 16)); + Hi3 := GetNearestColor(Handle, MixColors(c, gradHandle3, 128)); + Lo3 := GetNearestColor(Handle, MixColors(c, gradHandle3, 96)); + Hi4 := GetNearestColor(Handle, MixColors(c, gradHandle3, 72)); + R2 := R; + if IsVertical then + begin + Inc(R2.Top, 2); + Dec(R2.Bottom, 2); + Inc(R2.Left, 1); + i := R2.Top; + while (i < R2.Bottom - 1) do + begin + Pixels[R2.Left, i] := Hi1; + Pixels[R2.Left, i + 1] := Hi2; + Pixels[R2.Left + 1, i] := Lo1; + Pixels[R2.Left + 1, i + 1] := Lo2; + Pixels[R2.Left + 1, i + 2] := Hi4; + Pixels[R2.Left + 2, i + 2] := Hi3; + Pixels[R2.Left + 2, i + 1] := Lo3; + Inc(i, 4); + end; + end + else + begin + Inc(R2.Left, 2); + Dec(R2.Right, 2); + Inc(R2.Top, 1); + i := R2.Left; + while (i < R2.Right - 1) do + begin + Pixels[i, R2.Top] := Hi1; + Pixels[i, R2.Top + 1] := Hi2; + Pixels[i + 1, R2.Top] := Lo1; + Pixels[i + 1, R2.Top + 1] := Lo2; + Pixels[i + 1, R2.Top + 2] := Hi4; + Pixels[i + 2, R2.Top + 2] := Hi3; + Pixels[i + 2, R2.Top + 1] := Lo3; + Inc(i, 4); + end; + end; + if IsVertical then + InflateRect(R, -9, 0) + else + InflateRect(R, 0, -9); +{$ELSE} + if IsVertical then + InflateRect(R, -4, 0) + else + InflateRect(R, 0, -4); +{$ENDIF} + Font.Assign(SmCaptionFont); + Font.Color := clBtnText; + Brush.Style := bsClear; + Flags := DT_SINGLELINE or DT_VCENTER or DT_END_ELLIPSIS or DT_HIDEPREFIX; + if IsVertical then + DrawText(Canvas.Handle, Caption, -1, R, Flags) + else + DrawRotatedText(Canvas.Handle, string(Caption), R, Flags); + end; +end; + +procedure TTBXWhidbeyTheme.PaintDock(Canvas: TCanvas; const ClientRect, + DockRect: TRect; DockPosition: Integer); +begin + GradientFill(Canvas, DockRect, gradCol2, clBtnFace, TGLeftRight); +end; + +procedure TTBXWhidbeyTheme.SetupColorCache; +var + DC: HDC; + SwapC, HotBtnFace, DisabledText: TColor; + i1, i2: integer; + + procedure Undither(var C: TColor); + begin + if C <> clNone then + C := GetNearestColor(DC, ColorToRGB(C)); + end; + +begin + DC := StockCompatibleBitmap.Canvas.Handle; + + gradCol1 := clBtnFace; + gradCol2 := clWindow; + i1 := ColorIntensity(GradCol1); + i2 := ColorIntensity(GradCol2); + + if i1 > i2 then + begin + SwapC := gradCol1; + gradCol1 := gradCol2; + gradCol2 := SwapC; + end; + + if IsDarkColor(gradCol1) then + begin + if (i2 - i1) < 30 then + gradCol2 := Lighten(gradCol2, (i1 - i2)); + end + else if (i2 - i1) < 30 then + gradCol1 := Lighten(gradCol1, (i1 - i2)); + + gradHandle1 := gradCol1; + gradHandle2 := clBtnShadow; + gradHandle3 := clBtnHighlight; + gradBL := blend(clBtnShadow, gradCol1, 95); + + MenubarColor := Blend(gradCol1, gradCol2, 50); + ToolbarColor := Blend(gradCol1, gradCol2, 50); + PopupColor := Blend(clBtnFace, clWindow, 143); + DockPanelColor := PopupColor; + PopupFrameColor := Blend(clBtnText, clBtnShadow, 20); + SetContrast(PopupFrameColor, PopupColor, 100); + + HotBtnFace := Blend(clHighlight, clWindow, 20); + DisabledText := blend(clBtnText, gradCol2, 50); + + WinFrameColors[wfsActive, wfpBorder] := Blend(clBtnText, clBtnShadow, 15); + SetContrast(WinFrameColors[wfsActive, wfpBorder], ToolbarColor, 120); + WinFrameColors[wfsActive, wfpCaption] := clBtnShadow; + WinFrameColors[wfsActive, wfpCaptionText] := clBtnHighlight; + SetContrast(WinFrameColors[wfsActive, wfpCaptionText], clBtnShadow, 180); + WinFrameColors[wfsInactive, wfpBorder] := WinFrameColors[wfsActive, + wfpBorder]; + WinFrameColors[wfsInactive, wfpCaption] := clBtnFace; + WinFrameColors[wfsInactive, wfpCaptionText] := DisabledText; + SetContrast(WinFrameColors[wfsInactive, wfpCaptionText], clBtnFace, 120); + + PnlFrameColors[wfsActive, wfpBorder] := clBtnShadow; + PnlFrameColors[wfsActive, wfpCaption] := clBtnFace; + PnlFrameColors[wfsActive, wfpCaptionText] := clBtnText; + PnlFrameColors[wfsInactive, wfpBorder] := clBtnShadow; + PnlFrameColors[wfsInactive, wfpCaption] := clBtnFace; + PnlFrameColors[wfsInactive, wfpCaptionText] := DisabledText; + SetContrast(PnlFrameColors[wfsInactive, wfpCaptionText], clBtnFace, 120); + + BtnItemColors[bisNormal, ipBody] := clNone; + BtnItemColors[bisNormal, ipText] := clBtnText; + SetContrast(BtnItemColors[bisNormal, ipText], ToolbarColor, 180); + BtnItemColors[bisNormal, ipFrame] := clNone; + BtnItemColors[bisDisabled, ipBody] := clNone; + BtnItemColors[bisDisabled, ipText] := DisabledText; + + BtnItemColors[bisDisabled, ipFrame] := clNone; + BtnItemColors[bisSelected, ipBody] := Blend(clHighlight, Blend(clBtnFace, + clWindow, 50), 10); + SetContrast(BtnItemColors[bisSelected, ipBody], ToolbarColor, 5); + BtnItemColors[bisSelected, ipText] := BtnItemColors[bisNormal, ipText]; + BtnItemColors[bisSelected, ipFrame] := clHighlight; + BtnItemColors[bisPressed, ipBody] := Blend(clHighlight, clWindow, 50); + BtnItemColors[bisPressed, ipText] := clHighlightText; + BtnItemColors[bisPressed, ipFrame] := clHighlight; + SetContrast(BtnItemColors[bisPressed, ipFrame], ToolbarColor, 80); + BtnItemColors[bisHot, ipBody] := HotBtnFace; + BtnItemColors[bisHot, ipText] := clMenuText; + SetContrast(BtnItemColors[bisHot, ipText], BtnItemColors[bisHot, ipBody], + 180); + BtnItemColors[bisHot, ipFrame] := clHighlight; + SetContrast(BtnItemColors[bisHot, ipFrame], ToolbarColor, 100); + BtnItemColors[bisDisabledHot, ipBody] := HotBtnFace; + BtnItemColors[bisDisabledHot, ipText] := DisabledText; + BtnItemColors[bisDisabledHot, ipFrame] := clHighlight; + BtnItemColors[bisSelectedHot, ipBody] := Blend(clHighlight, clWindow, 40); + + SetContrast(BtnItemColors[bisSelectedHot, ipBody], ToolbarColor, 30); + BtnItemColors[bisSelectedHot, ipText] := clHighlightText; + SetContrast(BtnItemColors[bisSelectedHot, ipText], + BtnItemColors[bisSelectedHot, ipBody], 180); + BtnItemColors[bisSelectedHot, ipFrame] := clHighlight; + SetContrast(BtnItemColors[bisSelectedHot, ipFrame], + BtnItemColors[bisSelectedHot, ipBody], 100); + BtnItemColors[bisPopupParent, ipBody] := Blend(clBtnFace, clWindow, 183);//ToolbarColor; + BtnItemColors[bisPopupParent, ipText] := BtnItemColors[bisNormal, ipText]; + BtnItemColors[bisPopupParent, ipFrame] := PopupFrameColor; + + MenuItemColors[misNormal, ipBody] := clNone; + MenuItemColors[misNormal, ipText] := clWindowText; + SetContrast(MenuItemColors[misNormal, ipText], PopupColor, 180); + + MenuItemColors[misNormal, ipFrame] := clNone; + MenuItemColors[misDisabled, ipBody] := clNone; + MenuItemColors[misDisabled, ipText] := DisabledText; + MenuItemColors[misDisabled, ipFrame] := clNone; + + MenuItemColors[misHot, ipBody] := BtnItemColors[bisHot, ipBody]; + MenuItemColors[misHot, ipText] := BtnItemColors[bisHot, ipText]; + MenuItemColors[misHot, ipFrame] := BtnItemColors[bisHot, ipFrame]; + MenuItemColors[misDisabledHot, ipBody] := PopupColor; + MenuItemColors[misDisabledHot, ipText] := Blend(clGrayText, clWindow, 70); + MenuItemColors[misDisabledHot, ipFrame] := clHighlight; + + DragHandleColor := Blend(clBtnShadow, clWindow, 75); + SetContrast(DragHandleColor, ToolbarColor, 85); + IconShadowColor := Blend(clBlack, HotBtnFace, 25); + ToolbarSeparatorColor := Blend(clBtnShadow, clWindow, 70); + PopupSeparatorColor := ToolbarSeparatorColor; + SetContrast(PopupSeparatorColor, PopupColor, 50); + StatusPanelFrameColor := Blend(clWindow, clBtnFace, 30); + SetContrast(StatusPanelFrameColor, clBtnFace, 30); + + Undither(MenubarColor); + Undither(ToolbarColor); + Undither(PopupColor); + Undither(DockPanelColor); + Undither(PopupFrameColor); + Undither(WinFrameColors[wfsActive, wfpBorder]); + Undither(WinFrameColors[wfsActive, wfpCaption]); + Undither(WinFrameColors[wfsActive, wfpCaptionText]); + Undither(WinFrameColors[wfsInactive, wfpBorder]); + Undither(WinFrameColors[wfsInactive, wfpCaption]); + Undither(WinFrameColors[wfsInactive, wfpCaptionText]); + Undither(PnlFrameColors[wfsActive, wfpBorder]); + Undither(PnlFrameColors[wfsActive, wfpCaption]); + Undither(PnlFrameColors[wfsActive, wfpCaptionText]); + Undither(PnlFrameColors[wfsInactive, wfpBorder]); + Undither(PnlFrameColors[wfsInactive, wfpCaption]); + Undither(PnlFrameColors[wfsInactive, wfpCaptionText]); + Undither(BtnItemColors[bisNormal, ipBody]); + Undither(BtnItemColors[bisNormal, ipText]); + Undither(BtnItemColors[bisNormal, ipFrame]); + Undither(BtnItemColors[bisDisabled, ipBody]); + Undither(BtnItemColors[bisDisabled, ipText]); + Undither(BtnItemColors[bisDisabled, ipFrame]); + Undither(BtnItemColors[bisSelected, ipBody]); + Undither(BtnItemColors[bisSelected, ipText]); + Undither(BtnItemColors[bisSelected, ipFrame]); + Undither(BtnItemColors[bisPressed, ipBody]); + Undither(BtnItemColors[bisPressed, ipText]); + Undither(BtnItemColors[bisPressed, ipFrame]); + Undither(BtnItemColors[bisHot, ipBody]); + Undither(BtnItemColors[bisHot, ipText]); + Undither(BtnItemColors[bisHot, ipFrame]); + Undither(BtnItemColors[bisDisabledHot, ipBody]); + Undither(BtnItemColors[bisDisabledHot, ipText]); + Undither(BtnItemColors[bisDisabledHot, ipFrame]); + Undither(BtnItemColors[bisSelectedHot, ipBody]); + Undither(BtnItemColors[bisSelectedHot, ipText]); + Undither(BtnItemColors[bisSelectedHot, ipFrame]); + Undither(BtnItemColors[bisPopupParent, ipBody]); + Undither(BtnItemColors[bisPopupParent, ipText]); + Undither(BtnItemColors[bisPopupParent, ipFrame]); + Undither(MenuItemColors[misNormal, ipBody]); + Undither(MenuItemColors[misNormal, ipText]); + Undither(MenuItemColors[misNormal, ipFrame]); + Undither(MenuItemColors[misDisabled, ipBody]); + Undither(MenuItemColors[misDisabled, ipText]); + Undither(MenuItemColors[misDisabled, ipFrame]); + Undither(MenuItemColors[misHot, ipBody]); + Undither(MenuItemColors[misHot, ipText]); + Undither(MenuItemColors[misHot, ipFrame]); + Undither(MenuItemColors[misDisabledHot, ipBody]); + Undither(MenuItemColors[misDisabledHot, ipText]); + Undither(MenuItemColors[misDisabledHot, ipFrame]); + Undither(DragHandleColor); + Undither(IconShadowColor); + Undither(ToolbarSeparatorColor); + Undither(PopupSeparatorColor); + Undither(StatusPanelFrameColor); +end; + +function TTBXWhidbeyTheme.GetPopupShadowType: Integer; +begin + Result := PST_OFFICEXP; +end; + +constructor TTBXWhidbeyTheme.Create(const AName: string); +begin + inherited; + if CounterLock = 0 then + InitializeStock; + Inc(CounterLock); + AddTBXSysChangeNotification(Self); + SetupColorCache; +end; + +destructor TTBXWhidbeyTheme.Destroy; +begin + RemoveTBXSysChangeNotification(Self); + Dec(CounterLock); + if CounterLock = 0 then + FinalizeStock; + inherited; +end; + +procedure TTBXWhidbeyTheme.GetViewMargins(ViewType: Integer; + out Margins: TTBXMargins); +begin + Margins.LeftWidth := 0; + Margins.TopHeight := 0; + Margins.RightWidth := 0; + Margins.BottomHeight := 0; +end; + +procedure TTBXWhidbeyTheme.PaintPageScrollButton(Canvas: TCanvas; + const ARect: TRect; ButtonType: Integer; Hot: Boolean); +var + R: TRect; + X, Y, Sz: Integer; +begin + R := ARect; + if Hot then + Canvas.Brush.Color := BtnItemColors[bisHot, ipFrame] + else + Canvas.Brush.Color := clBtnShadow; + Canvas.FrameRect(R); + if Hot then + Canvas.Brush.Color := BtnItemColors[bisHot, ipBody] + else + Canvas.Brush.Color := clBtnFace; + InflateRect(R, -1, -1); + Canvas.FillRect(R); + X := (R.Left + R.Right) div 2; + Y := (R.Top + R.Bottom) div 2; + Sz := Min(X - R.Left, Y - R.Top) * 3 div 4; + if Hot then + Canvas.Pen.Color := BtnItemColors[bisHot, ipText] + else + Canvas.Pen.Color := BtnItemColors[bisNormal, ipText]; + Canvas.Brush.Color := Canvas.Pen.Color; + case ButtonType of + PSBT_UP: + begin + Inc(Y, Sz div 2); + Canvas.Polygon([Point(X + Sz, Y), Point(X, Y - Sz), Point(X - Sz, Y)]); + end; + PSBT_DOWN: + begin + Y := (R.Top + R.Bottom - 1) div 2; + Dec(Y, Sz div 2); + Canvas.Polygon([Point(X + Sz, Y), Point(X, Y + Sz), Point(X - Sz, Y)]); + end; + PSBT_LEFT: + begin + Inc(X, Sz div 2); + Canvas.Polygon([Point(X, Y + Sz), Point(X - Sz, Y), Point(X, Y - Sz)]); + end; + PSBT_RIGHT: + begin + X := (R.Left + R.Right - 1) div 2; + Dec(X, Sz div 2); + Canvas.Polygon([Point(X, Y + Sz), Point(X + Sz, Y), Point(X, Y - Sz)]); + end; + end; +end; + +procedure TTBXWhidbeyTheme.PaintFrameControl(Canvas: TCanvas; R: TRect; Kind, + State: Integer; Params: Pointer); +var + X, Y: Integer; + + procedure SetupPen; + begin + if Boolean(State and PFS_DISABLED) then + Canvas.Pen.Color := clBtnShadow + else if Boolean(State and PFS_PUSHED) then + Canvas.Pen.Color := BtnItemColors[bisPressed, ipFrame] + else if Boolean(State and PFS_HOT) then + Canvas.Pen.Color := BtnItemColors[bisHot, ipFrame] + else + Canvas.Pen.Color := clBtnShadow; + end; + + procedure SetupBrush; + begin + Canvas.Brush.Style := bsSolid; + if Boolean(State and PFS_DISABLED) then + Canvas.Brush.Style := bsClear + else if Boolean(State and PFS_PUSHED) then + Canvas.Brush.Color := BtnItemColors[bisPressed, ipBody] + else if Boolean(State and PFS_HOT) then + Canvas.Brush.Color := BtnItemColors[bisHot, ipBody] + else if Boolean(State and PFS_MIXED) then + Canvas.Brush.Bitmap := AllocPatternBitmap(clWindow, clBtnFace) + else + Canvas.Brush.Style := bsClear; + end; + + function TextColor: TColor; + begin + if Boolean(State and PFS_DISABLED) then + Result := BtnItemColors[bisDisabled, ipText] + else if Boolean(State and PFS_PUSHED) then + Result := BtnItemColors[bisPressed, ipText] + else if Boolean(State and PFS_MIXED) then + Result := clBtnShadow + else if Boolean(State and PFS_HOT) then + Result := BtnItemColors[bisHot, ipText] + else + Result := BtnItemColors[bisNormal, ipText]; + end; + + procedure DiagLine(C: TColor); + begin + with Canvas, R do + begin + Pen.Color := C; + MoveTo(Right - 1 - X, Bottom - 1); + LineTo(Right, Bottom - X - 2); + Inc(X); + end; + end; + +begin + with Canvas do + case Kind of + PFC_CHECKBOX: + begin + SetupPen; + SetupBrush; + InflateRect(R, -1, -1); + with R do + Rectangle(Left, Top, Right, Bottom); + Pen.Style := psSolid; + Brush.Style := bsSolid; + + if Boolean(State and (PFS_CHECKED or PFS_MIXED)) then + begin + X := (R.Left + R.Right) div 2 - 1; + Y := (R.Top + R.Bottom) div 2 + 1; + Pen.Color := TextColor; + Brush.Color := Pen.Color; + Polygon([Point(X - 2, Y), Point(X, Y + 2), Point(X + 4, Y - 2), + Point(X + 4, Y - 4), Point(X, Y), Point(X - 2, Y - 2), Point(X - + 2, Y)]); + end; + end; + PFC_RADIOBUTTON: + begin + SetupPen; + SetupBrush; + InflateRect(R, -1, -1); + with R do + Ellipse(Left, Top, Right, Bottom); + Pen.Style := psSolid; + Brush.Style := bsSolid; + if Boolean(State and PFS_CHECKED) then + begin + InflateRect(R, -3, -3); + Pen.Color := TextColor; + Brush.Color := Pen.Color; + with R do + Ellipse(Left, Top, Right, Bottom); + end; + end; + end; +end; + +procedure TTBXWhidbeyTheme.PaintStatusBar(Canvas: TCanvas; R: TRect; Part: + Integer); +var + D, Sz: integer; + + procedure DiagLine(C: TColor); + begin + with R do + DrawLineEx(Canvas.Handle, Right - 1 - D, Bottom - 1, Right, Bottom - D - + 2, C); + Inc(D); + end; + +begin + with Canvas, R do + case Part of + SBP_BODY: + begin + FillRectEx(Handle, R, clBtnFace); + end; + SBP_PANE, SBP_LASTPANE: + begin + if Part = SBP_PANE then + Dec(R.Right, 2); + FrameRectEx(Handle, R, StatusPanelFrameColor, True); + end; + SBP_GRIPPER: + begin + D := 0; + Sz := Min(Right - Left, Bottom - Top); + case Sz of + 0..8: + begin + DiagLine(clBtnShadow); + DiagLine(clBtnHighlight); + DiagLine(clBtnShadow); + DiagLine(clBtnHighlight); + DiagLine(clBtnShadow); + DiagLine(clBtnHighlight); + end; + 9..11: + begin + DiagLine(clBtnFace); + DiagLine(clBtnShadow); + DiagLine(clBtnHighlight); + DiagLine(clBtnFace); + DiagLine(clBtnShadow); + DiagLine(clBtnHighlight); + DiagLine(clBtnFace); + DiagLine(clBtnShadow); + DiagLine(clBtnHighlight); + end; + 12..14: + begin + DiagLine(clBtnShadow); + DiagLine(clBtnShadow); + DiagLine(clBtnHighlight); + DiagLine(clBtnShadow); + DiagLine(clBtnShadow); + DiagLine(clBtnHighlight); + DiagLine(clBtnShadow); + DiagLine(clBtnShadow); + DiagLine(clBtnHighlight); + end; + else + begin + DiagLine(clBtnShadow); + DiagLine(clBtnShadow); + DiagLine(clBtnHighlight); + DiagLine(clBtnFace); + DiagLine(clBtnShadow); + DiagLine(clBtnShadow); + DiagLine(clBtnShadow); + DiagLine(clBtnHighlight); + DiagLine(clBtnFace); + DiagLine(clBtnShadow); + DiagLine(clBtnShadow); + DiagLine(clBtnShadow); + DiagLine(clBtnHighlight); + end; + end; + end; + end; +end; + +procedure TTBXWhidbeyTheme.TBXSysCommand(var Message: TMessage); +begin + if Message.WParam = TSC_VIEWCHANGE then + SetupColorCache; +end; + +{$IFNDEF DTM_Package} +initialization + RegisterTBXTheme('Whidbey', TTBXWhidbeyTheme); +{$ENDIF} + +end. + diff --git a/official/2.1.6+2.1.beta1/TBX/TBX_MDI.res b/official/2.1.6+2.1.beta1/TBX/TBX_MDI.res new file mode 100644 index 0000000..eb371ed Binary files /dev/null and b/official/2.1.6+2.1.beta1/TBX/TBX_MDI.res differ diff --git a/official/2.1.6+2.1.beta1/TBX/_clean.bat b/official/2.1.6+2.1.beta1/TBX/_clean.bat new file mode 100644 index 0000000..4b01d20 --- /dev/null +++ b/official/2.1.6+2.1.beta1/TBX/_clean.bat @@ -0,0 +1,11 @@ +del /S *.~* +del /S *.dcu +del /S *.dsk +del /S *.cfg +del /S *.dof +del /S *.obj +del /S *.hpp +del /S *.ddp +del /S *.mps +del /S *.mpt +del /S *.bak diff --git a/official/2.1.6+2.1.beta1/TBX/_tbx_2.1.beta_patch.diff.txt b/official/2.1.6+2.1.beta1/TBX/_tbx_2.1.beta_patch.diff.txt new file mode 100644 index 0000000..6136197 --- /dev/null +++ b/official/2.1.6+2.1.beta1/TBX/_tbx_2.1.beta_patch.diff.txt @@ -0,0 +1,2649 @@ +--- TBX.pas 2004-05-29 19:48:58.000000000 +-0400 ++++ TBX.pas 2005-08-14 23:15:12.000000000 +-0400 +@@ -8,12 +8,16 @@ + + interface + + {$I TB2Ver.inc} + {$I TBX.inc} + ++{x$DEFINE TBX_NO_ANIMATION} ++ { Enabling the above define disables all menu animation. For debugging ++ purpose only. } {vb+} ++ + uses + Windows, Messages, Classes, SysUtils, Controls, Graphics, ImgList, Forms, + TB2Item, TB2Dock, TB2Toolbar, TB2ToolWindow, TB2Anim, TBXUtils, TBXThemes; + + const + TBXVersion = 2.1; +@@ -68,13 +72,13 @@ + property Underline: TTriState read FUnderline write SetUnderline default tsDefault; + property StrikeOut: TTriState read FStrikeOut write SetStrikeOut default tsDefault; + property Size: TFontSize read FSize write SetSize default 100; // percent + property Color: TColor read FColor write SetColor default clNone; + property Name: TFontName read FName write SetName; // default '' + end; +- ++ + TTBXPopupPositionInfo = record + Item: TTBCustomItem; // this is a tentative type, it will be changed + ParentView: TTBView; // or removed in future versions + ParentViewer: TTBItemViewer; + PositionAsSubmenu: Boolean; + APopupPoint: TPoint; +@@ -160,12 +164,13 @@ + property InheritOptions; + property Layout; + property MaskOptions; + property MinHeight; + property MinWidth; + property Options; ++ property RadioItem; + property ShortCut; + property Stretch; + property Visible; + property OnAdjustFont; + property OnDrawImage; + property OnClick; +@@ -224,12 +229,13 @@ + property Layout; + property LinkSubitems; + property MaskOptions; + property MinHeight; + property MinWidth; + property Options; ++ property RadioItem; + property ShortCut; + property Stretch; + property SubMenuImages; + property ToolBoxPopup; + property Visible; + property OnAdjustFont; +@@ -302,12 +308,13 @@ + + TTBXPopupWindow = class(TTBPopupWindow) + private + FControlRect: TRect; + FShadows: TShadows; + procedure CMHintShow(var Message: TCMHintShow); message CM_HINTSHOW; ++ procedure CMShowingChanged(var Message: TMessage); message CM_SHOWINGCHANGED; {vb+} + procedure TBMGetViewType(var Message: TMessage); message TBM_GETVIEWTYPE; + procedure WMNCCalcSize(var Message: TWMNCCalcSize); message WM_NCCALCSIZE; + procedure WMNCPaint(var Message: TMessage); message WM_NCPAINT; + procedure WMPrint(var Message: TMessage); message WM_PRINT; + procedure WMEraseBkgnd(var Message: TWMEraseBkgnd); message WM_ERASEBKGND; + procedure WMWindowPosChanged(var Message: TWMWindowPosChanged); message WM_WINDOWPOSCHANGED; +@@ -316,12 +323,13 @@ + procedure CreateParams(var Params: TCreateParams); override; + procedure CreateShadow; virtual; + procedure DestroyShadow; virtual; + function GetNCSize: TPoint; override; + function GetShowShadow: Boolean; virtual; + function GetViewClass: TTBViewClass; override; ++ procedure PaintScrollArrows; override; {vb+} + public + destructor Destroy; override; + function GetFillColor: TColor; + end; + + TTBXPopupView = class(TTBPopupView); +@@ -354,12 +362,13 @@ + protected + procedure DrawNCArea(const DrawToDC: Boolean; const ADC: HDC; const Clip: HRGN); override; + function GetChevronItemClass: TTBChevronItemClass; override; + function GetFloatingWindowParentClass: TTBFloatingWindowParentClass; override; + procedure GetToolbarInfo(out ToolbarInfo: TTBXToolbarInfo); virtual; + function GetViewClass: TTBToolbarViewClass; override; ++ procedure Loaded; override; {vb+} + procedure SetParent(AParent: TWinControl); override; + procedure UpdateEffectiveColor; + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + function Embedded: Boolean; +@@ -461,26 +470,29 @@ + protected + function CreatePopupEx(SelectFirstItem: Boolean; const AControlRect: TRect; + Alignment: TTBPopupAlignment): TTBPopupWindow; virtual; + function GetPopupWindowClass: TTBPopupWindowClass; override; + procedure GetPopupPosition(ParentView: TTBView; PopupWindow: TTBPopupWindow; + var PopupPositionRec: TTBPopupPositionRec); override; +- procedure OpenPopupEx(const SelectFirstItem, TrackRightButton: Boolean; +- const ControlRect: TRect; const Alignment: TTBPopupAlignment); +- procedure PopupEx(const ControlRect: TRect; TrackRightButton: Boolean; +- Alignment: TTBPopupAlignment = tbpaLeft); ++ function OpenPopupEx(const SelectFirstItem, TrackRightButton: Boolean; ++ const ControlRect: TRect; const Alignment: TTBPopupAlignment; ++ const ReturnClickedItemOnly: Boolean): TTBCustomItem; ++ function PopupEx(const ControlRect: TRect; TrackRightButton: Boolean; ++ Alignment: TTBPopupAlignment = tbpaLeft; ++ ReturnClickedItemOnly: Boolean = False): TTBCustomItem; + end; + + TTBXPopupMenu = class(TTBPopupMenu) + private + FToolBoxPopup: Boolean; + procedure TBMGetViewType(var Message: TMessage); message TBM_GETVIEWTYPE; + protected + function GetRootItemClass: TTBRootItemClass; override; + public +- procedure PopupEx(const ControlRect: TRect); ++ function PopupEx(const ControlRect: TRect; ++ ReturnClickedItemOnly: Boolean = False): TTBCustomItem; + property ToolBoxPopup: Boolean read FToolBoxPopup write FToolBoxPopup default False; + end; + + TTBXFloatingWindowParent = class(TTBFloatingWindowParent) + private + FCloseButtonHover: Boolean; +@@ -551,14 +563,35 @@ + destructor Destroy; override; + published + property Color default clNone; + property UseParentBackground: Boolean read FUseParentBackground write SetUseParentBackground default False; + end; + ++ { TTBXMenuAnimation } {vb+} ++ ++ TMenuAnimation = (maNone, maUnfold, maSlide, maFade); ++ TAnimationMode = (amNone, amSysDefault, amRandom, amUnfold, amSlide, amFade); ++ TAnimationModes = set of TAnimationMode; ++ ++ TTBXMenuAnimation = class ++ private ++ FAnimationMode: TAnimationMode; ++ function SysParamEnabled(Param: Cardinal): Boolean; ++ function GetAvailableModes: TAnimationModes; ++ function GetMenuAnimation: TMenuAnimation; ++ procedure SetAnimationMode(Value: TAnimationMode); ++ property MenuAnimation: TMenuAnimation read GetMenuAnimation; ++ public ++ constructor Create(AAnimationMode: TAnimationMode = amSysDefault); ++ property AnimationMode: TAnimationMode read FAnimationMode write SetAnimationMode; ++ property AvailableModes: TAnimationModes read GetAvailableModes; ++ end; ++ + var + CurrentTheme: TTBXTheme; ++ TBXMenuAnimation: TTBXMenuAnimation; { vb+ } + + {$IFNDEF JR_D6} + var + clMoneyGreen: TColor = TColor($C0DCC0); + clSkyBlue: TColor = TColor($F0CAA6); + clCream: TColor = TColor($F0FBFF); +@@ -588,25 +621,27 @@ + implementation + + {$R tbx_glyphs.res} + + uses + TBXExtItems, TBXLists, TB2Common, TBXUxThemes, MultiMon, TBXDefaultTheme, +- ComCtrls, Menus; ++ {ComCtrls, Menus;} {vb-} ++ ComCtrls, Menus, MMSystem; {vb+} + + type + TTBItemAccess = class(TTBCustomItem); + TTBViewAccess = class(TTBView); + TTBItemViewerAccess = class(TTBItemViewer); + TTBFloatingWindowParentAccess = class(TTBFloatingWindowParent); + TTBCustomDockableWindowAccess = class(TTBCustomDockableWindow); + TTBXToolbarAccess = class(TTBXToolbar); + TTBBackgroundAccess = class(TTBBackground); + TControlAccess = class(TControl); + TTBXThemeAccess = class(TTBXTheme); + TDockAccess = class(TTBDock); ++ TTBPopupWindowAccess = class(TTBPopupWindow); {vb+} + + { TTBNexus } + TTBXNexus = class + private + FNotifies: TList; + procedure TBXSysCommand(var Message: TMessage); message TBX_SYSCOMMAND; +@@ -670,14 +705,14 @@ + Shift.X := 0; Shift.Y := 0; + Shift := Parent.ScreenToClient(Control.ClientToScreen(Shift)); + SaveDC(DC); + try + SetWindowOrgEx(DC, Shift.X, Shift.Y, nil); + Msg.Msg := WM_ERASEBKGND; +- Msg.WParam := DC; +- Msg.LParam := DC; ++ Msg.WParam := Integer(DC); {vb+} ++ Msg.LParam := Integer(DC); {vb+} + Msg.Result := 0; + Parent.Dispatch(Msg); + finally + RestoreDC(DC, -1); + end; + +@@ -1316,13 +1351,13 @@ + end + else + begin + Inc(AHeight, ImgSize.CY); + if AWidth < ImgSize.CX + 7 then AWidth := ImgSize.CX + 7; + end; +- end; ++ end; + + if tbisSubmenu in TTBItemAccess(Item).ItemStyle then with CurrentTheme do + begin + if tbisCombo in TTBItemAccess(Item).ItemStyle then Inc(AWidth, SplitBtnArrowWidth) + else if tboDropdownArrow in Item.EffectiveOptions then + begin +@@ -1521,13 +1556,13 @@ + Result := not (tbisSubmenu in TTBItemAccess(Item).ItemStyle); + if (tbisCombo in TTBItemAccess(Item).ItemStyle) then + begin + if IsToolbarStyle then W := CurrentTheme.SplitBtnArrowWidth + else W := GetSystemMetrics(SM_CXMENUCHECK); + Result := X < (BoundsRect.Right - BoundsRect.Left) - W; +- end; ++ end; + end; + + function TTBXItemViewer.IsToolbarSize: Boolean; + begin + Result := inherited IsToolbarSize; + Result := Result or ((GetViewType(View) and PVT_TOOLBOX) = PVT_TOOLBOX); +@@ -1564,13 +1599,13 @@ + CAppActive: array [Boolean] of Integer = (0, IO_APPACTIVE); + var + Item: TTBXCustomItem; + View: TTBViewAccess; + ItemInfo: TTBXItemInfo; + +- M: Integer; ++ {M: Integer;} {vb-} + R: TRect; + ComboRect: TRect; + CaptionRect: TRect; + ImageRect: TRect; + C: TColor; + +@@ -1888,15 +1923,22 @@ + Left := Left + ((Right - Left) - CX) div 2; + ImageRect.Top := Top + ((Bottom - Top) - CY) div 2; + Right := Left + CX; + Bottom := Top + CY; + DrawItemImage(Canvas, ImageRect, ItemInfo); + end +- else if not ToolbarStyle and Item.Checked then +- CurrentTheme.PaintCheckMark(Canvas, ImageRect, ItemInfo); +- end; ++ {else if not ToolbarStyle and Item.Checked then ++ CurrentTheme.PaintCheckMark(Canvas, ImageRect, ItemInfo);} {vb-} ++ else {vb+} ++ if not ToolbarStyle and Item.Checked then ++ begin ++ if Item.RadioItem then ++ with ItemInfo do ItemOptions := ItemOptions or IO_RADIO; ++ CurrentTheme.PaintCheckMark(Canvas, ImageRect, ItemInfo); ++ end; ++ end; + end; + + + //============================================================================// + + { TTBXSubmenuItem } +@@ -2090,12 +2132,59 @@ + HintStr := View.Selected.GetHintText; + View.Selected.Dispatch(Message); + end; + end; + end; + ++procedure TTBXPopupWindow.CMShowingChanged(var Message: TMessage); {vb+} ++const ++ ShowFlags: array[Boolean] of UINT = ( ++ SWP_NOSIZE or SWP_NOMOVE or SWP_NOZORDER or SWP_NOACTIVATE or SWP_HIDEWINDOW, ++ SWP_NOSIZE or SWP_NOMOVE or SWP_NOZORDER or SWP_NOACTIVATE or SWP_SHOWWINDOW); ++var ++ MenuAni: TMenuAnimation; ++ AniDir: TTBAnimationDirection; ++begin ++ { Must override TCustomForm/TForm's CM_SHOWINGCHANGED handler so that the ++ form doesn't get activated when Visible is set to True. } ++ ++ { Handle animation. NOTE: I do not recommend trying to enable animation on ++ Windows 95 and NT 4.0 because there's a difference in the way the ++ SetWindowPos works on those versions. See the comment in the ++ TBStartAnimation function of TB2Anim.pas. } ++ {$IFNDEF TBX_NO_ANIMATION} ++ if ((View.ParentView = nil) or not(vsNoAnimation in View.ParentView.State)) and ++ Showing and (View.Selected = nil) and not IsWindowVisible(WindowHandle) and ++ (TBXMenuAnimation.AnimationMode <> amNone) then ++ begin ++ { Start animation only if WM_TB2K_POPUPSHOWING returns zero (or not handled) } ++ if SendMessage(WindowHandle, WM_TB2K_POPUPSHOWING, TPS_ANIMSTART, 0) = 0 then ++ begin ++ MenuAni := TBXMenuAnimation.MenuAnimation; ++ AniDir := TTBPopupWindowAccess(Self).AnimationDirection; ++ if MenuAni = maUnfold then ++ if [tbadDown, tbadUp] * AniDir <> [] ++ then Include(AniDir, tbadRight) ++ else Include(AniDir, tbadDown); ++ TBStartAnimation(WindowHandle, MenuAni = maFade, AniDir); ++ Exit; ++ end; ++ end; ++ {$ENDIF} ++ ++ { No animation... } ++ if not Showing then begin ++ { Call TBEndAnimation to ensure WS_EX_LAYERED style is removed before ++ hiding, otherwise windows under the popup window aren't repainted ++ properly. } ++ TBEndAnimation(WindowHandle); ++ end; ++ SetWindowPos(WindowHandle, 0, 0, 0, 0, 0, ShowFlags[Showing]); ++ if Showing then SendNotifyMessage(WindowHandle, WM_TB2K_POPUPSHOWING, TPS_NOANIM, 0); ++end; ++ + procedure TTBXPopupWindow.CreateParams(var Params: TCreateParams); + const + CS_DROPSHADOW = $00020000; + begin + inherited CreateParams(Params); + with Params do +@@ -2180,12 +2269,61 @@ + + function TTBXPopupWindow.GetViewClass: TTBViewClass; + begin + Result := TTBXPopupView; + end; + ++procedure TTBXPopupWindow.PaintScrollArrows; {vb+} ++ ++ function _GetPopupMargin: Integer; ++ begin ++ if View.ParentView <> nil then ++ Result := GetPopupMargin(TTBViewAccess(View.ParentView).OpenViewer) ++ else if View.ViewerCount > 0 then ++ Result := GetPopupMargin(View.Viewers[0]) ++ else Result := -1; ++ end; ++ ++ procedure DrawArrows; ++ var ++ ItemInfo: TTBXItemInfo; ++ Index: Integer; ++ begin ++ FillChar(ItemInfo, SizeOf(ItemInfo), 0); ++ ItemInfo.ViewType := PVT_POPUPMENU; ++ ItemInfo.Enabled := True; ++ ItemInfo.PopupMargin := _GetPopupMargin; ++ if ItemInfo.PopupMargin > 0 then ++ begin ++ if TTBViewAccess(View).ShowUpArrow then ++ for Index := 0 to View.ViewerCount- 1 do ++ if View.Viewers[Index].Show then ++ begin ++ CurrentTheme.PaintMenuItemFrame(Canvas, Rect(0, 0, ClientWidth, ++ View.Viewers[Index].BoundsRect.Top), ItemInfo); ++ Break; ++ end; ++ if TTBViewAccess(View).ShowDownArrow then ++ for Index := View.ViewerCount- 1 downto 0 do ++ if View.Viewers[Index].Show then ++ begin ++ CurrentTheme.PaintMenuItemFrame(Canvas, Rect(0, ++ View.Viewers[Index].BoundsRect.Bottom, ClientWidth, ++ ClientHeight), ItemInfo); ++ Break; ++ end; ++ end; ++ end; ++ ++begin ++ with TTBViewAccess(View) do ++ if ShowUpArrow or ShowDownArrow then ++ DrawArrows; ++ inherited; ++end; ++ + procedure TTBXPopupWindow.TBMGetViewType(var Message: TMessage); + var + PI: TTBCustomItem; + begin + Message.Result := PVT_POPUPMENU; + if View <> nil then +@@ -2462,13 +2600,13 @@ + R2 := CurrentDock.ClientRect; + OffsetRect(R2, -Left, -Top); + TDockAccess(CurrentDock).DrawBackground(DC, R2); + if (Color = clNone) and CurrentDock.BackgroundOnToolbars then + ACanvas.Brush.Style := bsClear; + end +- else ++ else + begin + ACanvas.Brush.Color := GetEffectiveColor(CurrentDock); + ACanvas.FillRect(R); + ACanvas.Brush.Color := EffectiveColor; + ACanvas.Brush.Style := bsSolid; + end; +@@ -2533,12 +2671,18 @@ + procedure TTBXToolbar.SetItemTransparency(const Value: TTBXItemTransparency); + begin + FItemTransparency := Value; + Invalidate; + end; + ++procedure TTBXToolbar.Loaded; {vb+} ++begin ++ inherited; ++ UpdateEffectiveColor; ++end; ++ + procedure TTBXToolbar.SetParent(AParent: TWinControl); + begin + inherited; + if AParent is TTBXFloatingWindowParent then + TTBXFloatingWindowParent(AParent).SnapDistance := SnapDistance; + end; +@@ -2806,14 +2950,15 @@ + + function TTBXRootItem.GetPopupWindowClass: TTBPopupWindowClass; + begin + Result := TTBXPopupWindow; + end; + +-procedure TTBXRootItem.OpenPopupEx(const SelectFirstItem, TrackRightButton: Boolean; +- const ControlRect: TRect; const Alignment: TTBPopupAlignment); ++function TTBXRootItem.OpenPopupEx(const SelectFirstItem, TrackRightButton: Boolean; ++ const ControlRect: TRect; const Alignment: TTBPopupAlignment; ++ const ReturnClickedItemOnly: Boolean): TTBCustomItem; + var + ModalHandler: TTBModalHandler; + Popup: TTBPopupWindow; + DoneActionData: TTBDoneActionData; + State: TTBViewState; + begin +@@ -2834,37 +2979,45 @@ + TTBViewAccess(Popup.View).SetState(State); + Popup.Free; + end; + finally + ModalHandler.Free; + end; +- ProcessDoneAction(DoneActionData); ++ Result := ProcessDoneAction(DoneActionData, ReturnClickedItemOnly); + end; + +-procedure TTBXRootItem.PopupEx(const ControlRect: TRect; +- TrackRightButton: Boolean; Alignment: TTBPopupAlignment); ++function TTBXRootItem.PopupEx(const ControlRect: TRect; ++ TrackRightButton: Boolean; Alignment: TTBPopupAlignment = tbpaLeft; ++ ReturnClickedItemOnly: Boolean = False): TTBCustomItem; + begin +- OpenPopupEx(False, TrackRightButton, ControlRect, Alignment); ++ Result := OpenPopupEx(False, TrackRightButton, ControlRect, ++ Alignment, ReturnClickedItemOnly); + end; + + + //============================================================================// + + { TTBXPopupMenu } + + function TTBXPopupMenu.GetRootItemClass: TTBRootItemClass; + begin + Result := TTBXRootItem; + end; + +-procedure TTBXPopupMenu.PopupEx(const ControlRect: TRect); ++function TTBXPopupMenu.PopupEx(const ControlRect: TRect; ++ ReturnClickedItemOnly: Boolean = False): TTBCustomItem; + begin + {$IFDEF JR_D5} ++ {$IFDEF JR_D9} ++ SetPopupPoint(Point(ControlRect.Left, ControlRect.Bottom)); ++ {$ELSE} + PPoint(@PopupPoint)^ := Point(ControlRect.Left, ControlRect.Bottom); + {$ENDIF} +- TTBXRootItem(Items).PopupEx(ControlRect, TrackButton = tbRightButton, TTBPopupAlignment(Alignment)) ++ {$ENDIF} ++ Result := TTBXRootItem(Items).PopupEx(ControlRect, TrackButton = tbRightButton, ++ TTBPopupAlignment(Alignment), ReturnClickedItemOnly); + end; + + procedure TTBXPopupMenu.TBMGetViewType(var Message: TMessage); + begin + Message.Result := PVT_POPUPMENU; + end; +@@ -3403,13 +3556,15 @@ + if Message.Msg = TBX_SYSCOMMAND then + Broadcast(TBM_THEMECHANGE, Message.WParam, 0); + end; + + procedure InitAdditionalSysColors; + begin ++{$IFNDEF JR_D7} {vb+} + AddTBXColor(clHotLight, 'clHotLight'); ++{$ENDIF} {vb+} + {$IFNDEF JR_D6} + AddTBXColor(clMoneyGreen, 'clMoneyGreen'); + AddTBXColor(clSkyBlue, 'clSkyBlue'); + AddTBXColor(clCream, 'clCream'); + AddTBXColor(clMedGray, 'clMedGray'); + {$ENDIF} +@@ -3572,17 +3727,111 @@ + begin + FResizing := True; + inherited; + FResizing := False; + end; + ++{ TTBXMenuAnimation } {vb+} ++ ++constructor TTBXMenuAnimation.Create(AAnimationMode: TAnimationMode = amSysDefault); ++begin ++ AnimationMode := AAnimationMode; ++end; ++ ++function TTBXMenuAnimation.GetAvailableModes: TAnimationModes; ++var IsWindows2K: Boolean; ++begin ++ Result := [amNone]; ++ IsWindows2K := (Win32Platform = VER_PLATFORM_WIN32_NT) and ++ CheckWin32Version(5); ++ if IsWindows2K or ((Win32Platform = VER_PLATFORM_WIN32_WINDOWS) and ++ CheckWin32Version(4, 10){Win98}) then ++ Result := Result+ [amSysDefault, amRandom, amUnfold, amSlide]; ++ if IsWindows2K then ++ Include(Result, amFade); ++end; ++ ++function TTBXMenuAnimation.GetMenuAnimation: TMenuAnimation; ++ ++ function GetSysDefault: TMenuAnimation; ++ const ++ SPI_GETMENUFADE = $1012; ++ SysDefAni: array[Boolean] of TMenuAnimation = (maSlide, maFade); ++ begin ++ if SysParamEnabled(SPI_GETMENUANIMATION) ++ then Result := SysDefAni[SysParamEnabled(SPI_GETMENUFADE)] ++ else Result := maNone; ++ end; ++ ++ function GetRandom: TMenuAnimation; ++ var Max: Integer; ++ begin ++ Max := Ord(High(TMenuAnimation)); ++ if not (amFade in AvailableModes) then ++ Dec(Max); ++ Result := Succ(TMenuAnimation(Random(Max))); ++ end; ++ ++begin ++ case AnimationMode of ++ amSysDefault: Result := GetSysDefault; ++ amRandom: Result := GetRandom; ++ amUnfold: Result := maUnfold; ++ amSlide: Result := maSlide; ++ amFade: Result := maFade; ++ else ++ Result := maNone; ++ end; ++end; ++ ++procedure TTBXMenuAnimation.SetAnimationMode(Value: TAnimationMode); ++var AvailModes: TAnimationModes; ++begin ++ AvailModes := AvailableModes; ++ while not (Value in AvailModes) do ++ Value := Pred(Value); ++ FAnimationMode := Value; ++end; ++ ++function TTBXMenuAnimation.SysParamEnabled(Param: Cardinal): Boolean; ++var B: BOOL; ++begin ++ Result := SystemParametersInfo(Param, 0, @B, 0) and B; ++end; ++ ++{ Work around delayed menu showing in Windows 2000+ } {vb+} ++var ++ FixPlaySoundThreadHandle: Cardinal; ++ ++function FixPlaySoundThreadFunc(Param: Pointer): Integer; stdcall; ++begin ++ Sleep(250); ++ PlaySound(nil, 0, 0); ++ CloseHandle(FixPlaySoundThreadHandle); { Harakiri :~| } ++ Result := $4E494150; { :) } ++end; ++ ++procedure FixPlaySoundDelay; ++var ThreadId: Cardinal; ++begin ++ if (Win32Platform = VER_PLATFORM_WIN32_NT) and CheckWin32Version(5) and ++ (FixPlaySoundThreadHandle = 0) then ++ FixPlaySoundThreadHandle := CreateThread(nil, $1000, ++ @FixPlaySoundThreadFunc, nil, 0, ThreadId); ++end; ++ + initialization +- CurrentTheme := nil; ++ FixPlaySoundDelay; {vb+} ++ {CurrentTheme := nil;} {vb-} + RegisterTBXTheme('Default', TTBXDefaultTheme); + TBXNexus := TTBXNexus.Create('Default'); ++ TBXMenuAnimation := TTBXMenuAnimation.Create; {vb+} ++ {$IFNDEF JR_D7} {vb+} + InitAdditionalSysColors; ++ {$ENDIF} {vb+} + + finalization + TBXNexus.Free; ++ FreeAndNil(TBXMenuAnimation); {vb+} + ColorRegistry := nil; + + end. +--- TBXAluminumTheme.pas 2004-05-25 22:02:56.000000000 +-0400 ++++ TBXAluminumTheme.pas 2005-08-03 02:29:24.000000000 +-0400 +@@ -441,12 +441,13 @@ + end; + + function TTBXAluminumTheme.GetIntegerMetrics(Index: Integer): Integer; + begin + case Index of + TMI_SPLITBTN_ARROWWIDTH: Result := 12; ++ TMI_MENU_LCAPTIONMARGIN: Result := 3; + TMI_MENU_MDI_DW: Result := 1; + TMI_MENU_MDI_DH: Result := 2; + TMI_EDIT_FRAMEWIDTH: Result := 2; + TMI_EDIT_TEXTMARGINHORZ: Result := 2; + TMI_EDIT_TEXTMARGINVERT: Result := 1; + TMI_EDIT_BTNWIDTH: Result := 14; +@@ -573,18 +574,27 @@ + end; + + procedure TTBXAluminumTheme.PaintCheckMark(Canvas: TCanvas; ARect: TRect; const ItemInfo: TTBXItemInfo); + var + DC: HDC; + X, Y: Integer; ++ C: TColor; + begin + DC := Canvas.Handle; +- X := (ARect.Left + ARect.Right) div 2 - 2; ++ X := (ARect.Left + ARect.Right) div 2 - 1; + Y := (ARect.Top + ARect.Bottom) div 2 + 1; +- PolyLineEx(DC, [Point(X-2, Y-2), Point(X, Y), Point(X+4, Y-4), +- Point(X+4, Y-3), Point(X, Y+1), Point(X-2, Y-1), Point(X-2, Y-2)], GetBtnColor(ItemInfo, ipText)); ++ C := GetBtnColor(ItemInfo, ipText); ++ if ItemInfo.ItemOptions and IO_RADIO > 0 then ++ begin ++ RoundRectEx(DC, X-2, Y-4, X+4, Y+2, 2, 2, ++ MixColors(C, ToolbarColor, 200), clNone); ++ RoundRectEx(DC, X-2, Y-4, X+4, Y+2, 6, 6, C, C); ++ end ++ else ++ PolylineEx(DC, [Point(X-2, Y-2), Point(X, Y), Point(X+4, Y-4), ++ Point(X+4, Y-3), Point(X, Y+1), Point(X-2, Y-1), Point(X-2, Y-2)], C); + end; + + procedure TTBXAluminumTheme.PaintDropDownArrow(Canvas: TCanvas; + const ARect: TRect; const ItemInfo: TTBXItemInfo); + var + X, Y: Integer; +--- TBXDefaultTheme.pas 2004-05-25 22:02:56.000000000 +-0400 ++++ TBXDefaultTheme.pas 2005-08-03 01:58:42.000000000 +-0400 +@@ -388,25 +388,36 @@ + Brush.Style := bsSolid; + end; + end; + + procedure TTBXDefaultTheme.PaintCheckMark(Canvas: TCanvas; ARect: TRect; const ItemInfo: TTBXItemInfo); + var ++ DC: HDC; + X, Y: Integer; ++ C: TColor; + begin ++ DC := Canvas.Handle; + X := (ARect.Left + ARect.Right) div 2 - 1; +- Y := (ARect.Top + ARect.Bottom) div 2 + 2; +- if ItemInfo.Enabled then Canvas.Pen.Color := clBtnText +- else Canvas.Pen.Color := clGrayText; +- Canvas.Polyline([Point(X-2, Y-2), Point(X, Y), Point(X+4, Y-4), +- Point(X+4, Y-3), Point(X, Y+1), Point(X-2, Y-1), Point(X-2, Y-2)]); +- if ItemInfo.Enabled then +- begin +- Canvas.Pen.Color := clBtnHighlight; +- Canvas.Polyline([Point(X-3, Y-2), Point(X-3, Y-1), Point(X, Y+2), +- Point(X+5, Y-3), Point(X+5, Y-5)]); ++ Y := (ARect.Top + ARect.Bottom) div 2 + 1; ++ if ItemInfo.Enabled ++ then C := clBtnText ++ else C := clGrayText; ++ if ItemInfo.ItemOptions and IO_RADIO > 0 then ++ begin ++ RoundRectEx(DC, X-2, Y-4, X+4, Y+2, 2, 2, ++ MixColors(C, clBtnHighlight, 128), clNone); ++ RoundRectEx(DC, X-2, Y-4, X+4, Y+2, 6, 6, C, C); ++ if ItemInfo.Enabled then ++ RoundRectEx(DC, X-3, Y-5, X+5, Y+3, 6, 6, clBtnHighlight, clNone); ++ end ++ else begin ++ PolyLineEx(DC, [Point(X-2, Y-2), Point(X, Y), Point(X+4, Y-4), ++ Point(X+4, Y-3), Point(X, Y+1), Point(X-2, Y-1), Point(X-2, Y-2)], C); ++ if ItemInfo.Enabled then ++ PolyLineEx(DC, [Point(X-3, Y-2), Point(X-3, Y-1), Point(X, Y+2), ++ Point(X+5, Y-3), Point(X+5, Y-5)], clBtnHighlight); + end; + end; + + procedure TTBXDefaultTheme.PaintChevron(Canvas: TCanvas; ARect: TRect; + const ItemInfo: TTBXItemInfo); + const +--- TBXDkPanels.pas 2004-05-29 18:16:02.000000000 +-0400 ++++ TBXDkPanels.pas 2005-08-12 12:24:26.000000000 +-0400 +@@ -18,13 +18,13 @@ + const + { New hit test constants for page scrollers } + HTSCROLLPREV = 30; + HTSCROLLNEXT = 31; + + type +- { TTBXDockablePanel } ++ { TTBXControlMargins } + + TTBXControlMargins = class(TPersistent) + private + FLeft, FTop, FRight, FBottom: Integer; + FOnChange: TNotifyEvent; + procedure SetBottom(Value: Integer); +@@ -47,47 +47,52 @@ + TTBXMultiDock = class(TTBDock) + protected + LastValidRowSize: Integer; + function Accepts(ADockableWindow: TTBCustomDockableWindow): Boolean; override; + procedure ValidateInsert(AComponent: TComponent); override; + public ++ procedure ArrangeToolbars; override; + procedure Paint; override; + procedure ResizeVisiblePanels(NewSize: Integer); +- procedure ArrangeToolbars; override; + end; + + +- { TTBXDockablePanel } ++ { TTBXCustomDockablePanel } + + TDPCaptionRotation = (dpcrAuto, dpcrAlwaysHorz, dpcrAlwaysVert); + TTBXResizingStage = (rsBeginResizing, rsResizing, rsEndResizing); + TTBXDockedResizing = procedure(Sender: TObject; Vertical: Boolean; + var NewSize: Integer; Stage: TTBXResizingStage; var AllowResize: Boolean) of object; + TDockKinds = set of (dkStandardDock, dkMultiDock); + +- TTBXDockablePanel = class(TTBCustomDockableWindow) ++ {TTBXDockablePanel = class(TTBCustomDockableWindow)} {vb-} ++ TTBXCustomDockablePanel = class(TTBCustomDockableWindow) {vb+} + private + FBorderSize: Integer; + FCaptionRotation: TDPCaptionRotation; + FDockedWidth: Integer; + FDockedHeight: Integer; + FEffectiveColor: TColor; + FFloatingWidth: Integer; + FFloatingHeight: Integer; ++ FHorzResizeCursor: TCursor; {vb+} ++ FHorzSplitCursor : TCursor; {vb+} + FIsResizing: Boolean; + FIsSplitting: Boolean; + FMinClientWidth: Integer; + FMinClientHeight: Integer; + FMaxClientWidth: Integer; + FMaxClientHeight: Integer; + FSmoothDockedResize: Boolean; + FSnapDistance: Integer; + FShowCaptionWhenDocked: Boolean; + FSplitHeight: Integer; + FSplitWidth: Integer; + FSupportedDocks: TDockKinds; ++ FVertResizeCursor: TCursor; {vb+} ++ FVertSplitCursor : TCursor; {vb+} + FOnDockedResizing: TTBXDockedResizing; + function CalcSize(ADock: TTBDock): TPoint; + procedure SetBorderSize(Value: Integer); + procedure SetCaptionRotation(Value: TDPCaptionRotation); + procedure SetDockedHeight(Value: Integer); + procedure SetDockedWidth(Value: Integer); +@@ -146,60 +151,96 @@ + function GetFloatingBorderSize: TPoint; override; + procedure ReadPositionData(const Data: TTBReadPositionData); override; + procedure SetBounds(ALeft, ATop, AWidth, AHeight: Integer); override; + procedure UpdateChildColors; + procedure WritePositionData(const Data: TTBWritePositionData); override; + property EffectiveColor: TColor read FEffectiveColor; +- published ++ property CaptionRotation: TDPCaptionRotation read FCaptionRotation write SetCaptionRotation default dpcrAuto; ++ property Color default clNone; ++ property CloseButtonWhenDocked default True; ++ property DblClickUndock default False; + { client size constraints should be restored before other size related properties } + property MaxClientHeight: Integer read FMaxClientHeight write FMaxClientHeight default 0; + property MaxClientWidth: Integer read FMaxClientWidth write FMaxClientWidth default 0; + property MinClientHeight: Integer read FMinClientHeight write SetMinClientHeight default 32; + property MinClientWidth: Integer read FMinClientWidth write SetMinClientWidth default 32; ++ property BorderSize: Integer read FBorderSize write SetBorderSize default 0; ++ property DockedWidth: Integer read FDockedWidth write SetDockedWidth default 128; ++ property DockedHeight: Integer read FDockedHeight write SetDockedHeight default 128; ++ property FloatingWidth: Integer read FFloatingWidth write SetFloatingWidth default 0; ++ property FloatingHeight: Integer read FFloatingHeight write SetFloatingHeight default 0; ++ property Height stored False; ++ property HorzResizeCursor: TCursor read FHorzResizeCursor write FHorzResizeCursor default crSizeWE; {vb+} ++ property HorzSplitCursor: TCursor read FHorzSplitCursor write FHorzSplitCursor default crHSplit; {vb+} ++ property ShowCaptionWhenDocked: Boolean read FShowCaptionWhenDocked write SetShowCaptionWhenDocked default True; ++ property SplitHeight: Integer read FSplitHeight write SetSplitHeight default 0; ++ property SplitWidth: Integer read FSplitWidth write SetSplitWidth default 0; ++ property SupportedDocks: TDockKinds read FSupportedDocks write FSupportedDocks; ++ property SmoothDockedResize: Boolean read FSmoothDockedResize write FSmoothDockedResize default True; ++ property SnapDistance: Integer read FSnapDistance write SetSnapDistance default 0; ++ property VertResizeCursor: TCursor read FVertResizeCursor write FVertResizeCursor default crSizeNS; {vb+} ++ property VertSplitCursor: TCursor read FVertSplitCursor write FVertSplitCursor default crVSplit; {vb+} ++ property Width stored False; ++ property OnDockedResizing: TTBXDockedResizing read FOnDockedResizing write FOnDockedResizing; ++ end; {vb+} + ++ { TTBXDockablePanel } ++ ++ TTBXDockablePanel = class(TTBXCustomDockablePanel) {vb+} ++ published ++ { client size constraints should be restored before other size related properties } ++ property MaxClientHeight; ++ property MaxClientWidth; ++ property MinClientHeight; ++ property MinClientWidth; ++ + property ActivateParent; + property Align; + property Anchors; +- property BorderSize: Integer read FBorderSize write SetBorderSize default 0; ++ property BorderSize; + property BorderStyle; + property Caption; +- property CaptionRotation: TDPCaptionRotation read FCaptionRotation write SetCaptionRotation default dpcrAuto; +- property Color default clNone; ++ property CaptionRotation; ++ property Color; + property CloseButton; +- property CloseButtonWhenDocked default True; ++ property CloseButtonWhenDocked; + property CurrentDock; +- property DblClickUndock default False; ++ property DblClickUndock; + property DefaultDock; + property DockableTo; +- property DockedWidth: Integer read FDockedWidth write SetDockedWidth default 128; +- property DockedHeight: Integer read FDockedHeight write SetDockedHeight default 128; ++ property DockedWidth; ++ property DockedHeight; + property DockMode; + property DockPos; + property DockRow; +- property FloatingWidth: Integer read FFloatingWidth write SetFloatingWidth default 0; +- property FloatingHeight: Integer read FFloatingHeight write SetFloatingHeight default 0; ++ property FloatingWidth; ++ property FloatingHeight; + property FloatingMode; + property Font; +- property Height stored False; ++ property Height; + property HideWhenInactive; ++ property HorzResizeCursor; {vb+} ++ property HorzSplitCursor; {vb+} + property LastDock; + property ParentFont; + property ParentShowHint; + property PopupMenu; + property Resizable; + property ShowCaption; +- property ShowCaptionWhenDocked: Boolean read FShowCaptionWhenDocked write SetShowCaptionWhenDocked default True; ++ property ShowCaptionWhenDocked; + property ShowHint; +- property SplitHeight: Integer read FSplitHeight write SetSplitHeight default 0; +- property SplitWidth: Integer read FSplitWidth write SetSplitWidth default 0; +- property SupportedDocks: TDockKinds read FSupportedDocks write FSupportedDocks; ++ property SplitHeight; ++ property SplitWidth; ++ property SupportedDocks; + property SmoothDrag; +- property SmoothDockedResize: Boolean read FSmoothDockedResize write FSmoothDockedResize default True; +- property SnapDistance: Integer read FSnapDistance write SetSnapDistance default 0; ++ property SmoothDockedResize; ++ property SnapDistance; + property TabOrder; + property UseLastDock; ++ property VertResizeCursor; {vb+} ++ property VertSplitCursor; {vb+} + property Visible; + property Width stored False; + + property OnClose; + property OnCloseQuery; + {$IFDEF JR_D5} +@@ -207,13 +248,13 @@ + {$ENDIF} + property OnDragDrop; + property OnDragOver; + property OnDockChanged; + property OnDockChanging; + property OnDockChangingHidden; +- property OnDockedResizing: TTBXDockedResizing read FOnDockedResizing write FOnDockedResizing; ++ property OnDockedResizing; + property OnMouseDown; + property OnMouseMove; + property OnMouseUp; + property OnMove; + property OnRecreated; + property OnRecreating; +@@ -390,12 +431,13 @@ + end; + + { TTBXLabel } + + TTBXLabel = class(TTBXCustomLabel) + published ++ property Action; {vb+} + property Align; + property Alignment; + property Anchors; + property AutoSize; + property BiDiMode; + property Caption; +@@ -473,12 +515,13 @@ + end; + + { TTBXLink } + + TTBXLink = class(TTBXCustomLink) + published ++ property Action; {vb+} + property Align; + property Alignment; + property Anchors; + property AutoSize; + property BiDiMode; + property Caption; +@@ -617,12 +660,13 @@ + function GetControlsAlignment: TAlignment; override; + end; + + { TTBXButton } + TTBXButton = class(TTBXCustomButton) + published ++ property Action; {vb+} + property Align; + property Alignment; + property GroupIndex; + property AllowAllUnchecked; + property Anchors; + property AutoSize; +@@ -715,12 +759,13 @@ + public + constructor Create(AOwner: TComponent); override; + end; + + TTBXCheckBox = class(TTBXCustomCheckBox) + published ++ property Action; {vb+} + property Align; + property Alignment; + property AllowGrayed; + property Anchors; + property AutoSize; + property BiDiMode; +@@ -800,12 +845,13 @@ + public + constructor Create(AOwner: TComponent); override; + end; + + TTBXRadioButton = class(TTBXCustomRadioButton) + published ++ property Action; {vb+} + property Align; + property Alignment; + property Anchors; + property AutoSize; + property BiDiMode; + property Caption; +@@ -1205,22 +1251,35 @@ + var + NewDockList: TList; + PosData: array of TPosRec; + LeftRight: Boolean; + I, J, K, L, DragIndex, ResizeIndex, ForcedWidth: Integer; + EmptySize, ClientW, ClientH, DockSize, TotalSize, TotalMinimumSize, TotalMaximumSize: Integer; +- DragIndexPos: Integer; ++ {DragIndexPos: Integer;} {vb-} + T: TTBXDockablePanel; + S: TPoint; + CurRowPixel, CurRowSize: Integer; + StretchPanelCount: Integer; + Stretching: Boolean; + AccDelta, Acc: Extended; + Delta, IntAcc: Integer; + MinWidth, MaxWidth, EffectiveMinWidth, EffectiveMaxWidth: Integer; + R: TRect; ++ ++ function IndexOfDraggingToolbar(const List: TList): Integer; {vb+} ++ { Returns index of toolbar in List that's currently being dragged, or -1 } ++ var ++ I: Integer; ++ begin ++ for I := 0 to List.Count-1 do ++ if TTBCustomDockableWindow(List[I]).DragMode then begin ++ Result := I; ++ Exit; ++ end; ++ Result := -1; ++ end; + + procedure GetSizes(Panel: TTBXDockablePanel; out Size, MinSize, MaxSize: Integer); + var + Sz: TPoint; + MinWidth, MinHeight, MaxWidth, MaxHeight: Integer; + begin +@@ -1305,16 +1364,20 @@ + + { Copy DockList to NewDockList, and ensure it is in correct ordering + according to DockRow/DockPos } + NewDockList := TList.Create; + NewDockList.Count := DockList.Count; + for I := 0 to NewDockList.Count - 1 do NewDockList[I] := DockList[I]; +- I := NewDockList.IndexOf(DragToolbar); ++ {I := NewDockList.IndexOf(DragToolbar); {vb-} ++ I := IndexOfDraggingToolbar(NewDockList); {vb+} + ListSortEx(NewDockList, CompareDockPos, nil); +- DragIndex := NewDockList.IndexOf(DragToolbar); +- if (I <> -1) and DragSplitting then ++ {DragIndex := NewDockList.IndexOf(DragToolbar); {vb-} ++ DragIndex := IndexOfDraggingToolbar(NewDockList); {vb+} ++ {if (I <> -1) and DragSplitting then {vb-} ++ if (I <> -1) and ++ TTBCustomDockableWindow(NewDockList[DragIndex]).DragSplitting then {vb+} + begin + { When splitting, don't allow the toolbar being dragged to change + positions in the dock list } + NewDockList.Move(DragIndex, I); + DragIndex := I; + end; +@@ -1345,18 +1408,18 @@ + begin + DragIndex := I; + Break; + end; + + { Count total sizes and set initial positions } +- DragIndexPos := 0; ++ {DragIndexPos := 0;} {vb-} + TotalSize := 0; TotalMinimumSize := 0; TotalMaximumSize := 0; + for I := 0 to Length(PosData) - 1 do + with PosData[I] do + begin +- if I = DragIndex then DragIndexPos := Panel.DockPos; ++ {if I = DragIndex then DragIndexPos := Panel.DockPos;} {vb-} + Pos := TotalSize; + Inc(TotalSize, Size); + Inc(TotalMinimumSize, MinSize); + Inc(TotalMaximumSize, MaxSize); + end; + +@@ -1815,19 +1878,19 @@ + end; + + //----------------------------------------------------------------------------// + + { TTBXDockablePanel } + +-procedure TTBXDockablePanel.AdjustClientRect(var Rect: TRect); ++procedure TTBXCustomDockablePanel.AdjustClientRect(var Rect: TRect); + begin + inherited AdjustClientRect(Rect); + if BorderSize <> 0 then InflateRect(Rect, -BorderSize, -BorderSize); + end; + +-procedure TTBXDockablePanel.BeginDockedSizing(HitTest: Integer); ++procedure TTBXCustomDockablePanel.BeginDockedSizing(HitTest: Integer); + var + OrigPos, OldPos: TPoint; + Msg: TMsg; + DockRect, DragRect, OrigDragRect, OldDragRect: TRect; + NCSizes: TPoint; + EdgeRect, OldEdgeRect: TRect; +@@ -1973,19 +2036,20 @@ + finally + if GetCapture = Handle then ReleaseCapture; + CommitResizing := DoEndDockedResizing(HitTest in [HTTOP, HTBOTTOM]); + if EraseEdgeRect then + begin + DrawDraggingOutline(ScreenDC, Rect(0, 0, 0, 0), OldEdgeRect); +- if CommitResizing then with OldDragRect do +- begin +- BlockSizeUpdate := True; +- if LeftRight then DockedWidth := Right - Left - NCSizes.X +- else DockedHeight := Bottom - Top - NCSizes.Y; +- BlockSizeUpdate := False; +- end; ++ if CommitResizing and not IsRectEmpty(OldDragRect) then ++ with OldDragRect do ++ begin ++ BlockSizeUpdate := True; ++ if LeftRight then DockedWidth := Right - Left - NCSizes.X ++ else DockedHeight := Bottom - Top - NCSizes.Y; ++ BlockSizeUpdate := False; ++ end; + end + else if not CommitResizing then + begin + BlockSizeUpdate := True; + BoundsRect := RectToClient(OrigDragRect); + BlockSizeUpdate := False; +@@ -1997,13 +2061,13 @@ + Form := GetParentForm(Self); + if (Form <> nil) and (Form.Designer <> nil) then Form.Designer.Modified; + end; + end; + end; + +-procedure TTBXDockablePanel.BeginSplitResizing(HitTest: Integer); ++procedure TTBXCustomDockablePanel.BeginSplitResizing(HitTest: Integer); + type + TPosRec = record + Panel: TTBXDockablePanel; + OrigPos, OrigSize, OrigWidth, Pos, Size, MinSize, MaxSize: Integer; + end; + var +@@ -2012,13 +2076,14 @@ + I: Integer; + LeftRight, Smooth, CommitResizing: Boolean; + DockSize, TotalSize, TotalMinSize, TotalMaxSize: Integer; + OrigCursorPos, OldCursorPos: TPoint; + Msg: TMsg; + EffectiveIndex: Integer; +- EffectivePanel: TTBXDockablePanel; ++ {EffectivePanel: TTBXDockablePanel;} {vb-} ++ EffectivePanel: TTBXCustomDockablePanel; {vb+} + PanelRect, DockRect, EdgeRect, OrigEdgeRect, OldEdgeRect: TRect; + EdgePosition: TTBDockPosition; + ScreenDC: HDC; + EraseEdgeRect: Boolean; + Form: TCustomForm; + Delta: Integer; +@@ -2339,13 +2404,13 @@ + Form := GetParentForm(Self); + if (Form <> nil) and (Form.Designer <> nil) then Form.Designer.Modified; + end; + end; + end; + +-function TTBXDockablePanel.CalcNCSizes: TPoint; ++function TTBXCustomDockablePanel.CalcNCSizes: TPoint; + begin + if not Docked then + begin + Result.X := 0; + Result.Y := 0; + end +@@ -2356,13 +2421,13 @@ + if ShowCaptionWhenDocked then + if IsVertCaption then Inc(Result.X, GetSystemMetrics(SM_CYSMCAPTION)) + else Inc(Result.Y, GetSystemMetrics(SM_CYSMCAPTION)); + end; + end; + +-function TTBXDockablePanel.CalcSize(ADock: TTBDock): TPoint; ++function TTBXCustomDockablePanel.CalcSize(ADock: TTBDock): TPoint; + begin + if Assigned(ADock) then + begin + if ADock.Position in [dpLeft, dpRight] then + begin + Result.X := FDockedWidth; +@@ -2395,18 +2460,18 @@ + + Result.X := FFloatingWidth; + Result.Y := FFloatingHeight; + end; + end; + +-function TTBXDockablePanel.CanAutoSize(var NewWidth, NewHeight: Integer): Boolean; ++function TTBXCustomDockablePanel.CanAutoSize(var NewWidth, NewHeight: Integer): Boolean; + begin + Result := True; + end; + +-function TTBXDockablePanel.CanDockTo(ADock: TTBDock): Boolean; ++function TTBXCustomDockablePanel.CanDockTo(ADock: TTBDock): Boolean; + begin + Result := inherited CanDockTo(ADock); + if Result then + begin + if ADock is TTBXMultiDock then + begin +@@ -2416,13 +2481,13 @@ + begin + Result := dkStandardDock in SupportedDocks;; + end; + end; + end; + +-function TTBXDockablePanel.CanSplitResize(EdgePosition: TTBDockPosition): Boolean; ++function TTBXCustomDockablePanel.CanSplitResize(EdgePosition: TTBDockPosition): Boolean; + var + Dock: TDockAccess; + begin + Result := Docked and (CurrentDock is TTBXMultiDock) and HandleAllocated; + if not Result then Exit; + Dock := TDockAccess(CurrentDock); +@@ -2444,60 +2509,64 @@ + else + Result := False; + end; + end; + end; + +-procedure TTBXDockablePanel.CMColorChanged(var Message: TMessage); ++procedure TTBXCustomDockablePanel.CMColorChanged(var Message: TMessage); + begin + UpdateEffectiveColor; + Brush.Color := Color; + if Docked and HandleAllocated then + begin + RedrawWindow(Handle, nil, 0, RDW_FRAME or RDW_INVALIDATE or + RDW_ERASE or RDW_UPDATENOW or RDW_ALLCHILDREN); + end; + Invalidate; + UpdateChildColors; + end; + +-procedure TTBXDockablePanel.CMControlChange(var Message: TCMControlChange); ++procedure TTBXCustomDockablePanel.CMControlChange(var Message: TCMControlChange); + begin + inherited; + if Message.Inserting and (Color = clNone) then + Message.Control.Perform(CM_PARENTCOLORCHANGED, 1, EffectiveColor); + end; + +-procedure TTBXDockablePanel.CMTextChanged(var Message: TMessage); ++procedure TTBXCustomDockablePanel.CMTextChanged(var Message: TMessage); + begin + inherited; + if HandleAllocated then + begin + if Docked then RedrawWindow(Handle, nil, 0, RDW_FRAME or RDW_INVALIDATE) + else RedrawWindow(TTBXFloatingWindowParent(Parent).Handle, nil, 0, RDW_FRAME or RDW_INVALIDATE); + end; + end; + +-procedure TTBXDockablePanel.ConstrainedResize(var MinWidth, MinHeight, MaxWidth, MaxHeight: Integer); ++procedure TTBXCustomDockablePanel.ConstrainedResize(var MinWidth, MinHeight, MaxWidth, MaxHeight: Integer); + var + Sz: TPoint; + begin + Sz := CalcNCSizes; + if MinClientWidth > 0 then MinWidth := MinClientWidth + Sz.X; + if MinClientHeight > 0 then MinHeight := MinClientHeight + Sz.Y; + if MaxClientWidth > 0 then MaxWidth := MaxClientWidth + Sz.X; + if MaxClientHeight > 0 then MaxHeight := MaxClientHeight + Sz.Y; + end; + +-constructor TTBXDockablePanel.Create(AOwner: TComponent); ++constructor TTBXCustomDockablePanel.Create(AOwner: TComponent); + begin + inherited; + FMinClientWidth := 32; + FMinClientHeight := 32; + FDockedWidth := 128; + FDockedHeight := 128; ++ FHorzResizeCursor := crSizeWE; {vb+} ++ FHorzSplitCursor := crHSplit; {vb+} ++ FVertResizeCursor := crSizeNS; {vb+} ++ FVertSplitCursor := crVSplit; {vb+} + CloseButtonWhenDocked := True; + DblClickUndock := False; + FShowCaptionWhenDocked := True; + FSmoothDockedResize := True; + BlockSizeUpdate := True; + SetBounds(Left, Top, 128, 128); +@@ -2505,36 +2574,36 @@ + FullSize := True; + Color := clNone; + AddThemeNotification(Self); + SupportedDocks := [dkStandardDock, dkMultiDock]; + end; + +-destructor TTBXDockablePanel.Destroy; ++destructor TTBXCustomDockablePanel.Destroy; + begin + RemoveThemeNotification(Self); + inherited; + end; + +-function TTBXDockablePanel.DoArrange(CanMoveControls: Boolean; ++function TTBXCustomDockablePanel.DoArrange(CanMoveControls: Boolean; + PreviousDockType: TTBDockType; NewFloating: Boolean; NewDock: TTBDock): TPoint; + begin + Result := CalcSize(NewDock); + end; + +-function TTBXDockablePanel.DoBeginDockedResizing(Vertical: Boolean): Boolean; ++function TTBXCustomDockablePanel.DoBeginDockedResizing(Vertical: Boolean): Boolean; + var + Sz: Integer; + begin + Result := True; + if Vertical then Sz := Height else Sz := Width; + if Assigned(FOnDockedResizing) then FOnDockedResizing(Self, Vertical, Sz, rsBeginResizing, Result); + if Result then + if Vertical then Height := Sz else Width := Sz; + end; + +-function TTBXDockablePanel.DoDockedResizing(Vertical: Boolean; var NewSize: Integer): Boolean; ++function TTBXCustomDockablePanel.DoDockedResizing(Vertical: Boolean; var NewSize: Integer): Boolean; + const + MIN_PARENT_CLIENT_SIZE = 32; + var + NCSizes: TPoint; + CW, CH: Integer; + DockParent: TWinControl; +@@ -2564,25 +2633,25 @@ + NewSize := CH + NCSizes.Y; + end; + Result := True; + if Assigned(FOnDockedResizing) then FOnDockedResizing(Self, Vertical, NewSize, rsResizing, Result); + end; + +-function TTBXDockablePanel.DoEndDockedResizing(Vertical: Boolean): Boolean; ++function TTBXCustomDockablePanel.DoEndDockedResizing(Vertical: Boolean): Boolean; + var + Sz: Integer; + begin + Result := True; + if Vertical then Sz := Height else Sz := Width; + if Assigned(FOnDockedResizing) then + FOnDockedResizing(Self, Vertical, Sz, rsEndResizing, Result); + if Result then + if Vertical then Height := Sz else Width := Sz; + end; + +-procedure TTBXDockablePanel.DrawNCArea(const DrawToDC: Boolean; ++procedure TTBXCustomDockablePanel.DrawNCArea(const DrawToDC: Boolean; + const ADC: HDC; const Clip: HRGN); + var + DC: HDC; + R, CR: TRect; + ACanvas: TCanvas; + Sz: Integer; +@@ -2628,18 +2697,18 @@ + end; + finally + if not DrawToDC then ReleaseDC(Handle, DC); + end; + end; + +-procedure TTBXDockablePanel.GetBaseSize(var ASize: TPoint); ++procedure TTBXCustomDockablePanel.GetBaseSize(var ASize: TPoint); + begin + ASize := CalcSize(CurrentDock); + end; + +-function TTBXDockablePanel.GetDockedCloseButtonRect(LeftRight: Boolean): TRect; ++function TTBXCustomDockablePanel.GetDockedCloseButtonRect(LeftRight: Boolean): TRect; + var + X, Y, Z: Integer; + begin + Z := GetSystemMetrics(SM_CYSMCAPTION) - 1; + if LeftRight or not IsVertCaption then + begin +@@ -2651,13 +2720,13 @@ + X := DockedBorderSize; + Y := ClientHeight + DockedBorderSize - Z; + end; + Result := Bounds(X, Y, Z, Z); + end; + +-procedure TTBXDockablePanel.GetDockPanelInfo(out DockPanelInfo: TTBXDockPanelInfo); ++procedure TTBXCustomDockablePanel.GetDockPanelInfo(out DockPanelInfo: TTBXDockPanelInfo); + begin + FillChar(DockPanelInfo, SizeOf(DockPanelInfo), 0); + DockPanelInfo.WindowHandle := WindowHandle; + DockPanelInfo.ViewType := GetViewType; + if CurrentDock <> nil then DockPanelInfo.IsVertical := not IsVertCaption; + DockPanelInfo.AllowDrag := CurrentDock.AllowDrag; +@@ -2672,105 +2741,105 @@ + DockPanelInfo.CloseButtonState := CDBS_VISIBLE; + if CloseButtonDown then DockPanelInfo.CloseButtonState := DockPanelInfo.CloseButtonState or CDBS_PRESSED; + if CloseButtonHover then DockPanelInfo.CloseButtonState := DockPanelInfo.CloseButtonState or CDBS_HOT; + end; + end; + +-function TTBXDockablePanel.GetFloatingBorderSize: TPoint; ++function TTBXCustomDockablePanel.GetFloatingBorderSize: TPoint; + begin + CurrentTheme.GetViewBorder(GetViewType or DPVT_FLOATING, Result); + end; + +-function TTBXDockablePanel.GetFloatingWindowParentClass: TTBFloatingWindowParentClass; ++function TTBXCustomDockablePanel.GetFloatingWindowParentClass: TTBFloatingWindowParentClass; + begin + Result := TTBXFloatingWindowParent; + end; + +-procedure TTBXDockablePanel.GetMinMaxSize(var AMinClientWidth, AMinClientHeight, ++procedure TTBXCustomDockablePanel.GetMinMaxSize(var AMinClientWidth, AMinClientHeight, + AMaxClientWidth, AMaxClientHeight: Integer); + begin + AMinClientWidth := FMinClientWidth; + AMinClientHeight := FMinClientHeight; + AMaxClientWidth := FMaxClientWidth; + AMaxClientHeight := FMaxClientHeight; + end; + +-function TTBXDockablePanel.GetViewType: Integer; ++function TTBXCustomDockablePanel.GetViewType: Integer; + begin + Result := DPVT_NORMAL; + if Floating then Result := Result or DPVT_FLOATING; + if Resizable then Result := Result or DPVT_RESIZABLE; + end; + +-function TTBXDockablePanel.IsVertCaption: Boolean; ++function TTBXCustomDockablePanel.IsVertCaption: Boolean; + begin + case CaptionRotation of + dpcrAlwaysHorz: Result := False; + dpcrAlwaysVert: Result := Docked; + else // dpcrAuto: + Result := Docked and (CurrentDock.Position in [dpTop, dpBottom]); + end; + end; + +-procedure TTBXDockablePanel.Loaded; ++procedure TTBXCustomDockablePanel.Loaded; + begin + inherited; + UpdateChildColors; + end; + +-procedure TTBXDockablePanel.Paint; ++procedure TTBXCustomDockablePanel.Paint; + begin + if csDesigning in ComponentState then with Canvas do + begin + Pen.Style := psDot; + Pen.Color := clBtnShadow; + Brush.Style := bsClear; + with ClientRect do Rectangle(Left, Top, Right, Bottom); + Pen.Style := psSolid; + end; + end; + +-procedure TTBXDockablePanel.ReadPositionData(const Data: TTBReadPositionData); ++procedure TTBXCustomDockablePanel.ReadPositionData(const Data: TTBReadPositionData); + begin + with Data do + begin + FDockedWidth := ReadIntProc(Name, rvDockedWidth, FDockedWidth, ExtraData); + FDockedHeight := ReadIntProc(Name, rvDockedHeight, FDockedHeight, ExtraData); + FFloatingWidth := ReadIntProc(Name, rvFloatingWidth, FFloatingWidth, ExtraData); + FFloatingHeight := ReadIntProc(Name, rvFloatingHeight, FFloatingHeight, ExtraData); + FSplitWidth := ReadIntProc(Name, rvSplitWidth, FSplitWidth, ExtraData); + FSplitHeight := ReadIntProc(Name, rvSplitHeight, FSplitHeight, ExtraData); + end; + end; + +-procedure TTBXDockablePanel.SetBorderSize(Value: Integer); ++procedure TTBXCustomDockablePanel.SetBorderSize(Value: Integer); + begin + if FBorderSize <> Value then + begin + FBorderSize := Value; + Realign; + end; + end; + +-procedure TTBXDockablePanel.SetBounds(ALeft, ATop, AWidth, AHeight: Integer); ++procedure TTBXCustomDockablePanel.SetBounds(ALeft, ATop, AWidth, AHeight: Integer); + begin + inherited SetBounds(ALeft, ATop, AWidth, AHeight); + end; + +-procedure TTBXDockablePanel.SetCaptionRotation(Value: TDPCaptionRotation); ++procedure TTBXCustomDockablePanel.SetCaptionRotation(Value: TDPCaptionRotation); + begin + if FCaptionRotation <> Value then + begin + FCaptionRotation := Value; + if Docked and HandleAllocated then + SetWindowPos(Handle, 0, 0, 0, 0, 0, SWP_FRAMECHANGED or + SWP_NOACTIVATE or SWP_NOMOVE or SWP_NOSIZE or SWP_NOZORDER); + end; + end; + +-procedure TTBXDockablePanel.SetDockedHeight(Value: Integer); ++procedure TTBXCustomDockablePanel.SetDockedHeight(Value: Integer); + begin + if Value < MinClientHeight then Value := MinClientHeight; + if Value <> FDockedHeight then + begin + FDockedHeight := Value; + if Docked and (CurrentDock.Position in [dpTop, dpBottom]) then +@@ -2779,13 +2848,13 @@ + Height := Value + CalcNCSizes.Y; + BlockSizeUpdate := False; + end; + end; + end; + +-procedure TTBXDockablePanel.SetDockedWidth(Value: Integer); ++procedure TTBXCustomDockablePanel.SetDockedWidth(Value: Integer); + begin + if Value < MinClientWidth then Value := MinClientWidth; + if Value <> FDockedWidth then + begin + FDockedWidth := Value; + if Docked and (CurrentDock.Position in [dpLeft, dpRight]) then +@@ -2794,13 +2863,13 @@ + Width := Value + CalcNCSizes.X; + BlockSizeUpdate := False; + end; + end; + end; + +-procedure TTBXDockablePanel.SetFloatingHeight(Value: Integer); ++procedure TTBXCustomDockablePanel.SetFloatingHeight(Value: Integer); + begin + { FloatingHeight (and floating width) can be set to 0 while panel is docked. + This will force to restore floating dimensions from docked size } + if Value < 0 then Value := 0; + if not Docked and (Value < MinClientHeight) then Value := MinClientHeight; + if Value <> FFloatingHeight then +@@ -2812,13 +2881,13 @@ + Height := Value + CalcNCSizes.Y; + BlockSizeUpdate := False; + end; + end; + end; + +-procedure TTBXDockablePanel.SetFloatingWidth(Value: Integer); ++procedure TTBXCustomDockablePanel.SetFloatingWidth(Value: Integer); + begin + { See comment for TTBXDockablePanel.SetFloatingHeight } + if Value < 0 then Value := 0; + if not Docked and (Value < MinClientWidth) then Value := MinClientWidth; + if Value <> FFloatingWidth then + begin +@@ -2829,32 +2898,32 @@ + Width := Value + CalcNCSizes.X; + BlockSizeUpdate := False; + end; + end; + end; + +-procedure TTBXDockablePanel.SetMinClientHeight(Value: Integer); ++procedure TTBXCustomDockablePanel.SetMinClientHeight(Value: Integer); + begin + if Value < 8 then Value := 8; + FMinClientHeight := Value; + end; + +-procedure TTBXDockablePanel.SetMinClientWidth(Value: Integer); ++procedure TTBXCustomDockablePanel.SetMinClientWidth(Value: Integer); + begin + if Value < 8 then Value := 8; + FMinClientWidth := Value; + end; + +-procedure TTBXDockablePanel.SetParent(AParent: TWinControl); ++procedure TTBXCustomDockablePanel.SetParent(AParent: TWinControl); + begin + inherited; + if AParent is TTBXFloatingWindowParent then + TTBXFloatingWindowParent(AParent).SnapDistance := SnapDistance; + end; + +-procedure TTBXDockablePanel.SetShowCaptionWhenDocked(Value: Boolean); ++procedure TTBXCustomDockablePanel.SetShowCaptionWhenDocked(Value: Boolean); + begin + if FShowCaptionWhenDocked <> Value then + begin + FShowCaptionWhenDocked := Value; + if Docked then + begin +@@ -2862,43 +2931,43 @@ + SetWindowPos(Handle, 0, 0, 0, 0, 0, SWP_FRAMECHANGED or + SWP_NOACTIVATE or SWP_NOMOVE or SWP_NOSIZE or SWP_NOZORDER); + end; + end; + end; + +-procedure TTBXDockablePanel.SetSnapDistance(Value: Integer); ++procedure TTBXCustomDockablePanel.SetSnapDistance(Value: Integer); + begin + if Value < 0 then Value := 0; + FSnapDistance := Value; + if (Parent <> nil) and (Parent is TTBXFloatingWindowParent) then + TTBXFloatingWindowParent(Parent).SnapDistance := Value; + end; + +-procedure TTBXDockablePanel.SetSplitHeight(Value: Integer); ++procedure TTBXCustomDockablePanel.SetSplitHeight(Value: Integer); + begin + if Value < 0 then Value := 0; + if FSplitHeight <> Value then + begin + FSplitHeight := Value; + if Docked and (CurrentDock.Position in [dpLeft, dpRight]) and + (CurrentDock is TTBXMultiDock) then CurrentDock.ArrangeToolbars; + end; + end; + +-procedure TTBXDockablePanel.SetSplitWidth(Value: Integer); ++procedure TTBXCustomDockablePanel.SetSplitWidth(Value: Integer); + begin + if Value < 0 then Value := 0; + if FSplitWidth <> Value then + begin + FSplitWidth := Value; + if Docked and (CurrentDock.Position in [dpTop, dpBottom]) and + (CurrentDock is TTBXMultiDock) then CurrentDock.ArrangeToolbars; + end; + end; + +-procedure TTBXDockablePanel.SizeChanging(const AWidth, AHeight: Integer); ++procedure TTBXCustomDockablePanel.SizeChanging(const AWidth, AHeight: Integer); + begin + if not BlockSizeUpdate then + begin + if Docked and (CurrentDock.Position in [dpLeft, dpRight]) then + FDockedWidth := AWidth - CalcNCSizes.X + else if Floating then +@@ -2908,24 +2977,24 @@ + FDockedHeight := AHeight - CalcNCSizes.Y + else if Floating then + FFloatingHeight := AHeight - CalcNCSizes.Y; + end; + end; + +-procedure TTBXDockablePanel.TBMGetEffectiveColor(var Message: TMessage); ++procedure TTBXCustomDockablePanel.TBMGetEffectiveColor(var Message: TMessage); + begin + Message.WParam := EffectiveColor; + Message.Result := 1; + end; + +-procedure TTBXDockablePanel.TBMGetViewType(var Message: TMessage); ++procedure TTBXCustomDockablePanel.TBMGetViewType(var Message: TMessage); + begin + Message.Result := GetViewType; + end; + +-procedure TTBXDockablePanel.TBMThemeChange(var Message: TMessage); ++procedure TTBXCustomDockablePanel.TBMThemeChange(var Message: TMessage); + var + M: TMessage; + begin + case Message.WParam of + TSC_BEFOREVIEWCHANGE: BeginUpdate; + TSC_AFTERVIEWCHANGE: +@@ -2947,53 +3016,53 @@ + M.Result := 0; + Broadcast(M); + end; + end; + end; + +-procedure TTBXDockablePanel.UpdateChildColors; ++procedure TTBXCustomDockablePanel.UpdateChildColors; + var + M: TMessage; + begin + M.Msg := CM_PARENTCOLORCHANGED; + M.WParam := 1; + M.LParam := EffectiveColor; + M.Result := 0; + Broadcast(M); + end; + +-procedure TTBXDockablePanel.UpdateEffectiveColor; ++procedure TTBXCustomDockablePanel.UpdateEffectiveColor; + begin + if Color = clNone then FEffectiveColor := CurrentTheme.GetViewColor(GetViewType) + else FEffectiveColor := Color; + end; + +-procedure TTBXDockablePanel.WMEraseBkgnd(var Message: TWMEraseBkgnd); ++procedure TTBXCustomDockablePanel.WMEraseBkgnd(var Message: TWMEraseBkgnd); + var + BRUSH: HBRUSH; + begin + BRUSH := CreateSolidBrush(ColorToRGB(EffectiveColor)); + FillRect(Message.DC, Clientrect, BRUSH); + DeleteObject(BRUSH); + Message.Result := 1; + end; + +-procedure TTBXDockablePanel.WMNCCalcSize(var Message: TWMNCCalcSize); ++procedure TTBXCustomDockablePanel.WMNCCalcSize(var Message: TWMNCCalcSize); + begin + Message.Result := 0; + if Docked then + with Message.CalcSize_Params^ do + begin + InflateRect(rgrc[0], -DockedBorderSize, -DockedBorderSize); + if ShowCaptionWhenDocked then + if IsVertCaption then Inc(rgrc[0].Left, GetSystemMetrics(SM_CYSMCAPTION)) + else Inc(rgrc[0].Top, GetSystemMetrics(SM_CYSMCAPTION)) + end; + end; + +-procedure TTBXDockablePanel.WMNCHitTest(var Message: TWMNCHitTest); ++procedure TTBXCustomDockablePanel.WMNCHitTest(var Message: TWMNCHitTest); + const + CResizeMargin = 2; + var + P: TPoint; + R: TRect; + Sz: Integer; +@@ -3072,13 +3141,13 @@ + end; + end; + end + else inherited; + end; + +-procedure TTBXDockablePanel.WMNCLButtonDown(var Message: TWMNCLButtonDown); ++procedure TTBXCustomDockablePanel.WMNCLButtonDown(var Message: TWMNCLButtonDown); + var + OldCursor: HCURSOR; + begin + if Message.HitTest in [HTLEFT..HTBOTTOM] then BeginDockedSizing(Message.HitTest) + else if Message.HitTest in [HT_TBX_SPLITRESIZELEFT..HT_TBX_SPLITRESIZEBOTTOM] then BeginSplitResizing(Message.HitTest) + else +@@ -3093,42 +3162,66 @@ + end; + end + else inherited; + end; + end; + +-procedure TTBXDockablePanel.WMSetCursor(var Message: TWMSetCursor); ++procedure TTBXCustomDockablePanel.WMSetCursor(var Message: TWMSetCursor); ++var Cur: TCursor; {vb+} + begin +- if Docked and CurrentDock.AllowDrag and +- (Message.CursorWnd = WindowHandle) and +- (Smallint(Message.HitTest) = HT_TB2k_Border) and +- ShowCaptionWhenDocked then +- begin +- SetCursor(LoadCursor(0, IDC_ARROW)); +- Message.Result := 1; +- Exit; +- end +- else if Docked and CurrentDock.AllowDrag and (Message.CursorWnd = WindowHandle) then +- begin +- if (Message.HitTest = HT_TBX_SPLITRESIZELEFT) or (Message.HitTest = HT_TBX_SPLITRESIZERIGHT) then +- begin +- SetCursor(LoadCursor(0, IDC_SIZEWE)); +- Message.Result := 1; +- Exit; +- end +- else if (Message.HitTest = HT_TBX_SPLITRESIZETOP) or (Message.HitTest = HT_TBX_SPLITRESIZEBOTTOM) then ++ {if Docked and CurrentDock.AllowDrag and ++ (Message.CursorWnd = WindowHandle) and ++ (Smallint(Message.HitTest) = HT_TB2k_Border) and ++ ShowCaptionWhenDocked then ++ begin ++ SetCursor(LoadCursor(0, IDC_ARROW)); ++ Message.Result := 1; ++ Exit; ++ end ++ else if Docked and CurrentDock.AllowDrag and (Message.CursorWnd = WindowHandle) then ++ begin ++ if (Message.HitTest = HT_TBX_SPLITRESIZELEFT) or (Message.HitTest = HT_TBX_SPLITRESIZERIGHT) then ++ begin ++ SetCursor(LoadCursor(0, IDC_SIZEWE)); ++ Message.Result := 1; ++ Exit; ++ end ++ else if (Message.HitTest = HT_TBX_SPLITRESIZETOP) or (Message.HitTest = HT_TBX_SPLITRESIZEBOTTOM) then ++ begin ++ SetCursor(LoadCursor(0, IDC_SIZENS)); ++ Message.Result := 1; ++ Exit; ++ end; ++ end; } {vb-} ++ if Docked and CurrentDock.AllowDrag and ++ (Message.CursorWnd = WindowHandle) then ++ begin ++ Cur := crNone; ++ case Message.HitTest of ++ HTLEFT, HTRIGHT: ++ Cur := HorzResizeCursor; ++ HTTOP, HTBOTTOM: ++ Cur := VertResizeCursor; ++ HT_TBX_SPLITRESIZELEFT, HT_TBX_SPLITRESIZERIGHT: ++ Cur := HorzSplitCursor; ++ HT_TBX_SPLITRESIZETOP, HT_TBX_SPLITRESIZEBOTTOM: ++ Cur := VertSplitCursor; ++ HT_TB2k_Border: ++ if ShowCaptionWhenDocked then Cur := crArrow; ++ end; ++ if Cur <> crNone then + begin +- SetCursor(LoadCursor(0, IDC_SIZENS)); ++ SetCursor(Screen.Cursors[Cur]); + Message.Result := 1; + Exit; + end; + end; + inherited; + end; + +-procedure TTBXDockablePanel.WMWindowPosChanged(var Message: TWMWindowPosChanged); ++procedure TTBXCustomDockablePanel.WMWindowPosChanged(var Message: TWMWindowPosChanged); + begin + inherited; + if (Message.WindowPos^.flags and SWP_NOSIZE) = 0 then + begin + Realign; + Update; +@@ -3137,13 +3230,13 @@ + begin + UpdateEffectiveColor; + UpdateChildColors; + end; + end; + +-procedure TTBXDockablePanel.WritePositionData(const Data: TTBWritePositionData); ++procedure TTBXCustomDockablePanel.WritePositionData(const Data: TTBWritePositionData); + begin + with Data do + begin + WriteIntProc(Name, rvDockedWidth, FDockedWidth, ExtraData); + WriteIntProc(Name, rvDockedHeight, FDockedHeight, ExtraData); + WriteIntProc(Name, rvFloatingWidth, FFloatingWidth, ExtraData); +@@ -3214,13 +3307,13 @@ + AdjustHeight; + end; + + constructor TTBXTextObject.Create(AOwner: TComponent); + begin + inherited; +- ControlStyle := ControlStyle + [csSetCaption] - [csDoubleClicks]; ++ ControlStyle := ControlStyle + [csSetCaption, csDoubleClicks]; + FMargins := TTBXControlMargins.Create; + FMargins.OnChange := MarginsChangeHandler; + FShowAccelChar := True; + PaintOptions := [cpoDoubleBuffered]; + AutoSize := True; + Width := 100; +--- TBXExtItems.pas 2004-05-25 22:02:56.000000000 +-0400 ++++ TBXExtItems.pas 2005-08-11 13:41:06.000000000 +-0400 +@@ -645,13 +645,14 @@ + begin + Edit.Text := S2; + Edit.SelStart := Length(S); + Edit.SelLength := Length(S2) - Length(S); + S := S2; + end; +- if S <> FLastEditChange then ++ {if S <> FLastEditChange then} {vb-} ++ if AnsiCompareText(S, FLastEditChange) <> 0 then {vb+} + begin + DoChange(S); // note, Edit.Text may be different from Self.Text + FLastEditChange := S; + end; + finally + FIsChanging := False; +@@ -1121,13 +1122,16 @@ + function TTBXDropDownItemViewer.HandleEditMessage(var Message: TMessage): Boolean; + begin + if Message.Msg = WM_KEYDOWN then + begin + if TWMKeyDown(Message).CharCode = VK_F4 then + begin +- TTBViewAccess(View).OpenChildPopup(True); ++ {TTBViewAccess(View).OpenChildPopup(True);} {vb-} ++ if (View.OpenViewer = Self) // WasAlreadyOpen {vb+} ++ then View.CloseChildPopups ++ else View.OpenChildPopup(True); + Result := True; + Exit; + end; + end; + + Result := inherited HandleEditMessage(Message); +@@ -1399,21 +1403,23 @@ + begin + if (Message.Msg = WM_KEYDOWN) then with TTBXComboBoxItem(Item) do + begin + case Message.wParam of + VK_UP: + begin +- ItemIndex := ItemIndex - 1; ++ if ItemIndex > 0 then {vb+} ++ ItemIndex := ItemIndex- 1; + EditControl.Text := Text; + EditControl.SelectAll; + Result := True; + end; + + VK_DOWN: + begin +- ItemIndex := ItemIndex + 1; ++ if ItemIndex < Strings.Count- 1 then {vb+} ++ ItemIndex := ItemIndex+ 1; + EditControl.Text := Text; + EditControl.SelectAll; + Result := True; + end; + else + Result := inherited HandleEditMessage(Message); +--- TBXLists.pas 2004-02-21 02:07:54.000000000 +-0400 ++++ TBXLists.pas 2005-08-07 00:27:10.000000000 +-0400 +@@ -188,12 +188,14 @@ + procedure MouseMove(X, Y: Integer); override; + procedure MouseUp(X, Y: Integer; MouseWasDownOnMenu: Boolean); override; + procedure MouseWheel(WheelDelta: Integer; X, Y: Integer); override; + procedure Paint(const Canvas: TCanvas; const ClientAreaRect: TRect; IsHoverItem, IsPushed, UseDisabledShadow: Boolean); override; + procedure UpdateItems; + property HoverIndex: Integer read FHoverIndex write FHoverIndex; ++ property Offset: Integer read FOffset; {vb+} ++ property VisibleItems: Integer read FVisibleItems; {vb+} + public + constructor Create(AView: TTBView; AItem: TTBCustomItem; AGroupLevel: Integer); override; + destructor Destroy; override; + end; + + { TTBXStringList } +--- TBXOfficeXPTheme.pas 2004-05-25 22:02:56.000000000 +-0400 ++++ TBXOfficeXPTheme.pas 2005-08-05 17:41:38.000000000 +-0400 +@@ -11,12 +11,14 @@ + {$I TB2Ver.inc} + {$I TBX.inc} + + uses + Windows, Messages, Graphics, TBXThemes, TBXDefaultTheme, ImgList; + ++{$DEFINE ALTERNATIVE_DISABLED_STYLE} // remove the asterisk to change appearance of disabled images ++ + type + TItemPart = (ipBody, ipText, ipFrame); + TBtnItemState = (bisNormal, bisDisabled, bisSelected, bisPressed, bisHot, + bisDisabledHot, bisSelectedHot, bisPopupParent); + TMenuItemState = (misNormal, misDisabled, misHot, misDisabledHot); + TWinFramePart = (wfpBorder, wfpCaption, wfpCaptionText); +@@ -361,19 +363,29 @@ + Brush.Style := bsSolid; + end; + end; + + procedure TTBXOfficeXPTheme.PaintCheckMark(Canvas: TCanvas; ARect: TRect; const ItemInfo: TTBXItemInfo); + var ++ DC: HDC; + X, Y: Integer; ++ C: TColor; + begin +- X := (ARect.Left + ARect.Right) div 2 - 2; ++ DC := Canvas.Handle; ++ X := (ARect.Left + ARect.Right) div 2 - 1; + Y := (ARect.Top + ARect.Bottom) div 2 + 1; +- Canvas.Pen.Color := GetBtnColor(ItemInfo, ipText); +- Canvas.Polyline([Point(X-2, Y-2), Point(X, Y), Point(X+4, Y-4), +- Point(X+4, Y-3), Point(X, Y+1), Point(X-2, Y-1), Point(X-2, Y-2)]); ++ C := GetBtnColor(ItemInfo, ipText); ++ if ItemInfo.ItemOptions and IO_RADIO > 0 then ++ begin ++ RoundRectEx(DC, X-2, Y-4, X+4, Y+2, 2, 2, ++ MixColors(C, ToolbarColor, 200), clNone); ++ RoundRectEx(DC, X-2, Y-4, X+4, Y+2, 6, 6, C, C); ++ end ++ else ++ PolylineEx(DC, [Point(X-2, Y-2), Point(X, Y), Point(X+4, Y-4), ++ Point(X+4, Y-3), Point(X, Y+1), Point(X-2, Y-1), Point(X-2, Y-2)], C); + end; + + procedure TTBXOfficeXPTheme.PaintChevron(Canvas: TCanvas; ARect: TRect; const ItemInfo: TTBXItemInfo); + const + Pattern: array[Boolean, 0..15] of Byte = ( + ($CC, 0, $66, 0, $33, 0, $66, 0, $CC, 0, 0, 0, 0, 0, 0, 0), +--- TBXReg.pas 2004-05-25 22:02:56.000000000 +-0400 ++++ TBXReg.pas 2004-12-16 20:22:26.000000000 +-0400 +@@ -432,12 +432,13 @@ + {$ENDIF} + + + RegisterComponentEditor(TTBXToolbar, TTBXItemsEditor); + RegisterComponentEditor(TTBXPopupMenu, TTBXItemsEditor); + RegisterPropertyEditor(TypeInfo(string), TTBXCustomItem, 'Caption', TMLStringProperty); ++ RegisterPropertyEditor(TypeInfo(string), TTBXCustomItem, 'Hint', TMLStringProperty); + RegisterPropertyEditor(TypeInfo(string), TTBXLabelItem, 'Caption', TCaptionProperty); + RegisterPropertyEditor(TypeInfo(string), TTBToolbar, 'ChevronHint', TMLStringProperty); + RegisterPropertyEditor(TypeInfo(string), TTBXToolbar, 'ChevronHint', TMLStringProperty); + RegisterPropertyEditor(TypeInfo(string), TTBXSwitcher, 'Theme', TThemeProperty); + {$IFDEF JR_D5} + RegisterPropertyEditor(TypeInfo(TImageIndex), TTBXCustomLink, 'ImageIndex', TTBXLinkImageIndexPropertyEditor); +--- TBXStrEdit.pas 2004-02-21 02:07:54.000000000 +-0400 ++++ TBXStrEdit.pas 2005-08-12 10:11:16.000000000 +-0400 +@@ -29,15 +29,15 @@ + procedure TStrEditDlg.ArrangeControls; + var + R, B: TRect; + W, H: Integer; + begin + R := ClientRect; +- InflateRect(R, -16, -16); ++ InflateRect(R, -6, -6); + B := R; +- W := 60; H := 23; ++ W := 70; H := 23; + B.Left := B.Right - W; + B.Top := B.Bottom - H; + Cancel.BoundsRect := B; + B.Right := B.Left - 4; + B.Left := B.Right - W; + OK.BoundsRect := B; +@@ -46,33 +46,38 @@ + end; + + constructor TStrEditDlg.Create(AOwner: TComponent); + begin + inherited CreateNew(AOwner); + AutoScroll := False; ++ Constraints.MinHeight := 200; ++ Constraints.MinWidth := 300; + Scaled := False; + Position := poScreenCenter; + Memo := TMemo.Create(Self); + with Memo do + begin + ScrollBars := ssBoth; + OnKeyDown := MemoKeyDown; ++ Parent := Self; + end; + OK := TButton.Create(Self); + with OK do + begin + Caption := 'OK'; + Default := True; + ModalResult := mrOk; ++ Parent := Self; + end; + Cancel := TButton.Create(Self); + with Cancel do + begin + Cancel := True; + Caption := 'Cancel'; + ModalResult := mrCancel; ++ Parent := Self; + end; + end; + + procedure TStrEditDlg.MemoKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); + begin + if Key = VK_ESCAPE then Cancel.Click; +--- TBXThemes.pas 2004-05-25 22:02:56.000000000 +-0400 ++++ TBXThemes.pas 2004-12-17 08:47:16.000000000 +-0400 +@@ -100,12 +100,13 @@ + const + IO_TOOLBARSTYLE = $01; + IO_SUBMENUITEM = $04; + IO_COMBO = $08; + IO_DESIGNING = $10; + IO_APPACTIVE = $20; // True when Application.Active = True ++ IO_RADIO = $40; + + { Drag handle styles } + const + DHS_DOUBLE = 0; + DHS_NONE = 1; + DHS_SINGLE = 2; +--- TBXUtils.pas 2004-04-01 03:22:58.000000000 +-0400 ++++ TBXUtils.pas 2005-08-14 04:51:58.000000000 +-0400 +@@ -21,12 +21,15 @@ + function EscapeAmpersandsW(const S: WideString): WideString; + function FindAccelCharW(const S: WideString): WideChar; + function StripAccelCharsW(const S: WideString): WideString; + function StripTrailingPunctuationW(const S: WideString): WideString; + {$ENDIF} + ++{$IFNDEF JR_D6} ++function CheckWin32Version(AMajor, AMinor: Integer = 0): Boolean; {vb+} ++{$ENDIF} + procedure GetRGB(C: TColor; out R, G, B: Integer); + function MixColors(C1, C2: TColor; W1: Integer): TColor; + function SameColors(C1, C2: TColor): Boolean; + function Lighten(C: TColor; Amount: Integer): TColor; + function NearestLighten(C: TColor; Amount: Integer): TColor; + function NearestMixedColor(C1, C2: TColor; W1: Integer): TColor; +@@ -47,12 +50,14 @@ + function CreateDitheredBrush(C1, C2: TColor): HBrush; + function FillRectEx(DC: HDC; const Rect: TRect; Color: TColor): Boolean; {$IFDEF COMPATIBLE_GFX}overload;{$ENDIF} + function FrameRectEx(DC: HDC; var Rect: TRect; Color: TColor; Adjust: Boolean): Boolean; {$IFDEF COMPATIBLE_GFX}overload;{$ENDIF} + procedure DrawLineEx(DC: HDC; X1, Y1, X2, Y2: Integer; Color: TColor); {$IFDEF COMPATIBLE_GFX}overload;{$ENDIF} + function PolyLineEx(DC: HDC; const Points: array of TPoint; Color: TColor): Boolean; + procedure PolygonEx(DC: HDC; const Points: array of TPoint; OutlineColor, FillColor: TColor); ++procedure RoundRectEx(DC: HDC; Left, Top, Right, Bottom: Integer; EllipseWidth, EllipseHeight, OutlineColor, FillColor: TColor); overload; {vb+} ++procedure RoundRectEx(DC: HDC; const R: TRect; EllipseWidth, EllipseHeight, OutlineColor, FillColor: TColor); overload; {vb+} + procedure DitherRect(DC: HDC; const R: TRect; C1, C2: TColor); {$IFDEF COMPATIBLE_GFX}overload;{$ENDIF} + procedure Frame3D(DC: HDC; var Rect: TRect; TopColor, BottomColor: TColor; Adjust: Boolean); {$IFDEF COMPATIBLE_GFX}overload;{$ENDIF} + procedure DrawDraggingOutline(DC: HDC; const NewRect, OldRect: TRect); + + { Gradients } + type +@@ -393,13 +398,19 @@ + else if (L > 3) and (Result[L - 2] = '.') and (Result[L - 1] = '.') and + (Result[L] = '.') then SetLength(Result, L - 3); + end; + + {$ENDIF} + +- ++{$IFNDEF JR_D6} ++function CheckWin32Version(AMajor, AMinor: Integer = 0): Boolean; {vb+} ++begin ++ Result := (Win32MajorVersion > AMajor) or ++ ((Win32MajorVersion = AMajor) and (Win32MinorVersion >= AMinor)); ++end; ++{$ENDIF} + + type + PPoints = ^TPoints; + TPoints = array [0..0] of TPoint; + + const +@@ -541,13 +552,13 @@ + begin + i1 := ColorDistance(AColor, $000000); + i2 := ColorDistance(ABkgndColor, $000000); + Threshold := GetAdjustedThreshold(i2, Threshold); + + if i1 > i2 then DoInvert := i2 < 442 - Threshold +- else DoInvert := i2 < Threshold; ++ else DoInvert := i2 < Threshold; + + x := (ABkgndColor and $FF) * WeightR; + y := (ABkgndColor shr 8 and $FF) * WeightG; + z := (ABkgndColor shr 16) * WeightB; + + r := (AColor and $FF) * WeightR; +@@ -728,27 +739,31 @@ + begin + if Color = clNone then + begin + LB.lbStyle := BS_HOLLOW; + Result := CreateBrushIndirect(LB); + end +- else if Color < 0 then Result := GetSysColorBrush(Color and $000000FF) +- else Result := CreateSolidBrush(Color); ++ {else if Color < 0 then Result := GetSysColorBrush(Color and $000000FF)} {vb-} ++ else begin {vb+} ++ if Color < 0 then Color := GetSysColor(Color and $000000FF); ++ Result := CreateSolidBrush(Color); ++ end; + end; + + function FillRectEx(DC: HDC; const Rect: TRect; Color: TColor): Boolean; + var + Brush: HBRUSH; + begin + Result := Color <> clNone; + if Result then + begin + if Color < 0 then Brush := GetSysColorBrush(Color and $000000FF) + else Brush := CreateSolidBrush(Color); + Windows.FillRect(DC, Rect, Brush); +- DeleteObject(Brush); ++ {DeleteObject(Brush);} {vb-} ++ if Color >= 0 then DeleteObject(Brush); {vb+} + end; + end; + + function FrameRectEx(DC: HDC; var Rect: TRect; Color: TColor; Adjust: Boolean): Boolean; + var + Brush: HBRUSH; +@@ -756,13 +771,14 @@ + Result := Color <> clNone; + if Result then + begin + if Color < 0 then Brush := GetSysColorBrush(Color and $000000FF) + else Brush := CreateSolidBrush(Color); + Windows.FrameRect(DC, Rect, Brush); +- DeleteObject(Brush); ++ {DeleteObject(Brush);} {vb-} ++ if Color >= 0 then DeleteObject(Brush); {vb+} + end; + if Adjust then with Rect do + begin + Inc(Left); Dec(Right); + Inc(Top); Dec(Bottom); + end; +@@ -810,12 +826,38 @@ + SelectObject(DC, OldBrush); + SelectObject(DC, OldPen); + DeleteObject(Brush); + DeleteObject(Pen); + end; + ++procedure RoundRectEx(DC: HDC; Left, Top, Right, Bottom: Integer; ++ EllipseWidth, EllipseHeight, OutlineColor, FillColor: TColor); {vb+} ++var ++ OldBrush, Brush: HBrush; ++ OldPen, Pen: HPen; ++begin ++ if (OutlineColor = clNone) and (FillColor = clNone) then Exit; ++ Pen := CreatePenEx(OutlineColor); ++ Brush := CreateBrushEx(FillColor); ++ OldPen := SelectObject(DC, Pen); ++ OldBrush := SelectObject(DC, Brush); ++ Windows.RoundRect(DC, Left, Top, Right, Bottom, EllipseWidth, EllipseHeight); ++ SelectObject(DC, OldBrush); ++ SelectObject(DC, OldPen); ++ DeleteObject(Brush); ++ DeleteObject(Pen); ++end; ++ ++procedure RoundRectEx(DC: HDC; const R: TRect; EllipseWidth, EllipseHeight, ++ OutlineColor, FillColor: TColor); {vb+} ++begin ++ with R do ++ RoundRectEx(DC, Left, Top, Right, Bottom, EllipseWidth, ++ EllipseHeight, OutlineColor, FillColor); ++end; ++ + function CreateDitheredBrush(C1, C2: TColor): HBrush; + var + B: TBitmap; + begin + B := AllocPatternBitmap(C1, C2); + B.HandleType := bmDDB; +@@ -949,26 +991,25 @@ + POP EDI + POP ESI + end; + + procedure DrawTBXIcon(Canvas: TCanvas; const R: TRect; + ImageList: TCustomImageList; ImageIndex: Integer; HiContrast: Boolean); +-const +- CWeirdColor = $00203241; ++{const ++ CWeirdColor = $00203241;} {vb -} + var + ImageWidth, ImageHeight: Integer; + I, J: Integer; + Src, Dst: PColor; + S, C: TColor; + begin + if not HiContrast then + begin + ImageList.Draw(Canvas, R.Left, R.Top, ImageIndex); + Exit; + end; +- + ImageWidth := R.Right - R.Left; + ImageHeight := R.Bottom - R.Top; + with ImageList do + begin + if Width < ImageWidth then ImageWidth := Width; + if Height < ImageHeight then ImageHeight := Height; +@@ -978,27 +1019,33 @@ + StockBitmap1.Height := ImageHeight; + StockBitmap2.Width := ImageWidth; + StockBitmap2.Height := ImageHeight; + + BitBlt(StockBitmap1.Canvas.Handle, 0, 0, ImageWidth, ImageHeight, + Canvas.Handle, R.Left, R.Top, SRCCOPY); +- for J := 0 to ImageHeight - 1 do +- FillLongWord(StockBitmap2.ScanLine[J]^, ImageWidth, CWeirdColor); ++ {for J := 0 to ImageHeight - 1 do ++ FillLongWord(StockBitmap2.ScanLine[J]^, ImageWidth, CWeirdColor);} {vb -} ++ BitBlt(StockBitmap2.Canvas.Handle, 0, 0, ImageWidth, ImageHeight, ++ Canvas.Handle, R.Left, R.Top, SRCCOPY); {vb +} + ImageList.Draw(StockBitmap2.Canvas, 0, 0, ImageIndex); + + for J := 0 to ImageHeight - 1 do + begin + Src := StockBitmap2.ScanLine[J]; + Dst := StockBitmap1.ScanLine[J]; + for I := 0 to ImageWidth - 1 do + begin +- S := Src^ and $00FFFFFF; +- if S <> CWeirdColor then ++ {S := Src^ and $00FFFFFF;} {vb -} ++ S := Src^; {vb +} ++ {if S <> CWeirdColor then} {vb -} ++ if S <> Dst^ then {vb +} + begin +- C := (S and $FF0000) shr 16 * 76 + (S and $00FF00) shr 8 * 150 + +- (S and $0000FF) * 29; ++ {C := (S and $FF0000) shr 16 * 76 + (S and $00FF00) shr 8 * 150 + ++ (S and $0000FF) * 29;} {vb -} ++ C := (S and $00FF0000) shr 16 * 76 + (S and $0000FF00) shr 8 * 150 + ++ (S and $000000FF) * 29; {vb +} + if C > $FD00 then S := $000000 + else if C < $6400 then S := $FFFFFF; + Dst^ := Lighten(S, 32); + end; + Inc(Src); + Inc(Dst); +@@ -1007,14 +1054,14 @@ + BitBlt(Canvas.Handle, R.Left, R.Top, ImageWidth, ImageHeight, + StockBitmap1.Canvas.Handle, 0, 0, SRCCOPY); + end; + + procedure BlendTBXIcon(Canvas: TCanvas; const R: TRect; + ImageList: TCustomImageList; ImageIndex: Integer; Opacity: Byte); +-const +- CWeirdColor = $00203241; ++{const ++ CWeirdColor = $00203241;} {vb -} + var + ImageWidth, ImageHeight: Integer; + I, J: Integer; + Src, Dst: ^Cardinal; + S, C, CBRB, CBG: Cardinal; + Wt1, Wt2: Cardinal; +@@ -1033,14 +1080,16 @@ + StockBitmap1.Height := ImageHeight; + StockBitmap2.Width := ImageWidth; + StockBitmap2.Height := ImageHeight; + + BitBlt(StockBitmap1.Canvas.Handle, 0, 0, ImageWidth, ImageHeight, + Canvas.Handle, R.Left, R.Top, SRCCOPY); ++ {BitBlt(StockBitmap2.Canvas.Handle, 0, 0, ImageWidth, ImageHeight, ++ StockBitmap1.Canvas.Handle, 0, 0, SRCCOPY);} {vb -} + BitBlt(StockBitmap2.Canvas.Handle, 0, 0, ImageWidth, ImageHeight, +- StockBitmap1.Canvas.Handle, 0, 0, SRCCOPY); ++ Canvas.Handle, R.Left, R.Top, SRCCOPY); {vb +} + ImageList.Draw(StockBitmap2.Canvas, 0, 0, ImageIndex, True); + + for J := 0 to ImageHeight - 1 do + begin + Src := StockBitmap2.ScanLine[J]; + Dst := StockBitmap1.ScanLine[J]; +@@ -1048,31 +1097,35 @@ + begin + S := Src^; + if S <> Dst^ then + begin + CBRB := (Dst^ and $00FF00FF) * Wt1; + CBG := (Dst^ and $0000FF00) * Wt1; +- C := ((S and $FF00FF) * Wt2 + CBRB) and $FF00FF00 + ((S and $00FF00) * Wt2 + CBG) and $00FF0000; ++ {C := ((S and $FF00FF) * Wt2 + CBRB) and $FF00FF00 + ++ ((S and $00FF00) * Wt2 + CBG) and $00FF0000;} {vb -} ++ C := ((S and $00FF00FF) * Wt2 + CBRB) and $FF00FF00 + ++ ((S and $0000FF00) * Wt2 + CBG) and $00FF0000; {vb +} + Dst^ := C shr 8; + end; + Inc(Src); + Inc(Dst); + end; + end; + BitBlt(Canvas.Handle, R.Left, R.Top, ImageWidth, ImageHeight, + StockBitmap1.Canvas.Handle, 0, 0, SRCCOPY); + end; + + procedure HighlightTBXIcon(Canvas: TCanvas; const R: TRect; + ImageList: TCustomImageList; ImageIndex: Integer; HighlightColor: TColor; Amount: Byte); +-const +- CWeirdColor = $00203241; ++{const ++ CWeirdColor = $00203241;} {vb -} + var + ImageWidth, ImageHeight: Integer; + I, J: Integer; +- Src, Dst: PColor; ++ {Src, Dst: PColor;} {vb -} ++ Src, Dst: ^Cardinal; {vb +} + S, C: Cardinal; + CBRB, CBG: Cardinal; + W1, W2: Cardinal; + begin + ImageWidth := R.Right - R.Left; + ImageHeight := R.Bottom - R.Top; +@@ -1086,14 +1139,16 @@ + StockBitmap1.Height := ImageHeight; + StockBitmap2.Width := ImageWidth; + StockBitmap2.Height := ImageHeight; + + BitBlt(StockBitmap1.Canvas.Handle, 0, 0, ImageWidth, ImageHeight, + Canvas.Handle, R.Left, R.Top, SRCCOPY); +- for J := 0 to ImageHeight - 1 do +- FillLongWord(StockBitmap2.ScanLine[J]^, ImageWidth, CWeirdColor); ++ {for J := 0 to ImageHeight - 1 do ++ FillLongWord(StockBitmap2.ScanLine[J]^, ImageWidth, CWeirdColor);} {vb -} ++ BitBlt(StockBitmap2.Canvas.Handle, 0, 0, ImageWidth, ImageHeight, ++ Canvas.Handle, R.Left, R.Top, SRCCOPY); {vb +} + ImageList.Draw(StockBitmap2.Canvas, 0, 0, ImageIndex); + + W2 := Amount; + W1 := 255 - W2; + HighlightColor := GetBGR(ColorToRGB(HighlightColor)); + CBRB := (Cardinal(HighlightColor) and $00FF00FF) * W1; +@@ -1102,16 +1157,21 @@ + for J := 0 to ImageHeight - 1 do + begin + Src := StockBitmap2.ScanLine[J]; + Dst := StockBitmap1.ScanLine[J]; + for I := 0 to ImageWidth - 1 do + begin +- S := Src^ and $00FFFFFF; +- if S <> CWeirdColor then ++ {S := Src^ and $00FFFFFF;} {vb -} ++ S := Src^; {vb +} ++ {if S <> CWeirdColor then} {vb -} ++ if S <> Dst^ then {vb +} + begin +- C := ((S and $FF00FF) * W2 + CBRB) and $FF00FF00 + ((S and $00FF00) * W2 + CBG) and $00FF0000; ++ {C := ((S and $FF00FF) * W2 + CBRB) and $FF00FF00 + ++ ((S and $00FF00) * W2 + CBG) and $00FF0000;} {vb -} ++ C := ((S and $00FF00FF) * W2 + CBRB) and $FF00FF00 + ++ ((S and $0000FF00) * W2 + CBG) and $00FF0000; {vb +} + Dst^ := C shr 8; + end; + Inc(Src); + Inc(Dst); + end; + end; +@@ -1144,14 +1204,16 @@ + StockBitmap1.Height := ImageHeight; + StockBitmap2.Width := ImageWidth; + StockBitmap2.Height := ImageHeight; + + BitBlt(StockBitmap1.Canvas.Handle, 0, 0, ImageWidth, ImageHeight, + Canvas.Handle, R.Left, R.Top, SRCCOPY); ++ {BitBlt(StockBitmap2.Canvas.Handle, 0, 0, ImageWidth, ImageHeight, ++ StockBitmap1.Canvas.Handle, 0, 0, SRCCOPY);} {vb -} + BitBlt(StockBitmap2.Canvas.Handle, 0, 0, ImageWidth, ImageHeight, +- StockBitmap1.Canvas.Handle, 0, 0, SRCCOPY); ++ Canvas.Handle, R.Left, R.Top, SRCCOPY); {vb +} + ImageList.Draw(StockBitmap2.Canvas, 0, 0, ImageIndex, True); + + for J := 0 to ImageHeight - 1 do + begin + Src := StockBitmap2.ScanLine[J]; + Dst := StockBitmap1.ScanLine[J]; +@@ -1159,14 +1221,16 @@ + begin + S := Src^; + if S <> Dst^ then + begin + CBRB := Dst^ and $00FF00FF; + CBG := Dst^ and $0000FF00; +- C := ((S and $FF0000) shr 16 * 29 + (S and $00FF00) shr 8 * 150 + +- (S and $0000FF) * 76) shr 8; ++ {C := ((S and $FF0000) shr 16 * 29 + (S and $00FF00) shr 8 * 150 + ++ (S and $0000FF) * 76) shr 8;} {vb -} ++ C := ((S and $00FF0000) shr 16 * 29 + (S and $0000FF00) shr 8 * 150 + ++ (S and $000000FF) * 76) shr 8; {vb +} + C := C div D_DIV[Density] + D_ADD[Density]; + Dst^ := ((CBRB * C and $FF00FF00) or (CBG * C and $00FF0000)) shr 8; + end; + Inc(Src); + Inc(Dst); + end; +@@ -1938,13 +2002,13 @@ + Size, I, Start, Finish: Integer; + GradIndex: Integer; + R, CR: TRect; + Brush: HBRUSH; + begin + if not RectVisible(DC, ARect) then Exit; +- ++ + ClrTopLeft := ColorToRGB(ClrTopLeft); + ClrBottomRight := ColorToRGB(ClrBottomRight); + if @GradientFill <> nil then + begin + { Use msimg32.dll } + with V[0] do +@@ -2085,18 +2149,24 @@ + NextCacheEntry: Integer = 0; + + procedure ClearCacheItem(var CacheItem: TThreadCacheItem); + var + I: Integer; + begin +- for I := NUM_TEMPLATES - 1 downto 0 do +- begin +- CacheItem.BaseColor := $FFFFFFFF; +- CacheItem.Roughness := -1; +- if CacheItem.Bitmaps[I] <> 0 then DeleteObject(CacheItem.Bitmaps[I]); +- CacheItem.Bitmaps[I] := 0; ++ with CacheItem do ++ begin ++ BaseColor := $FFFFFFFF; ++ Roughness := -1; ++ for I := NUM_TEMPLATES - 1 downto 0 do ++ begin ++ if Bitmaps[I] <> 0 then ++ begin ++ DeleteObject(Bitmaps[I]); ++ Bitmaps[I] := 0; ++ end; ++ end; + end; + end; + + procedure ResetBrushedFillCache; + var + I: Integer; +@@ -2235,29 +2305,25 @@ + DeleteDC(CacheDC); + + RestoreDC(DC, -1); + end; + + var +- hUser, hMSImg: HModule; ++ hMSImg: HModule; + + initialization +- +-hUser := LoadLibrary('user32.dll'); +-hMSImg := LoadLibrary('msimg32.dll'); +-@UpdateLayeredWindow := GetProcAddress(hUser, 'UpdateLayeredWindow'); +-@AlphaBlend := GetProcAddress(hMSImg, 'AlphaBlend'); +-@GradientFill := GetProcAddress(hMSImg, 'GradientFill'); +- +-InitializeStock; +-InitializeBrushedFill; +-ResetBrushedFillCache; +- ++ @UpdateLayeredWindow := GetProcAddress( ++ GetModuleHandle('user32.dll'), 'UpdateLayeredWindow'); ++ hMSImg := LoadLibrary('msimg32.dll'); ++ if hMSImg <> 0 then ++ begin ++ @AlphaBlend := GetProcAddress(hMSImg, 'AlphaBlend'); ++ @GradientFill := GetProcAddress(hMSImg, 'GradientFill'); ++ end; ++ InitializeStock; ++ InitializeBrushedFill; ++ ResetBrushedFillCache; + finalization +- +-FinalizeBrushedFill; +-FinalizeStock; +- +-FreeLibrary(hMSImg); +-FreeLibrary(hUser); +- ++ FinalizeBrushedFill; ++ FinalizeStock; ++ if hMSImg <> 0 then FreeLibrary(hMSImg); + end. +--- TBXOffice2003Theme.pas 2005-02-14 12:06:12.000000000 +-0400 ++++ TBXOffice2003Theme.pas 2005-08-12 12:33:40.000000000 +-0400 +@@ -19,13 +19,13 @@ + // I advise you to get it from http://pngdelphi.sourceforge.net + // after downloading, install it and TPNGImageList component from PNGImgList.pas + // uncomment next string if you have TPNGImage and TPNGImageList installed + //{$DEFINE PNGIMAGELIST} + + // uncomment next string if you want to see highlighted icons +-//{$DEFINE HIGHLIGHTTOOLBARICONS} ++{$DEFINE HIGHLIGHTTOOLBARICONS} + + uses + Windows, Messages, Graphics, TBXThemes, ImgList, TBXUxThemes + {$IFDEF PNGIMAGELIST}, PNGImgList{$ENDIF}; + + type +@@ -414,13 +414,13 @@ + Result := BtnBodyColors[B, False] + else + Result := BtnItemColors[B, ItemPart]; + if Embedded and (Result = clNone) then + begin + if ItemPart = ipBody then Result := EmbeddedColor; +- if ItemPart = ipFrame then Result := EmbeddedFrameColor;; ++ if ItemPart = ipFrame then Result := EmbeddedFrameColor; + end; + end; + end; + end; + + function TTBXOffice2003Theme.GetItemColor(const ItemInfo: TTBXItemInfo): TColor; +@@ -550,19 +550,29 @@ + Brush.Style := bsSolid; + end; + end; + + procedure TTBXOffice2003Theme.PaintCheckMark(Canvas: TCanvas; ARect: TRect; const ItemInfo: TTBXItemInfo); + var ++ DC: HDC; + X, Y: Integer; ++ C: TColor; + begin +- X := (ARect.Left + ARect.Right) div 2 - 2; ++ DC := Canvas.Handle; ++ X := (ARect.Left + ARect.Right) div 2 - 1; + Y := (ARect.Top + ARect.Bottom) div 2 + 1; +- Canvas.Pen.Color := GetBtnColor(ItemInfo, ipText); +- Canvas.Polyline([Point(X - 2, Y - 2), Point(X, Y), Point(X + 4, Y - 4), +- Point(X + 4, Y - 3), Point(X, Y + 1), Point(X - 2, Y - 1), Point(X - 2, Y - 2)]); ++ C := GetBtnColor(ItemInfo, ipText); ++ if ItemInfo.ItemOptions and IO_RADIO > 0 then ++ begin ++ RoundRectEx(DC, X-2, Y-4, X+4, Y+2, 2, 2, ++ MixColors(C, ToolbarColor1, 200), clNone); ++ RoundRectEx(DC, X-2, Y-4, X+4, Y+2, 6, 6, C, C); ++ end ++ else ++ PolylineEx(DC, [Point(X-2, Y-2), Point(X, Y), Point(X+4, Y-4), ++ Point(X+4, Y-3), Point(X, Y+1), Point(X-2, Y-1), Point(X-2, Y-2)], C); + end; + + procedure TTBXOffice2003Theme.PaintChevron(Canvas: TCanvas; ARect: TRect; const ItemInfo: TTBXItemInfo); + const + Pattern: array[Boolean, 0..15] of Byte = ( + ($CC, 0, $66, 0, $33, 0, $66, 0, $CC, 0, 0, 0, 0, 0, 0, 0), diff --git a/official/2.1.6+2.1.beta1/TBX/license.txt b/official/2.1.6+2.1.beta1/TBX/license.txt new file mode 100644 index 0000000..372ab01 --- /dev/null +++ b/official/2.1.6+2.1.beta1/TBX/license.txt @@ -0,0 +1,47 @@ +LICENSE + +Copyright 2001-2003 Alex A. Denisov. All rights reserved. + +This notice is only applicable to TBX package; it does not apply +to Toolbar2000 package, where the separate license is provided. + +TBX is distributed as freeware. You are free to use it in any +kind of application as well as redistribute source code in the +original form, provided the following conditions are met: + +- All redistributions of source code must be in the original form, + they must include all the original files, including but not + limited to original documentation, license agreement, copyright + notice, and web site address. + +- Redistribution of TBX package or any part of TBX code in modified + form is allowed only with express written permission from the + author (Alex A. Denisov). + +- You are not allowed to make modifications to TBX documentation. + You may only redistribute the documentation with original + unmodified package. + +- If TBX is used in your software in the compiled form, an + acknowledgement in product documentation and/or in the About box + is required. Only registered users are allowed to omit the + acknowledgement. + +- The origin of this software must not be misrepresented; you must + not claim your authorship. + +If you do not agree to all of the above terms, you are not +permitted to use this package. + +This software is provided 'as-is', without warranty of any kind, +either expressed or implied. In no event shall the author be held +liable for any damages arising from the use of this software. + +Alex A. Denisov + +alex@g32.org + +http://g32.org + + + diff --git a/official/2.1.6+2.1.beta1/TBX/patch.bat b/official/2.1.6+2.1.beta1/TBX/patch.bat new file mode 100644 index 0000000..7a5a5af --- /dev/null +++ b/official/2.1.6+2.1.beta1/TBX/patch.bat @@ -0,0 +1,3 @@ +@if not %2 == "" %2 +@if not %3 == "" cd %3 +patch -p0 --backup --batch < %1 \ No newline at end of file diff --git a/official/2.1.6+2.1.beta1/TBX/patch.exe b/official/2.1.6+2.1.beta1/TBX/patch.exe new file mode 100644 index 0000000..cc0bdb0 Binary files /dev/null and b/official/2.1.6+2.1.beta1/TBX/patch.exe differ diff --git a/official/2.1.6+2.1.beta1/TBX/readme.txt b/official/2.1.6+2.1.beta1/TBX/readme.txt new file mode 100644 index 0000000..f96f2cf --- /dev/null +++ b/official/2.1.6+2.1.beta1/TBX/readme.txt @@ -0,0 +1 @@ +See TBX.chm file for installation and usage instructions. \ No newline at end of file diff --git a/official/2.1.6+2.1.beta1/TBX/registration.txt b/official/2.1.6+2.1.beta1/TBX/registration.txt new file mode 100644 index 0000000..b83d9e5 --- /dev/null +++ b/official/2.1.6+2.1.beta1/TBX/registration.txt @@ -0,0 +1,26 @@ +REGISTRATION AND DONATIONS + +The TBX package is a freeware product and you can use it for any +kind of applications provided the license conditions are satisfied. +Registration is required only if you don't want to include the +acknowledgement. The price of the license is US$100 for a single +user and US$200 per site. Proceed to [https://order.kagi.com/?GRH] +for registartion. + +As long as you include an acknowledgement, you can use the TBX +package free of charge even for commercial and shareware applications. +However, if you wish to express your appreciation for the time I +spend on developing, documenting and supporting it, I do accept and +appreciate donations. + +You can make your donation at [https://order.kagi.com/?GRH]. +The base amount is US$20, but if you would like to donate more, +feel free to order multiple copies of the "TBX donation" product. + +Thank you for your support. + +Alex A. Denisov +alex@g32.org +http://g32.org + + diff --git a/official/2.1.6+2.1.beta1/TBX/rmkThemes.pas b/official/2.1.6+2.1.beta1/TBX/rmkThemes.pas new file mode 100644 index 0000000..84a7776 --- /dev/null +++ b/official/2.1.6+2.1.beta1/TBX/rmkThemes.pas @@ -0,0 +1,550 @@ +unit rmkThemes; + +interface + +uses + Windows, Messages, Graphics, Types, TBXUtils; + +type + TGradDir = (tgLeftRight, tgTopBottom); + +procedure ButtonFrame(Canvas: TCanvas; R: TRect; RL, RR: Integer; c1, c2, c3: + TColor); +procedure SmartFrame(Canvas: TCanvas; R: TRect; RL, RR: Integer; c1, c2: TColor); +procedure GradientGlass(const Canvas: TCanvas; const ARect: TRect; + const Aqua:Boolean; const Direction: TGradDir); Overload; +procedure GradientGlass(const Canvas: TCanvas; const ARect: TRect; + const Aqua, Dark: Boolean; const Direction: TGradDir); Overload; +procedure OLDGradientFill(const Canvas: TCanvas; const ARect: TRect; + const StartColor, EndColor: TColor; const Direction: TGradDir); + +// --- +{ LOW LEVEL } +function GradientFillWinEnabled: Boolean; +function GradientFillWin(DC: HDC; PVertex: Pointer; NumVertex: Cardinal; + PMesh: Pointer; NumMesh, Mode: Cardinal): BOOL; +{ HIGH LEVEL } +procedure GradientFill(DC: HDC; const ARect: TRect; + StartColor, EndColor: TColor; Direction: TGradDir); overload; +procedure GradientFill(Canvas: TCanvas; const ARect: TRect; + StartColor, EndColor: TColor; Direction: TGradDir); overload; + +{ Redeclare TRIVERTEX } +type + {$EXTERNALSYM COLOR16} + COLOR16 = Word; { in Delphi Windows.pas wrong declared as Shortint } + + PTriVertex = ^TTriVertex; + {$EXTERNALSYM _TRIVERTEX} + _TRIVERTEX = packed record + x : Longint; + y : Longint; + Red : COLOR16; + Green : COLOR16; + Blue : COLOR16; + Alpha : COLOR16; + end; + TTriVertex = _TRIVERTEX; + {$EXTERNALSYM TRIVERTEX} + TRIVERTEX = _TRIVERTEX; +// --- + + +implementation + +// --- +type + TGradientFillWin = function(DC: HDC; PVertex: Pointer; NumVertex: ULONG; + Mesh: Pointer; NumMesh, Mode: ULONG): BOOL; stdcall; + TGradientFill = procedure(DC: HDC; const ARect: TRect; + StartColor, EndColor: TColor; Direction: TGradDir); +var + InitDone : Boolean = False; + MSImg32Module : THandle; + GradFillWinProc : TGradientFillWin; + GradFillProc : TGradientFill; +// ---- + +procedure ButtonFrame(Canvas: TCanvas; R: TRect; RL, RR: Integer; c1, c2, c3: + TColor); +var + Color: TColor; +begin + with Canvas, R do + begin + Color := Pen.Color; + Pen.Color := c1; + Dec(Right); + Dec(Bottom); + PolyLine([ + Point(Left + RL, Top), + Point(Right - RR, Top), + Point(Right, Top + RR), + Point(Right, Bottom - RR), + Point(Right - RR, Bottom), + Point(Left + RL, Bottom), + Point(Left, Bottom - RL), + Point(Left, Top + RL), + Point(Left + RL, Top) + ]); + + if c2 <> clNone then + begin + Pen.Color := c2; + PolyLine([ + Point(Right, Top + RR), + Point(Right, Bottom - RR), + Point(Right - RR, Bottom), + Point(Left + RL - 1, Bottom) + ]); + end; + + Pen.Color := c3; + if RR > 0 then + begin + Inc(Right); + MoveTo(Right - RR, Top); + LineTo(Right, Top + RR); + MoveTo(Right - RR, Bottom); + LineTo(Right, Bottom - RR); + Dec(Right); + end; + + if RL > 0 then + begin + Dec(Left); + MoveTo(Left + RL, Top); + LineTo(Left, Top + RL); + MoveTo(Left + RL, Bottom); + LineTo(Left, Bottom - RL); + Inc(Left); + end; + + Inc(Right); + Inc(Bottom); + Pen.Color := Color; + end; +end; + +procedure SmartFrame(Canvas: TCanvas; R: TRect; RL, RR: Integer; c1, c2: TColor); +var + Color: TColor; +begin + with Canvas, R do + begin + Color := Pen.Color; + Pen.Color := c1; + Dec(Right); + Dec(Bottom); + PolyLine([ + Point(Left + RL, Top), + Point(Right - RR, Top), + Point(Right, Top + RR), + Point(Right, Bottom - RR), + Point(Right - RR, Bottom), + Point(Left + RL, Bottom), + Point(Left, Bottom - RL), + Point(Left, Top + RL), + Point(Left + RL, Top) + ]); + if c2 <> clNone then + begin + Pen.Color := c2; + PolyLine([ + Point(Right, Top + RR), + Point(Right, Bottom - RR), + Point(Right - RR, Bottom), + Point(Left + RL - 1, Bottom) + ]); + end; + + Pen.Color := Blend(Pixels[Left, Top], c1, 60); + if RL > 0 then + begin + Dec(Left); + MoveTo(Left + RL, Top); + LineTo(Left, Top + RL); + MoveTo(Left + RL, Bottom); + LineTo(Left, Bottom - RL); + Inc(Left); + end; + + if c2 <> clNone then + Pen.Color := Blend(Pixels[Right, Bottom], c2, 60); + if RR > 0 then + begin + Inc(Right); + MoveTo(Right - RR, Top); + LineTo(Right, Top + RR); + MoveTo(Right - RR, Bottom); + LineTo(Right, Bottom - RR); + Dec(Right); + end; + + Inc(Right); + Inc(Bottom); + Pen.Color := Color; + end; +end; + +procedure GradientGlass(const Canvas: TCanvas; const ARect: TRect; + const Aqua, Dark: Boolean; const Direction: TGradDir); +var + GSize: Integer; + rc1, rc2, gc1, gc2, bc1, bc2, rc3, gc3, bc3, rc4, gc4, bc4, + r, g, b, y1, Counter, i, d1, d2, d3: Integer; + + Brush: HBrush; +begin + if Aqua then + begin + if Dark then + begin + rc1 := $e0; rc2 := $70; rc3 := $60; rc4 := $A0; + gc1 := $e8; gc2 := $A0; gc3 := $D0; gc4 := $EF; + bc1 := $EF; bc2 := $D0; bc3 := $E0; bc4 := $EF; + end else + begin + rc1 := $f0; rc2 := $80; rc3 := $70; rc4 := $B0; + gc1 := $f8; gc2 := $B0; gc3 := $E8; gc4 := $FF; + bc1 := $FF; bc2 := $E0; bc3 := $F0; bc4 := $FF; + end; + end else + begin + rc1 := $F8; rc2 := $d8; rc3 := $f0; rc4 := $F8; + gc1 := $F8; gc2 := $d8; gc3 := $f0; gc4 := $F8; + bc1 := $F8; bc2 := $d8; bc3 := $f0; bc4 := $F8; + end; + + if Direction = tGTopBottom then + begin + GSize := (ARect.Bottom - ARect.Top) - 1; + y1 := GSize div 3; + if y1 = 0 then y1:= 1; + d1 := y1; + d2 := y1 + y1; + for i := 0 to y1 do + begin + r := rc1 + (((rc2 - rc1) * (i)) div y1); + g := gc1 + (((gc2 - gc1) * (i)) div y1); + b := bc1 + (((bc2 - bc1) * (i)) div y1); + if r < 0 then r := 0 else if r > 255 then r := 255; + if g < 0 then g := 0 else if g > 255 then g := 255; + if b < 0 then b := 0 else if b > 255 then b := 255; + Brush := CreateSolidBrush( + RGB(r, g, b)); + Windows.FillRect(Canvas.Handle, Rect(ARect.Left, ARect.Top + i, ARect.Right, ARect.Top + i + 1), Brush); + DeleteObject(Brush); + end; + + for i := y1 to d2 do + begin + r := rc2 + (((rc3 - rc2) * (i - d1)) div y1); + g := gc2 + (((gc3 - gc2) * (i - d1)) div y1); + b := bc2 + (((bc3 - bc2) * (i - d1)) div y1); + if r < 0 then r := 0 else if r > 255 then r := 255; + if g < 0 then g := 0 else if g > 255 then g := 255; + if b < 0 then b := 0 else if b > 255 then b := 255; + Brush := CreateSolidBrush( + RGB(r, g, b)); + Windows.FillRect(Canvas.Handle, Rect(ARect.Left, ARect.Top + i, ARect.Right, ARect.Top + i + 1), Brush); + DeleteObject(Brush); + end; + + for i := d2 to GSize do + begin + r := rc3 + (((rc4 - rc3) * (i - d2)) div y1); + g := gc3 + (((gc4 - gc3) * (i - d2)) div y1); + b := bc3 + (((bc4 - bc3) * (i - d2)) div y1); + if r < 0 then r := 0 else if r > 255 then r := 255; + if g < 0 then g := 0 else if g > 255 then g := 255; + if b < 0 then b := 0 else if b > 255 then b := 255; + Brush := CreateSolidBrush( + RGB(r, g, b)); + Windows.FillRect(Canvas.Handle, Rect(ARect.Left, ARect.Top + i, ARect.Right, ARect.Top + i + 1), Brush); + DeleteObject(Brush); + end; + end else + begin + GSize := (ARect.Right - ARect.Left) - 1; + y1 := GSize div 3; + if y1 = 0 then y1:= 1; + d1 := y1; + d2 := y1 + y1; + for i := 0 to y1 do + begin + r := rc1 + (((rc2 - rc1) * (i)) div y1); + g := gc1 + (((gc2 - gc1) * (i)) div y1); + b := bc1 + (((bc2 - bc1) * (i)) div y1); + if r < 0 then r := 0 else if r > 255 then r := 255; + if g < 0 then g := 0 else if g > 255 then g := 255; + if b < 0 then b := 0 else if b > 255 then b := 255; + Brush := CreateSolidBrush( + RGB(r, g, b)); + Windows.FillRect(Canvas.Handle, Rect(ARect.Left + i, ARect.Top, ARect.Left + i + 1, ARect.Bottom), Brush); + DeleteObject(Brush); + end; + for i := y1 to d2 do + begin + r := rc2 + (((rc3 - rc2) * (i - d1)) div y1); + g := gc2 + (((gc3 - gc2) * (i - d1)) div y1); + b := bc2 + (((bc3 - bc2) * (i - d1)) div y1); + if r < 0 then r := 0 else if r > 255 then r := 255; + if g < 0 then g := 0 else if g > 255 then g := 255; + if b < 0 then b := 0 else if b > 255 then b := 255; + Brush := CreateSolidBrush( + RGB(r, g, b)); + Windows.FillRect(Canvas.Handle, Rect(ARect.Left + i, ARect.Top, ARect.Left + i + 1, ARect.Bottom), Brush); + DeleteObject(Brush); + end; + for i := d2 to GSize do + begin + r := rc3 + (((rc4 - rc3) * (i - d2)) div y1); + g := gc3 + (((gc4 - gc3) * (i - d2)) div y1); + b := bc3 + (((bc4 - bc3) * (i - d2)) div y1); + if r < 0 then r := 0 else if r > 255 then r := 255; + if g < 0 then g := 0 else if g > 255 then g := 255; + if b < 0 then b := 0 else if b > 255 then b := 255; + Brush := CreateSolidBrush( + RGB(r, g, b)); + Windows.FillRect(Canvas.Handle, Rect(ARect.Left + i, ARect.Top, ARect.Left + i + 1, ARect.Bottom), Brush); + DeleteObject(Brush); + end; + end; +end; + +procedure GradientGlass(const Canvas: TCanvas; const ARect: TRect; + const Aqua: Boolean; const Direction: TGradDir); +begin + GradientGlass(Canvas, Arect, Aqua, False, Direction); +end; + +procedure OLDGradientFill(const Canvas: TCanvas; const ARect: TRect; + const StartColor, EndColor: TColor; + const Direction: TGradDir); +var + rc1, rc2, gc1, gc2, bc1, bc2, Counter, GSize: Integer; + Brush: HBrush; +begin + rc1 := GetRValue(ColorToRGB(StartColor)); + gc1 := GetGValue(ColorToRGB(StartColor)); + bc1 := GetBValue(ColorToRGB(StartColor)); + rc2 := GetRValue(ColorToRGB(EndColor)); + gc2 := GetGValue(ColorToRGB(EndColor)); + bc2 := GetBValue(ColorToRGB(EndColor)); + + if Direction = tGTopBottom then + begin + GSize := (ARect.Bottom - ARect.Top) - 1; + if GSize = 0 then GSize:= 1; + for Counter := 0 to GSize do + begin + Brush := CreateSolidBrush( + RGB( + Byte(rc1 + (((rc2 - rc1) * (Counter)) div GSize)), + Byte(gc1 + (((gc2 - gc1) * (Counter)) div GSize)), + Byte(bc1 + (((bc2 - bc1) * (Counter)) div GSize))) + ); + Windows.FillRect(Canvas.Handle, Rect(ARect.Left, + ARect.Top, + ARect.Right, + ARect.Bottom - Counter), Brush); + DeleteObject(Brush); + end; + end else + begin + GSize := (ARect.Right - ARect.Left) - 1; + if GSize = 0 then GSize:= 1; + for Counter := 0 to GSize do + begin + Brush := CreateSolidBrush( + RGB(Byte(rc1 + (((rc2 - rc1) * (Counter)) div GSize)), + Byte(gc1 + (((gc2 - gc1) * (Counter)) div GSize)), + Byte(bc1 + (((bc2 - bc1) * (Counter)) div GSize)))); + Windows.FillRect(Canvas.Handle, Rect(ARect.Left, ARect.Top, ARect.Right - Counter, ARect.Bottom), Brush); + DeleteObject(Brush); + end; + end; +end; + + +// Code belowe is from Vladimir Bochkarev + +(******************************************************************************) +procedure + InitializeGradientFill; forward; +(******************************************************************************) +{ GradientFillWin } +(******************************************************************************) +function GradFillWinInitProc(DC: HDC; PVertex: Pointer; NumVertex: ULONG; + Mesh: Pointer; NumMesh, Mode: ULONG): BOOL; stdcall; +begin + InitializeGradientFill; + Result := GradFillWinProc(DC, PVertex, NumVertex, Mesh, NumMesh, Mode); +end; +(******************************************************************************) +function GradFillWinNone(DC: HDC; PVertex: Pointer; NumVertex: ULONG; + Mesh: Pointer; NumMesh, Mode: ULONG): BOOL; stdcall; +begin + Result := False; +end; +(******************************************************************************) +function GradientFillWin(DC: HDC; PVertex: Pointer; NumVertex: Cardinal; + PMesh: Pointer; NumMesh, Mode: Cardinal): BOOL; +begin + Result := GradFillWinProc(DC, PVertex, NumVertex, PMesh, NumMesh, Mode); +end; +(******************************************************************************) +function GradientFillWinEnabled: Boolean; +begin + if not InitDone then InitializeGradientFill; + Result := @GradFillWinProc <> @GradFillWinNone; +end; +(******************************************************************************) +{ GradientFill } +(******************************************************************************) +procedure GradFillInitProc(DC: HDC; const ARect: TRect; + StartColor, EndColor: TColor; Direction: TGradDir); +begin + InitializeGradientFill; + GradFillProc(DC, ARect, StartColor, EndColor, Direction); +end; +(*****************************************************************************) +procedure GradFillInt(DC: HDC; const ARect: TRect; + StartColor, EndColor: TColor; Direction: TGradDir); +var + FillRect : TRect; + RS, GS, BS : TColor; + RE, GE, BE : TColor; + LineCount : Integer; + CurLine : Integer; + //---------------------------------------------------------------------------- + procedure InternalFillRect; + var Brush: HBRUSH; + begin + Brush := CreateSolidBrush( + RGB((RS+ (((RE- RS)* CurLine) div LineCount)), + (GS+ (((GE- GS)* CurLine) div LineCount)), + (BS+ (((BE- BS)* CurLine) div LineCount)))); + Windows.FillRect(DC, FillRect, Brush); + DeleteObject(Brush); + end; + //---------------------------------------------------------------------------- +begin + FillRect := ARect; + if StartColor < 0 then + StartColor := Integer(GetSysColor(StartColor and $000000FF)); + if EndColor < 0 then + EndColor := Integer(GetSysColor(EndColor and $000000FF)); + RS := GetRValue(Cardinal(StartColor)); + GS := GetGValue(Cardinal(StartColor)); + BS := GetBValue(Cardinal(StartColor)); + RE := GetRValue(Cardinal(EndColor)); + GE := GetGValue(Cardinal(EndColor)); + BE := GetBValue(Cardinal(EndColor)); + if Direction = tgLeftRight then + begin + FillRect.Right := FillRect.Left+ 1; + LineCount := ARect.Right- ARect.Left; + for CurLine := 1 to LineCount do + begin + InternalFillRect; + Inc(FillRect.Left); + Inc(FillRect.Right); + end; + end + else begin + FillRect.Bottom := FillRect.Top+ 1; + LineCount := ARect.Bottom- ARect.Top; + for CurLine := 1 to LineCount do + begin + InternalFillRect; + Inc(FillRect.Top); + Inc(FillRect.Bottom); + end; + end; +end; +(******************************************************************************) +procedure GradFillWin(DC: HDC; const ARect: TRect; + StartColor, EndColor: TColor; Direction: TGradDir); +var + Vertexs: array[0..1] of TTriVertex; + //---------------------------------------------------------------------------- + procedure SetVertex(Index, AX, AY, AColor: TColor); + begin + with Vertexs[Index] do + begin + X := AX; + Y := AY; + Red := (AColor and $000000FF) shl 8; + Green := (AColor and $0000FF00); + Blue := (AColor and $00FF0000) shr 8; + Alpha := 0; + end; + end; + //---------------------------------------------------------------------------- +var + GRect : TGradientRect; + Mode : Cardinal; +begin + if StartColor < 0 then + StartColor := Integer(GetSysColor(StartColor and $000000FF)); + if EndColor < 0 then + EndColor := Integer(GetSysColor(EndColor and $000000FF)); + SetVertex(0, ARect.Left, ARect.Top, StartColor); + SetVertex(1, ARect.Right, ARect.Bottom, EndColor); + with GRect do + begin + UpperLeft := 0; + LowerRight := 1; + end; + if Direction = tgLeftRight + then Mode := GRADIENT_FILL_RECT_H + else Mode := GRADIENT_FILL_RECT_V; + GradientFillWin(DC, @Vertexs, 2, @GRect, 1, Mode); +end; +(******************************************************************************) + +procedure GradientFill(DC: HDC; const ARect: TRect; + StartColor, EndColor: TColor; Direction: TGradDir); +begin + GradFillProc(DC, ARect, StartColor, EndColor, Direction); +end; + +(******************************************************************************) +procedure GradientFill(Canvas: TCanvas; const ARect: TRect; + StartColor, EndColor: TColor; Direction: TGradDir); +begin + GradientFill(Canvas.Handle, ARect, EndColor, StartColor, Direction); +end; + +{ Initializations } +(******************************************************************************) +procedure InitializeGradientFill; +begin + if InitDone then Exit; + MSImg32Module := LoadLibrary('msimg32.dll'); + if MSImg32Module <> 0 + then GradFillWinProc := GetProcAddress(MSImg32Module, 'GradientFill') + else GradFillWinProc := nil; + if @GradFillWinProc = nil then + begin + GradFillWinProc := GradFillWinNone; + GradFillProc := GradFillInt; + end + else GradFillProc := GradFillWin; + InitDone := True; +end; +(******************************************************************************) +procedure UninitializeGradientFill; +begin + if MSImg32Module <> 0 then FreeLibrary(MSImg32Module); +end; +(******************************************************************************) +initialization + GradFillWinProc := GradFillWinInitProc; + GradFillProc := GradFillInitProc; +finalization + UninitializeGradientFill; +(******************************************************************************) +end. diff --git a/official/2.1.6+2.1.beta1/TBX/tbx_glyphs.res b/official/2.1.6+2.1.beta1/TBX/tbx_glyphs.res new file mode 100644 index 0000000..06e6e86 Binary files /dev/null and b/official/2.1.6+2.1.beta1/TBX/tbx_glyphs.res differ diff --git a/official/2.1.6+2.1.beta1/tb2k.chm b/official/2.1.6+2.1.beta1/tb2k.chm new file mode 100644 index 0000000..e6e1eb0 Binary files /dev/null and b/official/2.1.6+2.1.beta1/tb2k.chm differ diff --git a/official/2.1.6+2.1.beta1/whatsnew.htm b/official/2.1.6+2.1.beta1/whatsnew.htm new file mode 100644 index 0000000..b893476 --- /dev/null +++ b/official/2.1.6+2.1.beta1/whatsnew.htm @@ -0,0 +1,361 @@ + + + Toolbar2000 Revision History + + + + + + + + + + + +
Toolbar2000
+Revision History
+
+ +

Copyright © 1998-2005 Jordan Russell. All rights reserved.
+For conditions of distribution and use, see LICENSE.txt. + +

2.1.6 (2005-07-30)

+
    +
  • The captions of floating toolbars are now grayed when their parent forms are inactive (e.g., when a modal dialog is up). +
  • Replaced various global "var"s with "threadvar"s to improve thread safety when Toolbar2000 is used in a browser-embedded ActiveForm. (Note that this can never be 100% safe because the VCL itself has some thread safety issues.) +
  • Fix: When running on an Athlon 64 CPU with the Cool'n'Quiet feature enabled, menus animated at approximately half the expected speed when the CPU utilization was low. (Previously, it used QueryPerformanceCounter to time the animation, but with Cool'n'Quiet enabled, the rate at which the performance counter increments actually varies depending on the current CPU clock frequency. Now it uses GetTickCount instead.) +
  • Fix: In the Delphi 2005 IDE, toolbar editor forms could fall behind the IDE's main form. +
  • Fix: When an EXE contained a Toolbar2000 menu bar, and a modal Delphi form hosted in a DLL was currently active, pressing Alt would open the menu bar in the EXE even though the form containing the menu bar was disabled/inactive. +
  • Fix: Fixed MSAA bug reported in "Accessibility issue with Window-Eyes" thread on newsgroup 2005-06-21. +
  • Internal tweaks and trivial fixes. +
+ +

2.1.5 (2004-12-13)

+
    +
  • Packages for Delphi 2005 are now included. +
  • Added new RadioItem property to TTBCustomItem and descendants. Like the property of the same name on TMenuItem, it causes the item to display a circle instead of a check mark when the item is checked and no other image has been specified. +
  • Like standard menus, it now prevents other applications from stealing the focus while a menu is open. This should make it fully compatible with Tweak UI's X-Mouse option. +
  • If the application displays a modal dialog of its own while a menu is open, the menu will now be hidden. +
  • TTBCustomDockableWindow and descendants: Made Canvas a public property. +
  • Fix "ImageIndex on toolbutton incorrectly overriden by action's imageindex" issue reported on newsgroup 2004-09-02 by Anthony Egerton.
    +(Note: The problem described in the thread isn't Toolbar2000 specific. Standard menus and controls will continue to exhibit the same problem.) +
  • TMainMenu/TPopupMenu converter: Now additionally transfers the AutoCheck, GroupIndex, and RadioItem properties. +
  • Internal tweaks. +
+ +

2.1.4 (2004-02-28)

+
    +
  • Toolbar2000 may now alternatively, at your option, be used and/or distributed under the terms of the GNU General Public License. Please see the updated LICENSE.txt file for more information on the two licensing options.
    +Note that if you choose the GPL license option, your application as a whole must also be licensed under the GPL. Therefore, you cannot choose the GPL license option if your application is proprietary/closed-source. +
  • Reworded point 5 of the Toolbar2000 License for clarity. +
  • Added new ChevronPriorityForNewItems property to TTBToolbar. +
+ +

2.1.3 (2003-11-23)

+
    +
  • Added new tboNoAutoHint value to the Options property. When set, the automatic hint generation feature (introduced in 2.1.1) will be disabled. +
  • On Windows NT/2000/XP, use SetWindowsHookExW instead of SetWindowsHookEx to work around apparent OS bug reported on the newsgroup by George Kyrou 2003-09-23. +
  • Tweak to HookProc in TB2Toolbar.pas to avoid ANSI/Unicode character set issue with hooks on Windows NT/2000/XP. +
  • Fix: When a TTBEditItem was focused, it didn't inherit the font settings from the parent toolbar. +
+ +

2.1.2 (2003-08-10)

+
    +
  • It's now possible to nest "group" items such as TTBGroupItem. Previously, placing one group item inside another did not work. +
  • Tweaked the automatic hint generation introduced in the last version: It now will not generate hints for submenu items unless the submenu item has the DropdownCombo property set to True or the submenu item has no visible caption. +
  • TTBControlItem is no longer explicitly registered. There is a slim chance that this change may affect you if your application initially used one of the very early Toolbar2000 betas. In those early betas, Toolbar2000 did not assign to the Name property of TTBControlItem components it created. If you have unnamed TTBControlItem components on your forms, you must now assign them names, otherwise you might receive a "class not found" error message when running your application. +
  • Fix: TTBEditItem would lose the focus when Alt+[keypad digit] was pressed. +
  • Internal tweaks. +
+ +

2.1.1-beta (2003-07-13)

+
    +
  • Now automatically supplies short hints for items with no short hint assigned to the Hint property. The hint is derived from the item's caption, with accelerator keys and any trailing colon or ellipsis stripped. +
  • Shortcut text is now displayed in the hints of items that don't have associated Actions. +
  • Fix: In TTBMRUList, "&" characters in filenames weren't escaped when assigning item captions. +
  • MSAA-related tweaks: +
      +
    • Escape any "&" characters when assigning text to chevron item's Caption property. +
    • Work around bug in Delphi/C++Builder 4's ShortCutToText function. +
    +
  • Internal tweaks. +
+ +

2.1.0-beta (2003-07-05)

+
    +
  • Microsoft Active Accessibility support for Toolbar2000's menus and toolbars. This exclusive feature will make your application's user interface more accessible to users who rely on screen readers. For more details, see the MSAA Support topic in the help file. +
  • When new items are inserted programmatically at run-time, they are now placed at the top of the "priority list" instead of at the bottom. This means that new items will now be the last to move onto the chevron menu when all items can't fit on the toolbar. +
  • On popup menus, accelerator keys are now properly hidden if the last input came from the mouse. +
  • On TTBMDIButtonsItem, the biMinimize setting of BorderIcons on MDI child forms is now respected. +
  • As a performance optimization, the default image base of the Delphi design and run-time packages have been changed from $400000 to $3F800000 and $3FC00000 respectively.
    +(The C++Builder packages remain at $400000 due to a design flaw in the C++Builder linker: it strips the image's relocation table whenever the base address is changed from $400000. DLLs must have relocation tables in order to load properly in all cases.) +
  • Fix: When a top-level DropdownCombo=True submenu item is selected using Alt+[accelerator key] the item is now clicked instead of opened. +
  • Fix: When F1 was pressed on a menu item and Toolbar2000 handled it, a WM_HELP message would still reach the parent form. +
  • Fix: A focused TTBEditItem would lose the focus when Alt+Shift was pressed. +
  • Many internal changes, most of them necessary for supporting MSAA as cleanly as possible. +
+ +
+ +

2.0.16 (2003-03-28)

+
    +
  • Added new tboSameWidth value to the Options property. When set along with tboImageAboveCaption on two or more items on the same view, the items will be stretched as necessary so that they all have the width in pixels. +
  • Added ChevronMoveItems property to TTBToolbar. Normally, when an item on a toolbar's chevron popup menu is clicked, the clicked item will move into the visible area of the toolbar in place of the least recently clicked item. Setting this property to False will disable that behavior. +
  • TTBCustomItem.Click now checks the Enabled property before calling any event handlers, like TMenuItem.Click does. +
  • TTBPopupMenu.Popup now sets the PopupPoint property. +
  • Published OnContextPopup event properties on TTBDock, TTBToolbar, and TTBToolWindow. +
  • Fixed issues with Russian characters as accelerator keys on Windows NT/2000/XP. +
  • Internal tweaks and trivial fixes. +
+ +

2.0.15 (2002-09-29)

+
    +
  • Packages for Delphi 7 are now included. +
  • Revised the Toolbar2000 License Agreement. +
  • TTBMRUList: Added new Remove method.
    +TTBMRUListStrings: IndexOf method now uses AnsiCompareFileName instead of AnsiCompareText. +
  • Fix: The issue reported in the "Problem with tb2k in Com Server/ActiveX" thread on the newsgroup has been fixed. +
  • Internal tweaks and trivial fixes. +
+ +

2.0.14 (2002-05-10)

+
    +
  • Added new tboNoRotation value to Options property. When set, the item and its caption will not be rotated 270 degrees when docked vertically. +
  • Added Move Up and Move Down commands to the design-time editor to make it easier to move items. +
  • Chevron popup windows now wrap if they are too wide to fit on the screen. +
  • A toolbar's LastDock property is no longer updated when the toolbar is dragged over but not dropped on a dock. +
  • When arranging toolbars on a dock, row numbers that contain only invisible or undocked toolbars are no longer removed. This way, when the toolbars are shown/docked again, they stay on their row. This was how Toolbar97 worked. +
  • A toolbar's DockRow and DockPos properties got updated if you dragged the toolbar over a dock but didn't drop it on the dock. Now it restores the original DockRow and DockPos settings when a toolbar is not dropped on a dock. +
  • Fix: When arranging toolbars on a dock, there was a case where LimitToOneRow wasn't being checked. +
  • Internal tweaks. +
+ +

2.0.13 (2002-04-06)

+
    +
  • New item class: TTBVisibilityToggleItem. This item class controls the Visible property of a control, such as a TTBToolbar. +
  • On menus, it now uses clGrayText to draw disabled text when the menu background color doesn't equal clBtnFace. (That is how standard menus work.) +
  • On vertically docked toolbars, it now uses a vertical font if one is available so that Asian characters aren't drawn sideways. +
  • Now, if at design time you double click a TTBToolbar or TTBPopupMenu that has its LinkSubitems property assigned, it asks if you want to edit the item specified by LinkSubitems instead. +
  • TTBEditItem: The outermost border is now transparent when the item is not selected. +
  • In the functions that load toolbar positions, it now compares the dock names with case insensitivity. +
  • Added new demo project file for C++Builder 6 - DemoBCB6 - because DemoBCB doesn't seem to compile under C++Builder 6. +
  • Internal tweaks. +
+ +

2.0.12 (2002-03-06)

+
    +
  • Menus now display scroll arrows when they are too tall to fit on the screen. +
  • Packages for C++Builder 6 are now included. +
  • Minor tweaks and documentation updates. +
+ +

2.0.11 (2002-02-23)

+
    +
  • Fix: The new Stretch property introduced in 2.0.10 had some bugs. +
+ +

2.0.10 (2002-02-13)

+
    +
  • Added new Stretch property to TTBToolWindow and TTBToolbar. When True, the toolbar, when docked, will stretch to fill any unused space on the row. +
  • On TTBToolbar, chevrons now display a "More Buttons" hint, like Office 2000. The hint text can be customized by changing the new ChevronHint property, or globally by changing STBChevronItemMoreButtonsHint in TB2Consts.pas. +
  • The OnMove event of TTBToolbar/TTBToolWindow now gets fired when the bar is floating also. +
  • Fix: TTBPopupMenu.OnPopup was being called twice when the popup was displayed - once with the TTBPopupMenu as the Sender, and once with the internal TTBRootItem as the Sender. Now, it's called only once with the TTBPopupMenu as the Sender. +
  • Fix: TTBEditItem: Fixed double-click issue ("TB2k Strange Behaviour"). +
  • Internal tweaks. +
+ +

2.0.9 (2002-01-11)

+
    +
  • Added new TTBImageList component. It is an enhanced version of the standard TImageList component, designed for use with the Toolbar2000 components. It adds the ability to use special images for different item states (hot, disabled, checked). It also adds the ability to load the images from a bitmap instead of using TImageList's normal streaming mechanism, which has problems with older COMCTL32.DLL versions. +
  • Added new OnSelect property to TTBCustomItem and descendants. This event lets you trap when the mouse enters or leaves an item. +
  • Added new CharCase and OnBeginEdit properties to TTBEditItem. +
  • Added C++Builder version of the Demo project - DemoBCB. +
  • Minor tweaks and fixes. +
+ +

2.0.8 (2001-12-27)

+
    +
  • Now supports "flat" menu borders on Windows XP. +
  • The background of a selected menu item's image is now filled with clBtnFace. This seems to look better with Windows XP's white menus. +
  • Made chevron popups colored clBtnFace instead of clMenu. This seems to look better on Windows XP with themes enabled. +
  • Fix: Fixed "stack overflow" problem that may have occurred if you had a floating TTBToolWindow and pressed Alt on the keyboard. +
  • Fix: On Delphi 6 the ActionComponent property of an action now gets set properly when the action is fired from a TB2k item. +
  • Removed some Windows NT 3.51 support code since NT 3.51 is now officially unsupported. +
+ +

2.0.7 (2001-12-19)

+
    +
  • Menus now display drop-shadows on Windows XP if they are enabled in the Display Properties. +
  • When a menu is up, keystrokes will no longer get processed by an IME if one was active.
    +Note: The ImmGetVirtualKey function is used, which is not available on Windows NT 3.51. Therefore, NT 3.51 is now officially unsupported. (It never was officially supported anyway.) +
  • TTBToolbar: Added new published FloatingWidth property. +
  • Fix: Accessing menu bars on non-main forms with the keyboard should now work. +
  • Minor fixes. +
+ +

2.0.6 (2001-11-14)

+
    +
  • When a shortcut key is pressed, it now sends OnPopup/OnClick events to the selected item's parents so that they can update the Enabled state of the item if needed. +
  • The OnPopup event of TTBPopupMenu is now fired when one of its items' shortcut keys is pressed. +
  • TTBPopupMenu now processes shortcuts. +
  • Added OnUpdate event to TTBMDIWindowItem. +
  • Minor fixes. +
+ +

2.0.5 (2001-10-09)

+
    +
  • Toolbars that are neither docked nor floating can now wrap or display a chevron (ShrinkMode is no longer ignored). For it to work, you must do at least one of the following: set AutoResize to False, set Align to one of [alTop, alBottom, alClient], or add [akLeft, akRight] to Anchors (which is now a published property). +
  • TTBToolWindow: Published the Align and Anchors properties. +
  • Now allows F1 to be handled while the mouse button is down (an odd quirk of standard menus). +
  • Now always streams out the Width & Height properties of a toolbar that is neither docked nor floating. Needed to properly support anchored toolbars. +
  • Fix: Fixed a GDI resource leak in TB2Item that occurred on Windows 9x/Me due to an undocumented difference/bug in the way SaveDC works. +
  • Fix: Fixed resource leak with TTBMDIHandler: it was trying to free an icon handle with DeleteObject instead of DestroyIcon. +
  • Fix: Made TTBPopupWindow a TCustomControl descendant instead of a TForm descendant. This resolves the issue with the Application window's taskbar button reappearing after the program initially hid it. +
  • Fix: When destroying a toolbar on a dock that had another toolbar on the same dock linked to one of the destroying toolbar's subitems, an AV may have occurred. +
  • Fix: Fixed problem in TTBView.GivePriority. +
+ +

2.0.4 (2001-09-30)

+
    +
  • Added new tboImageAboveCaption value to Options property. When set, the item's caption will be displayed underneath its image, making for an Internet Explorer-like appearance. +
  • Added Options property to TTBPopupMenu. +
  • Fix: It was possible to "click" disabled top-level items by pressing Alt+[accelchar]. +
  • Fix: Shortcut keys now work on toolbars that are on frames. +
  • Fixed issue with TActiveForms: OnClick events were always executed in the context of the first thread. +
  • Minor tweaks. +
+ +

2.0.3 (2001-09-13)

+
    +
  • Added AutoCheck property to TTBCustomItem and descendants. +
  • Added Prefix property to TTBMRUList. +
  • Added Enabled property to TTBMDIWindowItem. +
  • Published GroupIndex property on TTBSubmenuItem and TTBEditItem. +
  • TTBView's Selected property is now writable. +
  • Fix: Sealed minor memory leak that occurred when when a TTBMDIHandler component was created, or when the LinkSubItems property of a toolbar was changed. +
  • Fix: Modifying a TTBBackground's bitmap after a dock that used the background was destroyed may have caused an AV. +
  • Fix: Alt+- didn't work unless the two keys were pressed simultaneously. +
  • Fix: Shortcuts didn't work if TTBToolbar.LinkSubitems was set. +
  • Fix: MDI buttons didn't show when FullSize=False and ShrinkMode=tbsmWrap. +
  • Fix: Unwrapped floating toolbars were a pixel too high. +
  • Fix: Hopefully fixed Delphi 6 AV with design-time editor again. +
+ +

2.0.2 (2001-08-19)

+
    +
  • Added new component: TTBMDIHandler, which adds the MDI system menu and minimize/restore/close buttons to a menu bar. See the documentation for details. +
  • Added new item type: TTBMDIWindowItem, which expands to a list of available MDI child windows at run-time. This is intended to be placed at the end of an MDI application's Window menu, following a separator. +
  • The design-time menu converter can now convert TPopupMenu's too. +
  • The Alignment property of TTBPopupMenu is now respected. Also added optional Alignment parameter to the TTBCustomItem.Popup method. +
  • Added TTBCustomItem.Clear method. +
  • Now respects the system's "menu drop alignment" setting when dropping down menus. +
  • Pressing Home or End on a toolbar or menu now moves the selection to the first or last item. +
  • Fix: TTBToolWindow's that had their FullSize properties set to True weren't the correct size when undocked. +
  • Fix: Now doesn't attempt to draw or invalidate TTBControlItem's. Fixes issue with Transparent=True TLabel's. +
  • Fix: Now doesn't display the size-all cursor on DragHandle=dhNone toolbars. +
  • Fix: The keyboard shortcuts for Cut/Copy/Paste in the design-time editor now work again. +
  • Some minor internal tweaks. +
+ +

2.0.1 (2001-08-04)

+
    +
  • Added slide/fade animation support. It is enabled automatically if the user has menu animation enabled in Windows. +
  • On vertical toolbars, the tboDropdownArrow arrows are now drawn rotated and below the text. +
  • Fix: When you have ProcessShortCuts=True toolbars on multiple forms, it now first looks for shortcuts on the active form's toolbars, and then the main form's toolbars. Previously, it looked on all forms' toolbars. +
  • Fix: It wasn't loading item icons correctly after design-time code was moved to the tb2kdsgn package. +
  • Fix: Setting EditOptions on TTBEditAction had no effect. +
  • Some minor internal tweaks. +
+ +

2.0.0 (2001-07-21)

+
    +
  • Revised the Toolbar2000 License Agreement. +
  • Moved design-time units to separate tb2kdsgn_* packages so that tb2k_* may now be used as run-time packages. +
  • Tweaked the component icons. +
+ +
+ +

Beta Releases

+ +

2.0-BETA6 (2001-07-18)

+
    +
  • TTBMRUList: Added AddFullPath and HidePathExtension properties. Both are True by default. See documentation for details. +
  • TTBMRUList: Added OnChange event. +
  • Typing or pressing Enter on the design-time editor's tree view now activates the Object Inspector. +
  • Fix: On Delphi 6, the ShortCut property of TTBCustomItem was showing up like an Integer property in Object Inspector, thanks to some change Borland made. Workaround added. +
  • Fix: Removed call in design-time editor that appeared to cause AV's in certain cases. +
+ +

2.0-BETA5 (2001-07-09)

+
    +
  • Now works around the Windows 2000 problem of delaying on the first PlaySound call by not calling PlaySound at all if there is no sound associated with the event. +
  • Added LoadFromIni, LoadFromRegIni, SaveToIni, SaveToRegIni methods to TTBMRUList. +
  • Updated documentation; added an index. +
  • Updated demo project. +
  • Fix: The change to the Click handling in 2.0-BETA4 broke exception handling. +
  • Fix: The OnResize event was never fired. +
  • A few very minor fixes and tweaks. +
+ +

2.0-BETA4 (2001-07-01)

+
    +
  • Added UpdateActions property to TTBToolbar. Setting it to False can decrease CPU utilization. See the documentation for details. +
  • Now, as with standard menus, when an item is clicked it posts a message to the queue so that the Click handler gets called when control returns to the message loop. This fixes the problem with modal forms not correctly getting the focus when an item is selected from a menu with the keyboard. +
  • Fixed potential AV problem when Escape was pressed. +
  • Improvements to design-time editor: +
      +
    • There's now an empty item at the end of the item list, similar to Delphi's menu editor. You can't (currently) type on this item item, but you can select it and press Insert to add a new item to the end. +
    • You can now hold down Shift while pressing Insert or clicking one of the New buttons to add an item to the end instead of inserting it before the currently selected item. +
    • Added keyboard shortcuts for New Subitem and New Separator. +
    • Now selects root item when list view is focused and no item is selected. +
    • After deleting the items, it now selects the item with the focus. +
    +
+ +

2.0-BETA3 (2001-06-25)

+
    +
  • Context help (F1) is now supported on menu items. +
  • Added a GroupIndex property to TTBCustomItem due to popular demand. See documentation for details on how it works. +
  • Added a new ImageIndex property editor which is fully compatible with Delphi 6. +
  • It now substitutes Arial for MS Sans Serif & Microsoft Sans Serif when drawing vertical text, instead of letting Windows pick a font. +
  • Remarked out code in TTBDock.ArrangeToolbars that was there to work around a VCL alignment bug*, because it had some undesirable side effects. Now, if you want to avoid the bug, you need to right-click your alClient-aligned controls in the form designer and select "Send to Back." +
    * The VCL alignment bug: if a control is taller or wider than the client height or width of its parent, alClient-aligned controls may appear on top of the control, instead of being hidden from view. +
  • Fix: When toolbars are dragged across a dock that has a background bitmap, they should no longer flicker. +
  • Fix: The menu converter now transfers the Tag property. +
  • Fix: The toolbar-dragging changes in 2.0-BETA2 broke the splitter. +
  • Fix: Work around an annoying Windows or VCL bug. (If you close all MDI child windows, the MDI client window gets the focus, and when it has the focus, pressing Alt+[char] doesn't send a WM_SYSCOMMAND message to the form for some reason.) +
  • Fix: In the design-time item editor, when a new item is created while the tree view has the focus, it now sets the focus to the list view so that the item becomes selected in Object Inspector. +
  • Fix: On TTBDock, LimitToOneRow=True didn't actually limit to one row while dragging. +
  • Various other minor tweaks and fixes. +
+ +

2.0-BETA2 (2001-06-18)

+
    +
  • Delphi 6 is now supported. There is one limitation however: the ImageIndex property editor used by TTBCustomItem descendants had to be disabled because TComponentImageIndexPropertyEditor is gone in Delphi 6! Therefore, on Delphi 6, the dropdown lists of ImageIndex properties may not work correctly, at least for now. +
  • Text on vertical toolbars is now drawn vertically! +
  • Vastly improved the code that handles toolbar dragging. Previously, when you dragged a SmoothDrag=True docked toolbar over other docked toolbars, the toolbar may not have ended up on the row you were expecting. This was because the old code - ported from Toolbar97 - was not designed with smooth dragging in mind. Now it should function almost exactly like Office 2000. +
  • TTBEditItem (and friends): Removed DisplayAsButton property; replaced with EditOptions property. Now, by default, edits on toolbars will automatically change into buttons when the toolbar is docked vertically. Add tboUseEditWhenVertical to EditOptions to disable this. +
  • On wrapped toolbars, menus now pop out to the side which obscures the least amount of items, like Office 2000. +
  • Up/Down/Left/Right arrow keys on vertical toolbars now work like Office 2000. +
  • Fix: Hints on chevron popup's items didn't include shortcuts. +
  • Fix: Deleting an item from a TTBMRUList via Items.Delete() did not refresh the keyboard shortcuts. +
  • Fix: Fixed "Run-time creation of items and chevron" problem reported by Francois Rivierre. +
  • Some very minor tweaks. +
+ +

2.0-BETA1 (2001-06-12)

+
    +
  • Updated the Toolbar2000 License Agreement. +
  • You can now display the version of Toolbar2000 by right-clicking a toolbar and selecting "Version". +
  • Added an improved Demo project. +
  • Made the margins of menu items a bit more like Office and standard menus. +
  • Now includes size of a font's external leading when calculating an menu item's height. +
  • Added workaround an apparent NT 4.0 & 2000 bug that was causing the right side of floating toolbars' non-client area to be painted incorrectly if the toolbar's width was greater than the screen width. +
  • Various tweaks to the display of disabled toolbar & menu items. +
+ +
+ + +