text:
Projects, the Code Editor, and the Code Explorer
Everyone Needs a Project
Using the Project Manager
The Project Manager Window
Creating and Using Project Groups
Building Projects or Project Groups
Understanding Project Options
The Forms Page
The Application Page
The Compiler Page
The Linker Page
The Directories/Conditionals Page
The Version Info Page
The Packages Page
The Delphi Code Editor
Basic Editor Operations
Highlighting Text
Specialized Editor Features
Module Browsing
The Code Editor Context Menu
Changing the Editor Options
The Code Explorer
The Code Explorer Context Menu
Navigating a Unit
Adding Code Using the Code Explorer
Code Explorer Options
Today you learn more about the Delphi IDE and how it all works together to create real-world working programs. Specifically you learn about
Projects and the Project Manager
The Code Editor
It will be a long day, but a rewarding one.
On Day 4, "The Delphi IDE Explored," you were introduced to Delphi projects and found out a little about how projects work. In this section, I cover projects in detail. Projects are a fact of life with Delphi. You cannot create a program without a project. The project makes sure that everything works together to create a working application. The following sections talk about
The Project Options dialog box
At some point, every project needs some management. Maybe you must add a new source unit to the project, or maybe you must remove a source unit. You might need to add another type of file to the project, such as a binary resource file. You add and remove units and other project files through the Project Manager.
On Day 4, I said that a project is a collection of files that work together to create a stand-alone executable file or DLL. That's the definition of a project as far as the Delphi IDE is concerned. In the real world, you might have a different kind of project, such as a job that you have to complete.
A large project might include one or more executable files and several DLLs. Because some projects consist of more than a single executable program, Delphi enables you to group several Delphi projects together and deal with them as a single unit. This unit is called a project group.
Why Use Project Groups?
You might be wondering what advantage project groups provide. Project groups give you the following:
Better control over a complete software project.
The ability to work on a DLL and a test EXE for the DLL at the same time.
The ability to build (compile and link) a group of projects all at one time.
The ability to have several projects open at one time and to easily switch between open projects.
A way to organize related projects.
A project that creates a single executable file doesn't need a project group. A single project can hardly be considered a group, right? In the case of a single project, the concept of a project group is out of place.
But imagine for a moment a program that includes an EXE and a single supporting DLL. Both the DLL and the EXE go together. Usually, if you are working on the DLL, you will want the EXE present so that you can immediately test any changes you make to the DLL. In this scenario, a project group makes perfect sense because the EXE and DLL go everywhere together.
You can create a project group that contains these two individual projects and save it. When you want to work on either the application or the DLL, you can open the project group rather than an individual project. When you open the project group, both the EXE project and the DLL project are displayed. You can work on either the DLL or the EXE in the Code Editor and switch back and forth between them any time you want. Figure 9.1 shows the Project Manager window with this type of project group open.
FIGURE 9.1. The Project Manager window showing a project group.
Another reason to have a project group is so that you can group related projects. That probably sounds like it doesn't make much sense, so let me explain. Here at TurboPower Software we have a product called Async Professional, which is a collection of serial communications components. These components include three main categories: basic serial communications, faxing, and TAPI. We include dozens of sample programs with Async Professional covering each of these three categories.
Given that scenario, we could create a project group for all of our faxing examples, one for all of our TAPI examples, and one for all of our basic serial communications examples. Our users could then open the TAPI Examples project group and have all the TAPI examples in one neat package. The entire project group could be built at one time, thereby saving the time and aggravation of opening and building each project individually. In this case, the projects don't work together like a DLL and EXE do, but the projects are related, so the concept of a project group makes just as much sense.
The Active Project
In any project group there is always an active project. The active project is displayed in the Project Manager in bold type. In Figure 9.1, the active project is the project called TestDll. The active project is the project that will be built when you choose Make or Build from the Project menu on the Delphi main menu.
These menu items are modified each time a project is made the active project. For example, if the active project is called Project1, the menu items will be called Make Project1 and Build Project1. If a project called PictView is made the active project, these two menu items will be called Make PictView and Build PictView.
The active project also has significance when a new form or a new unit is added using the Project Manager. When you create a new form using the Project Manager, the new form will be added to the active project regardless of which node in the Project Manager is currently selected. The active project is also the project to which new forms or units are added if you add new elements via the Delphi main menu or the Delphi toolbar.
You can make a project the active project in one of several ways. One way is to select any item in the project node that you want to make the active project and click the Activate Selected Project button on the top of the Project Manager. Another way is to simply double-click the project node itself. Finally, you can choose Activate from the project node context menu to activate a particular project.
The Project Manager in Delphi 4 is brand-new. The Project Manager concept is not new to Delphi 4, but the current implementation is much better than the previous Project Manager. The Project Manager is the central controller for all of your projects and your program groups. It enables you to add files to a project, delete files from a project, view a unit or form, add projects to the project group, change the order of projects, and more. To display the Project Manager, choose View|Project Manager from the main menu or press Ctrl+Alt+F11.
The Project Manager window contains a tree view control that displays up to four levels. Those levels are as follows:
The project group
The projects within the project group
Forms and other files within the project
Individual form files and units under the form node
Naturally, the individual nodes can be collapsed or expanded as with any tree view control. The Project Manager nodes have icons that indicate whether the node contains a project, an individual file, a form, or a form/unit pair. Refer to Figure 9.1 to see the different icons and levels that the Project Manager displays.
NOTE: In previous versions of Delphi, the Project Manager showed the path to any units as well as the unit filename. The Delphi 4 Project Manager does not show the path and filename in the same way. To see the path and filename, click on a unit in the Project Manager window and the Project Manager status bar will show the full path and filename for the unit (refer to Figure 9.1).
The Project Manager Context Menus
Most of the Project Manager's work is done through the Manager's context menus. There are four separate context menus for the Project Manager. The following sections describe each of the context menus.
The Project Group Context Menu
The project group context menu is the context menu you see when you right-click the project group node at the top of the Project Manager tree. Table 9.1 lists the project group context menu items that appear on this menu.
TABLE 9.1. THE PROJECT GROUP CONTEXT MENU ITEMS.
Add New Project Opens the Object Repository so that you can choose a new target. Targets include applications, DLLs, forms, data modules, components, or any other object available from the Object Repository.
Add Existing Project Opens a project file from disk and adds it to the project group.
Save Project Group Saves the project group. Project groups have a .bpg extension.
Save Project Group As Saves the project group with a new name.
View Project Group Source Displays the project group source. The project group source is a special file (a makefile) that contains references to all projects within the project group.
Toolbar Toggles the Project Manager toolbar on and off.
Status Bar Toggles the Project Manager status bar on and off.
Dockable Specifies whether the Project Manager is dockable.
NOTE: The Toolbar, Status Bar, and Dockable menu items appear on each of the Project Manager context menus. I won't mention them again when I discuss the other Project Manager context menus.
The Project Context Menu
The project context menu is displayed when you right-click a project node in the Project Manager. Table 9.2 lists the context menu items specific to the project context menu.
TABLE 9.2. THE PROJECT CONTEXT MENU ITEMS.
Add Opens the Add to Project dialog box so that you can add a file to the project. The same as choosing Project|Add to Project from the main menu or from the Delphi toolbar.
Remove File Opens the Remove From Project dialog box so that you can remove a file from the project. The same as choosing Project|Remove from Project from the main menu or from the Delphi toolbar.
Save Saves the project. The same as choosing File|Save from the Delphi main menu.
Options Displays the Project Options dialog box for this project. The same as choosing Project|Options from the Delphi main menu.
Activate Makes this project the active project.
Compile Compiles this project. The difference between compile and build was discussed on Day 4.
Build Builds this project.
View Source Displays the project source file. The same as choosing Project|View Source from the Delphi main menu.
Close Closes this project and all its files. If the project is part of a saved project group, the project node icon will be grayed out. The project is still part of the group but is not open in the IDE. If the project is part of the default project group, the project is closed and removed from the default group.
Remove Project Removes this project from the project group. The project is not deleted from your hard drive, just removed from the project group. Same as clicking the Remove Selected Project button on the Project Manager toolbar.
Build Sooner Moves the project up in the project tree. Projects are built from the top of the Project Manager down.
Build Later Moves the project down in the project tree.
NOTE: The Project Manager context menus are even more diverse than represented in this section. The project context menus contain additional items if the project is a Batch File or a Package project. The differences are not significant, so I won't go over those additional menu items.
The Unit Context Menu
The unit context menu is displayed when you right-click a unit node in the Project Manager. Table 9.3 lists the unit context menu items.
TABLE 9.3. THE UNIT CONTEXT MENU ITEMS.
Open Displays the unit in the Code Editor (for standalone units) or Form Designer (if the unit has an associated form).
Remove From Project removes the unit from the project. The Project Manager does not prompt you to remove the unit and there is no undo for this action. You an always add the unit back to the project if you remove a unit by accident.
Save Saves the unit. The same as choosing File|Save from the Delphi main menu.
Save As Opens the Save As dialog box so that you can save the unit with a new name. The same as choosing File|Save As from the Delphi main menu.
The File Context Menu
The file context menu is displayed when you right-click a node other than the project group node, a project node, or a unit node (usually a .pas or .dfm file). This context menu has only one item. The Open menu item displays the selected node in either the Code Editor or the Form Designer, depending on the type of the selected node.
The Project Manager Toolbar and Keyboard Commands
In addition to the Project Manager context menus, the Project Manager has a toolbar to make working with the Project Manager easier. The Project Manager toolbar contains three buttons:
The Add New Project button displays the Object Repository so that you can add a new project to the project group. This is the same as clicking the Add New Project menu item from the project context menu.
The Remove Selected Project button removes the selected project from the project group. Use this button only to remove an entire project, not to remove a particular form or file from a project.
The Activate Selected Project button makes the selected target the active project.
Keyboard commands include the Delete key and the Insert key. When you press Delete, the selected node is removed. If a project node is selected, the project is removed from the project group. If a unit node is selected, the unit is removed from the project to which the unit belongs. The Insert key behaves exactly the same as choosing Add to Project from the project context menu.
TIP: The Project Manager toolbar buttons can be either large or small. By default, the Project Manager toolbar buttons are small. You can change the toolbar button size by dragging the bottom of the toolbar either up (to show the small buttons) or down (to show the large buttons).
Project groups are a great benefit for complex projects, but using project groups is not mandatory. You don't have to use project groups with every project. The Project Manager has a default project group called ProjectGroup1 that is used when you don't specifically open or create a project group. Try this:
1. Choose File|Close All to close any open projects or project groups.
2. Choose File|New Application to create a new application.
3. Choose View|Project Manager to display the Project Manager. The Project Manager is displayed as shown in Figure 9.2.
FIGURE 9.2. The Project Manager showing the default project group.
The project group called ProjectGroup1 is a temporary project group. When you choose Save All from the File menu, you are prompted to save the project, but not the project group. If you want to save the project group, you must explicitly save it using the Save Project Group or Save Project Group As menu item from the Project Manager context menu.
Adding Units
Adding existing units to your projects is as simple as clicking the Add To Project button on the Project Manager toolbar or choosing Add To Project from the Project Manager context menu.
NOTE: You cannot add a unit to a project if a form with the same name already exists in the project. For example, if you have a form called MainForm and try to add a unit from another project that also has a form named MainForm, you get an error message from Delphi even if the filenames are different.
Removing Units
You use the Remove From Project option to remove files from the project. Alternatively, you can select the unit you want to remove and press the Delete key on the keyboard. Files removed from the project are not deleted from your hard drive, but are just removed from the project compile/link process.
CAUTION: Be careful when removing units from your projects. You must take care not to remove units that are referenced by other units in the project. If you remove units that are required by your project, a compiler error will result. Before removing a unit, be sure it is not used in your project. If you accidentally remove a needed unit from your project, you can add it back to the project with the Add To Project option as explained in the preceding section.
The Remove From Project dialog box enables multiple selection, so you can remove several units from a project at one time if you want.
Viewing Units or Forms
To view a unit, form, or other file, just double-click the node representing the form or unit you want to view. You can also choose Open from the Project Manager context menu. The form or unit will be displayed in either the Form Designer or Code Editor, depending on the type of node you are viewing.
To build a particular project, you can do one of the following:
Right-click the project node in the Project Manager and choose Build from the context menu.
Choose Project|Build <project name> from the Delphi main menu. The name of this menu item will change based on the name of the active project.
Press Ctrl+F9 on the keyboard to compile the active project.
To build an entire project group, choose Project|Build All Projects from the Delphi main menu. All projects in the project group will be built starting with the first project in the group (the project at the top of the Project Manager tree) and proceeding down through the last project in the group.
Project options are another of those features that are easy to ignore. For one, the defaults are usually good enough when you are just starting out. After all, who has time to worry about all those compiler/linker options when you are simply struggling to learn a new programming environment? At some point, though, you will start to become more interested in what all those options do, and it's good to have some reference when the time comes.
This section looks at the Project Options dialog box. You can invoke this dialog box by choosing Project|Options from the main menu. The Project Options dialog box is a tabbed dialog box with several pages:
Directories/Conditionals
I won't discuss every page of the Project Options dialog box, but you'll take a look at the most important pages so that you can understand more about what each of these pages does. I'll start you out easy by discussing the Forms and Application pages. After that I'll move on to the more complicated pages.
NOTE: At the bottom of each page of the Project Options dialog box is a check box labeled Default. If you want the current settings to become the default settings for all new projects created, check the Default box. When you click OK, the current settings become the new default settings.
The Forms page of the Project Options dialog box is where you control how your application handles its forms. You saw this dialog box on Day 4 when you created the Picture Viewer program. Figure 9.3 shows the Forms page of the Project Options dialog box for the ScratchPad program.
FIGURE 9.3. The Forms page of the Project Options dialog box.
At the top of the Forms page is the Main form combo box. This is where you tell Delphi which form to display when the application starts. By default, the first form you create will be the main form. If you change your project around in such a way that a different form becomes the main form, you must change this setting so that the new form becomes the application's main form.
In the middle of the dialog box are two list boxes. The list box on the left is labeled Auto-create forms; the one on the right is labeled Available forms. Before I talk about how to use these two list boxes, let's take a moment to go over auto-creation of forms.
Auto-creation means that Delphi will construct the form during the application startup process.
Each time you create a form, Delphi places that form in the auto-create list for the application. Forms that are auto-created display more quickly than forms that are not auto-created. The disadvantage to auto-creation of forms is that your application will use more memory than it would if your forms were not auto-created. Another disadvantage, although probably insignificant, is that your application will take slightly longer to load if you are auto-creating a lot of forms.
NOTE: The first form in the Auto-create forms list box is always the main form. If you change the main form, the new form selected will move to the top of the Auto-create forms list box. Another way to set the main form is to drag and drop any of the forms in the Auto-create forms list box to the top of the list.
The nice thing about auto-creation is that displaying an auto-created form is easy. All you do is call that form's Show or ShowModal function:
AboutBox.ShowModal;
If you do not have your forms auto-created by Delphi, you must take the responsibility of creating the form before you use it:
About : TAboutBox;
About := TAboutBox.Create(Self);
About.ShowModal;
About.Free;
This example does not use the Delphi-generated pointer to the About box. It creates a local pointer, displays the form, and then deletes the pointer as soon as the form is no longer needed. As is often the case in Object Pascal programming, there are several ways to perform this particular task. Because Delphi always creates a pointer to the form object, you could have written the previous code like this:
if not Assigned(AboutBox) then
AboutBox := TAboutBox.Create(Self);
This code checks to see whether the form has already been created. If it has not, the object is created, and then the ShowModal method is called. Deciding which method of form creation you will use is up to you, but I prefer the former because it handles everything locally.
NOTE: Each time you create a form in the Form Designer, Delphi creates a pointer to the form. If you enable Delphi to auto-create a form, you don't have to worry about the pointer being valid. If you choose not to have a form auto-created, the pointer to the form will be nil until you explicitly create the form and initialize the pointer. If you forget and use the pointer before it is initialized, Windows will generate an access-violation error.
Okay, now turn your attention back to the Project Options dialog box. The Auto-create forms list box contains a list of the forms that will be auto-created. If you do not want a form to be auto-created, drag the form from the Auto-create forms list box to the Available forms list box. To move several forms at one time, simply select the forms you want to move (both list boxes support multiple selection) and drag and drop them all at once. It's that easy.
NOTE: You can use the buttons between the two list boxes to move forms from one list box to the other, but it's usually easier to use drag and drop.
The Application page of the Project Options dialog box is very simple (see Figure 9.4).
FIGURE 9.4. The Application page.
The Title field on this page is used to set the title of the application. The title is the text that will appear on the Windows taskbar when your application is minimized.
NOTE: The application's title and the caption of the main form are two separate items. If you want your program's name to show up when you minimize your program, you must be sure that you set the title for the application in the Project Options dialog box. If you do not provide an application title, the name of the project file is used by default.
The Help file field of the Application page is used to set the help file that your application will use. This is the help file that the program will load when you press F1 while your application is running. You can use the Browse button to locate the help file if you can't remember the name or location of the help file. If you do not supply a help file, pressing F1 in your application will have no effect.
The Icon option enables you to choose an icon for your application. This is the icon that will be displayed in the Windows taskbar when your application runs and when it is minimized. In addition, this icon will be displayed on your main form's title bar unless you have explicitly set an icon for the main form. To choose an icon, click the Load Icon button and locate the icon file (.ico) using the Application Icon dialog box.
You use the Target file extension field to specify the filename extension of the project when the project is built. For example, if you were creating a screen saver, you would change this field to scr so that your screen saver would be created with an extension of .scr rather than .exe. Control Panel applets are another example. These are special programs saved with a .cpl extension. The project filename extension is automatically set to .exe for executable projects (console applications and GUI applications) and to .dll for DLLs, so you don't have to provide a value for this field for normal projects.
The Compiler page of the Project Options dialog box is where you set the options that the compiler uses to build your project. Figure 9.5 shows this page of the Project Options dialog box.
The Compiler page is divided into five sections. I'll take each section and examine it so that you can better understand the different options on this page.
FIGURE 9.5. The Compiler page of the Project Options dialog box.
The compiler can be configured to perform optimizations on your code. When optimizations are turned off (the Optimization check box is not selected), the compiler makes no attempts to optimize code in any way. If you turn the Optimization option on, the compiler will generate the fastest code possible without regard to code size. In most cases, you should leave this option on the default setting. Sometimes, however, it is better to turn optimization off while debugging your application. I'll discuss optimization and debugging in more detail on Day 10, "Debugging Your Applications."
The Aligned Record Fields option is used to control how records are aligned in memory. When this option is on, records are aligned on 4-byte boundaries. When this option is off, records are byte-aligned.
You might want to turn the Stack Frames option on when debugging. When you are finished debugging, you can turn off this option to have the compiler generate smaller and faster code, but compile times will be slightly longer with the Stack Frames option off.
The Pentium-Safe FDIV option causes the compiler to generate code that detects a faulty floating-point division instruction.
Syntax Options and Runtime Errors
These two sections affect how the compiler generates code for a project. The Delphi help for the Compiler page explains what each of these options is for, so I won't repeat that information here. To display the help page for the compiler options, click the Help button when the Compiler page is displayed or press the F1 key on the keyboard.
The Debugging section of the Compiler page of the Project Options dialog box controls how the compiler generates code for debugging sessions. When the Debug information option is enabled, Delphi generates debug information for the project. If you do not generate debug information, you will not be able to stop on breakpoints and inspect variables during debugging. Put another way, you can't debug your program unless you tell Delphi to generate debug information.
NOTE: If you change any of the options on the Compiler page, you should do a build immediately following the change. This will ensure that all units are rebuilt using the same compiler settings.
The Messages section determines whether you want the compiler to report hints and warnings after compiling. I always leave both the Show Hints and Show Warnings options on. Hints and warnings should not be ignored in the long term (in the short term, you can ignore warnings that you know are due to temporary conditions in your code). Usually, compiler warnings can, and should, be resolved. Learn to treat hints and warnings as errors. Quality code compiles without warnings.
The Linker page of the Project Options dialog box is where you set options that specify how you want the linker to operate. Until you become very familiar with Delphi, you can leave this page alone and accept the default settings. Figure 9.6 shows the Linker page of the Project Options dialog box. The options available on this page are explained in the following sections.
FIGURE 9.6. Project Linker options.
Map File
The Map File settings control whether a map file is generated and how much detail is included in it. A map file is an advanced debugging tool and is something that you will not likely use until you get further into Delphi. For that reason, I won't go into more detail on the Map File options.
EXE and DLL Options
The EXE and DLL Options section determines the type of executable file produced by Delphi for an application project. When the Generate Console Application check box is checked, Delphi produces a console application as opposed to a GUI application.
The Include TD32 Debug Info option causes the linker to link the debug information into the EXE or DLL. ("TD32" refers to the 32-bit version of the venerable old Turbo Debugger. TD32 is an advanced standalone debugger that used to ship with Borland C++ products and with some versions of Delphi.) Some debugging utilities use debug information in TD32 format. TurboPower's Memory Sleuth, for example, requires TD32 debug information to be present in the EXE. Turn this option on when using programs like Memory Sleuth.
The Include Remote Debug Symbols option generates the debug symbols necessary for remote debugging of Web broker applications.
Linker Output
The Linker Output section determines what type of compiled binary file the linker should produce. Normally the linker produces DCU files (the default for Delphi applications). You might, however, want to generate C or C++ object files (OBJs) rather than DCUs, thereby allowing your Pascal units to be used with a C or C++ program built with Borland C++Builder.
Memory Sizes
The Memory Sizes section can be ignored by all but the most advanced users. The default values are acceptable for all applications. In some cases, you might change the Image base address when building a DLL, but doing so is rarely necessary.
The EXE Description field is used to specify a string that will be embedded in the application. This field is sometimes used to add copyright information to an EXE or DLL. Most of the time, you will use version info to store copyright information in a file rather than using the EXE Description field on this page. Version info is described later in the section "The Version Info Page."
The Directories/Conditionals page of the Project Options dialog box is where you set the directories that your project uses to find library files. Figure 9.7 shows the Directories/ Conditionals page. The fields on this page are described in the following sections.
FIGURE 9.7. The Directories/ Conditionals page.
The fields in this section determine where Delphi can find various source files during compilation of the project. It also contains fields that determine where certain files created by the compiler and linker will be placed during a build of the project.
The Output Directory field is used to specify the directory where the final executable file or DLL will be placed. The Unit Output Directory determines where the DCU files will be placed for each unit compiled. The Search Path field is used to specify the directories where any additional libraries needed to build the project can be found. The Debug Source Path field is used to specify the path to any source units that you want to debug, but which are not in the current project's directory. For example, if you want to step into a DLL while debugging, you have to enter the path to the DLL's source code in this field. The BPL Output Directory and the DCP Output Directory fields specify where the BPL and DCP files should be placed when building a package.
Note that a small button with an ellipsis on it appears next to several of the fields on the Directories/Conditionals page. Clicking this button displays an editor that enables you to add, remove, or rearrange the items in a particular field. Figure 9.8 shows this dialog box while editing the Search Path field.
FIGURE 9.8. The Directories editor dialog box.
You use the Conditional Defines field to specify any defines that you want to add at the project level. For example, let's say you have code in your project that will be compiled only if the symbol TRIALRUN is defined. In that case, you would add TRIALRUN to the Conditional Defines field. If you have more than one symbol to define, make sure that each symbol is separated by a semicolon.
The Unit Aliases field is used to specify any unit aliases. For example, Delphi 1 used units called WinTypes.pas and WinProcs.pas for all Windows-specific code. Delphi 2, 3, and 4 use a unit called Windows.pas in place of WinTypes and WinProcs. The Unit Aliases field aliases WinTypes and WinProcs to the Windows unit. In this case, aliasing enables programs written in Delphi 1 to compile in Delphi 4 without modification of the uses list.
The Version Info page enables you to set the version information for your applications. Version information is stored in your program's EXE file or in a DLL or ActiveX file. It is used by installation programs to determine whether a file being installed is older or newer than the file it is replacing.
Version info has other uses as well. You can view the version information for a file from Windows Explorer. Just right-click the file and choose Properties from the Explorer context menu. When the Properties dialog box comes up, click the Version tab to view the version information for the file. Figure 9.9 shows the Properties dialog box displaying version information for the Database Desktop utility that comes with Delphi.
FIGURE 9.9. The Properties dialog box showing version information for DBD32.EXE.
Figure 9.10 shows the Version Info page of the Project Options dialog box. At the top of the page is a check box labeled Include Version Information in Project. When this check box is checked, version information will be included in the project's executable file. When this check box is not checked, version information is not included in the project, and the rest of the page is disabled.
FIGURE 9.10. Version information for your projects can be supplied on the Version Info page.
The remaining fields on the Version Info page are used to specify the various pieces of version information. The Major Version, Minor Version, Release, and Build fields work together to form the file version number. The version number of the file in Figure 9.10 is version 2.0, build 0. If you check the Auto-Increment Build Number option, the build number will automatically increment by one each time you perform a build.
The Module Attributes section can be used to determine any special attributes you want specified for the file. The Language section enables you to select a locale identifier for the file. For more information on the possible values for the Locale ID field, see the Windows API online help under the topic "Language Identifiers and Locales."
The table at the bottom of the Version Info page can be used to set a variety of information. This information includes your company name, the file description, the internal name of the file, the legal copyright or trademark information, the product name, product version, and any comments you want to add.
You can provide information for any of these fields or none at all (the FileVersion field is set based on the fields in the Module Version Number section). You can even add your own custom version information fields. To add a custom version info field, simply click in the version info table and scroll to the end of the table using the down-arrow key. Type the down-arrow key once more and a dialog box will be displayed asking you for the version key to add. Supply a key name and that key is added to the version info for the project. Adding version information to a project has never been so easy!
The Packages page is where you determine the type of linking that your projects will use. The top part of the page enables you to add or remove design packages, but that really doesn't have anything to do with the current project. The only option that pertains to the current project is the Build with Runtime Packages check box.
When this option is selected, your application will use dynamic linking of the VCL and any third-party components. This means that your executable file will be smaller, but you will have to be sure to ship the correct packages with your application. When this check box is off, your application uses static linking. Static linking means that any VCL code and the code from any third-party components that your application uses is linked directly into your executable file. Packages were discussed in detail yesterday in the section "Using Packages." Figure 9.11 shows the Packages page of the Project Options dialog box.
FIGURE 9.11. The Packages page.
There is no question that Delphi is highly visual in nature--that's one of the great benefits of programming with Delphi. Still, any program of any significance will have a great deal of code that must be written by hand. After you get the UI part of your application written with Delphi's impressive visual tools, you'll likely spend a long stretch with the Delphi Code Editor. The Code Editor has some features you'll learn to appreciate when you discover them.
In this section, you learn about the following:
NOTE: The Delphi Code Editor enables you to choose from four keyboard-mapping configurations: Default, IDE Classic, BRIEF, and Epsilon. The rest of this chapter assumes Default keyboard mapping. If you are already familiar with one of the other keyboard mapping configurations, you can ignore any references to specific keystrokes.
I'm going to assume that you know enough to be able to enter and delete text, highlight text with the mouse, cut, copy, paste, and so on. I won't spend any time going over functions at that level.
When it comes right down to it, the Delphi Code Editor is a typical code editor. It features syntax highlighting, which makes identifying keywords, strings, numeric constants, and comments at a glance easy. You'll look at setting the editor preferences a little later.
The Code Editor is a tabbed window. You can open as many editor windows as you like; each window will be represented by a tab along the top of the editor window that will display the name of the file. To switch to a source file, simply click the tab corresponding to the file you want to view. If more tabs exist than can be displayed at one time, scroll buttons will appear so that you can scroll among the tabs.
The status bar at the bottom of the Code Editor gives status information (obviously). The current line number and the cursor position on the line are reported in the left panel of the status bar. If the file has changed since it was last saved, the status bar will say Modified in the center panel of the status bar. The right panel of the status bar shows the current mode, either Insert or Overwrite. If the file has been set to read-only, this panel will say Read Only.
The editor window has a gray strip in the left margin that is called the gutter. The gutter is used to display icons at different stages of the development process. For example, when you set a debugger breakpoint (discussed tomorrow), a red dot is placed in the gutter. When you set a bookmark (discussed in just a bit), an icon representing the bookmark is placed in the gutter.
NOTE: If you accidentally click on the gutter when trying to select text or place the cursor, you will find that a breakpoint is set on that line. Click the gutter again to clear the breakpoint.
Opening and Saving Files
Nothing is very mysterious about opening and saving files in the Code Editor. It should be pointed out, though, that there is a difference between opening a project and opening a source file. When you choose File|Open Project from the main menu, you are prompted for the name of a project file to open. When you choose File|Open from the main menu, you can open an individual Delphi source file or form file. Actually, you can open any type of text file (including file types not listed in the Open dialog box's Files of Type field). This includes .pas, .rc, .txt, and even C++ source and header files (.cpp and .h). Both the Open and Open Project menu items have corresponding toolbar buttons.
NOTE: If you open a unit file (.pas) that contains a form, Delphi will open the source file in the Code Editor and will also open the form in the Form Designer.
You can also open multiple files at one time. To open multiple files, choose the files you want to open in the Open dialog box and click OK. Each file selected will be loaded, and a tab for each file will be placed at the top of the editor window.
TIP: You can also use drag-and-drop to open files. For example, you can choose a file (or a group of files) in Explorer, drag it onto the Code Editor, and drop it. The file will be opened in the Code Editor.
To save a file, choose File|Save or File|Save As from the main menu or type Ctrl+S on the keyboard. If the file has not been previously saved, the Save As dialog box will appear, and you can enter a filename at that time.
Although text highlighting is basic text-editor stuff, I thought it wouldn't hurt to remind you of a few basic highlighting techniques you can use in the Delphi Code Editor.
To highlight a short block of text, you can use the mouse to drag across any text you want to highlight. After you've selected the text, you can cut, copy, or paste as needed. To highlight longer blocks of code, you can use the Click+Shift+Click method. First, click at the beginning of the block you want to highlight. Next, hold the Shift key on the keyboard and then click again at the end of the block. All text between the starting point and the ending point is highlighted.
Another useful feature is the capability to quickly select an individual word. To select a keyword, function name, or variable, just double-click on the word. Now you can perform any editing operations you want with the highlighted word.
TIP: To select a single line of code with the mouse, click at the beginning of the line and drag straight down to the beginning of the next line. To highlight a single line of code with the keyboard, first press the Home key to move to the beginning of the line and then use Shift+down-arrow key to highlight the line.
Dozens of keyboard combinations can be used to highlight text and do other editing chores. For a complete list of all the keyboard shortcuts available, consult the Delphi online help.
TIP: As you program you often add, delete, or move blocks of text. Sometimes you will need to indent an entire block of code. At other times you will need to un-indent (outdent?) an entire block of code. To indent a block of code, highlight the lines that you want to indent and then press Ctrl+Shift+I on the keyboard. The entire block will be indented. To un-indent a block of code, press Ctrl+Shift+U on the keyboard.
The Code Editor also supports drag-and-drop editing. To move a section of code, first highlight it. Next, place the mouse cursor over the highlighted text and drag. Drag until the cursor reaches the location where you want the code to be placed. Release the mouse button and the code will be moved to the new location. To copy text rather than move it, repeat the preceding steps but hold down the Ctrl key before you drop the text.
The Code Editor has a virtually limitless number of undo levels (32,767 by default). Normally, you can only undo commands up to the last time you saved a file. By changing the editor options, you will be able to undo past commands even after saving the file. I'll talk about editor options and preferences later in the chapter in the section titled "Changing the Editor Options."
In general, it pays to remember this simple maxim: "Undo is your friend."
Find and Replace are used fairly heavily in programming. You might use Find to find a specific piece of code or a specific variable in your code. You might use Replace to change a variable's name or to change the name of a method. The possibilities are endless.
The Delphi Find Text and Replace Text dialog boxes implement more or less standard find-and-replace operations. To bring up the Find Text dialog box, choose Search|Find from the main menu or press Ctrl+F. Enter text in the Text to find field and click OK or press Enter. If the text is found, it will be highlighted.
NOTE: Text highlighted by the Find Text dialog box is not the same as text highlighted with the mouse. You will notice that searched text is highlighted in black whereas text selected with the mouse is highlighted in blue (assuming you haven't changed the editor defaults). Text highlighted after a search operation is not selected for editing, it's just marked so that you can see it better.
To invoke the Replace Text dialog box, choose Search|Replace from the menu or press Ctrl+R. Figure 9.12 shows the Delphi Replace Text dialog box. With a few obvious exceptions, the Find Text dialog box contains the same options.
For the most part, the options on the Find Text and Replace Text dialog boxes do exactly what they indicate. If you choose the Case Sensitive option, you must type the search text exactly as it appears in the source file.
FIGURE 9.12. The Replace Text dialog box.
Use the Whole Words Only option when you want to be sure that text for which you are searching is not part of a longer word or variable name. For example, let's say you want to replace Form with MyForm. In this case, you would want to search for whole words only because the word Form might be used in other variable names (such as TForm).
The Regular Expressions option requires explanation as well. When this option is on, you can use special and wildcard characters when doing searches. The special characters enable you to find elements such as the beginning of a line or the end of a line in your search strings. Wildcard characters work much like they do in directory operations. For a complete description of regular expressions, see the Delphi online help under the topic "Regular Expressions."
When replacing text, it is safest to leave the Prompt on Replace option on. When you do a Replace All operation with this option on, the editor will highlight each found word and prompt you whether to replace it. It is easy to miscalculate the results of a Replace All operation, so always use Replace All with care. Even then, it still pays to remember that maxim: "Undo is your friend."
The rest of the Find and Replace options are self-explanatory and therefore don't need additional mention.
Find in Files
Find in Files is a great tool for searching for text in multiple files. I frequently use Find in Files to search the VCL source code for particular methods, variables, or classes. This tool is useful and convenient, and you should learn how to use it.
To display the Find Text dialog box, you can choose Search|Find in Files from the main menu. Perhaps an easier way is to type Ctrl+F on the keyboard to bring up the Find Text dialog box and then click the Find in Files tab. Figure 9.13 shows the Find Text dialog box with the Find in Files tab showing.
FIGURE 9.13. The Find Text dialog box.
Find in Files uses some of the same search options as the regular Find operation (case-sensitive, whole word only, and regular expressions). In addition, you have the option to search all files in the project, all open files, or files in a particular directory, including subdirectories.
When you start Find in Files, a small window with a title of Searching appears in the lower-right portion of your screen. This window shows the status of the Find in Files operation. It will show you the current file being searched and the number of matches up to this point. To cancel the search, just close the Searching window.
Any matches are reported in the Code Editor's message window. The message window shows the filename of the file in which the text was found, the line number where the text was found, and the line containing the search text with the search text displayed in bold. To view the file that contains a match, just double-click a line in the message window. Delphi will open the appropriate file and display the exact line containing the text for which you are searching. Figure 9.14 shows Delphi searching a set of files.
When specifying the file mask, all the usual wildcard characters apply. For example, if you want to search all text files in a directory, you would enter the following in the File masks field:
c:\MyStuff\*.txt
Find in Files is an indispensable tool. I find myself using it all the time. Learning to use Find in Files will save you a lot of time.
FIGURE 9.14. Delphi searching for text.
One of the most useful features of the Code Editor is its integration with the Delphi help system. Just place the editor cursor over an Object Pascal keyword, a VCL property or method, or any other Delphi-specific text and press F1. If a help topic for the text under the cursor exists in the Delphi help files, Windows Help will run with the appropriate page showing. If no help topic exists for the selected text, an error message will be displayed.
This feature is extremely useful when you can't remember how to use a particular aspect of Delphi, Object Pascal, or VCL. Help, as they say, is just a keystroke away.
The Delphi Code Editor has a few features that are extremely useful when you are writing a lot of code. They are explained in the following sections.
Code Templates
Code templates are another nice feature of the Delphi Code Editor. Code templates enable you to insert any predefined code (or any text, for that matter) in your source units. To use code templates, just type Ctrl+J on the keyboard while editing in the Code Editor. When you do, a list box will pop up giving you a list of templates from which to choose. Choose a template from the list, press Enter, and the text corresponding to that code template will be inserted into your source code. Figure 9.15 shows the code template list box as it appears when you type Ctrl+J.
FIGURE 9.15. The Delphi code template list box.
You can add new templates or edit existing templates via the Code Insight page of the Environment Options dialog box. Or, if you prefer, you can open the code template file with any text editor (such as the Delphi Code Editor) and edit the code templates there. The code template file is called DELPHI32.DCI and is located in the Delphi 4\Bin directory.
Feel free to modify the code templates in any way you see fit. For example, I have modified my code template representing the for statement to look like this:
for I := 0 to Pred(|) do begin
Notice the pipe character (|) in the code snippet. The pipe in a code template entry is a placeholder that determines where the cursor will be placed after the text is inserted into your source code.
TIP: If you make a lot of modifications to the code template file, be sure to keep a backup of the file in a safe location. You will need a backup because the Delphi installation program will overwrite your modified DELPHI32.DCI file when you update or reinstall Delphi.
You can use code templates for more than just code. Here at TurboPower Software our source files always have a header at the top of the unit. It looks something like this:
{*********************************************************};
{*                 Filename and version                  *};
{*        Copyright (c) TurboPower Software 1998         *};
{*                 All rights reserved.                  *};
Because most of this text stays constant, I have a template that quickly inserts the header in any new source units I create. Use code templates for any text that you use frequently in your day-to-day programming.
Code Parameters
The code parameters feature of the Code Editor displays a tooltip that prompts you with the needed parameters of a VCL method or Windows API function. With hundreds of VCL methods and Windows API functions, there is virtually no way to remember every function's parameters. The code parameters feature saves you time by showing you the parameters of a method as you type. For example, let's say you are calling the SetBounds method. When you type the opening parentheses, a hint window pops up as shown in Figure 9.16.
FIGURE 9.16. Code parameters in action.
As you can see in Figure 9.16, each parameter is listed in the tooltip. The parameter you need to type next is displayed in bold. As you type a parameter, the next parameter is displayed in bold. This continues until you type all the method's parameters. After you have typed all the required parameters, the code parameters tooltip disappears. The code parameters options are set on the Code Insight page of the Environment Options dialog boxes. I'll discuss that page later in the section "The Code Insight Page."
Code Completion
Code completion is another Code Editor feature that can save you development time. Type a class variable name followed by the dot operator, and the Code Editor will display a list box with all of that class's properties and methods. If, for example, you have a memo component called Memo, you will type
Memo.
and pause for a moment. A list box pops up as shown in Figure 9.17.
FIGURE 9.17. Code completion displaying the properties and methods of TMemo.
When you see the list box, you can select an item from the list in one of two ways. One way is to locate a property or method in the list box using the mouse or the keyboard and press Enter. The property or method will be inserted into your code. Alternatively, you can type the first few letters of the property or method you want to insert into your code. As you type, Delphi searches the list of properties and methods for a match and highlights the item in the list that most closely matches the text you are typing.
When you see the property or method you want, press the Enter key and the property or method will be inserted into your code. If you don't want to use the code completion list box, you can press the Esc key on the keyboard and the code completion list box will disappear.
Code completion saves you time by providing a list of properties and methods from which to choose. It has the added benefit of providing perfect spelling and capitalization of property and method names. Just choose the property or method you want, press the Enter key, and Delphi inserts the identifier in your code.
Tooltip Symbol Insight
Tooltip symbol insight pops up a tooltip when you place your mouse cursor over just about any identifier in your source code. For example, a standard new project will have this line in the interface section:
TForm1 = class(TForm)
When you place your mouse cursor over the identifier TForm, a tooltip pops up that says:
type Forms.TForm = class(TCustomForm) - Forms.pas (584)
This line shows you the TForm class declaration and tells you that TForm is declared on line 584 of the Forms.pas unit.
Tooltip symbol insight will tell you information about any variable in your program. This is particularly convenient when you forget the type of a variable (was X declared as a Byte, a Word, or an Integer?).
Class Completion
Class completion is a new feature in Delphi 4. Type any properties or method declarations in the interface section and type Ctrl+Shift+C on the keyboard. Delphi will add the necessary code to the implementation section to complete the class. This is best illustrated by performing an exercise. Perform these steps:
1. Start with a blank project.
2. Switch to the Code Editor and locate the form's class declaration in the interface section.
3. Type the following code in the public section of the form's class declaration:
procedure Test;
function GetSomething : Integer;
4. Type Ctrl+Shift+C on the keyboard.
When you perform step 4, Delphi automatically adds the bodies of the Test and GetSomething methods to the implementation section and places the editing cursor in the first method. The added code looks like this:
function TForm1.GetSomething: Integer;
procedure TForm1.Test;
Keep this unit handy because you will use it again in the next section when I discuss module navigation.
Code completion works with property declarations as well as methods. Type a property declaration, type Ctrl+Shift+C, and Delphi completes the property declaration. It even adds a write method for your property. I don't cover writing properties until Day 20, "Creating Components," so this might not make much sense to you right now. It will be more clear when you begin writing your own components.
For me, class completion is one of the best of Delphi 4's new features. This feature alone has saved me a lot of time when writing components. I wouldn't be without it now that I have been using it for a period of time.
Module Navigation
Module navigation enables you to quickly move from a method in the implementation section to that method's declaration in the interface section, and vice versa. Again, an exercise is worth a thousand words. Do this:
1. Navigate to the class declaration of the form you modified in the previous exercise.
2. Click on the line containing the Test procedure's declaration.
3. Type Ctrl+Shift+down arrow on the keyboard. The Code Editor jumps to the Test procedure body in the implementation section.
4. Type Ctrl+Shift+up arrow. The Code Editor jumps back to the Test procedure's declaration in the interface section.
5. Move down a line to the GetSomething function declaration. Type Ctrl+Shift+down arrow again. The Code Editor jumps to the GetSomething method in the implementation section.
As you can see, module navigation makes it easy to quickly move between the implementation and interface sections.
TIP: It doesn't matter whether you use the up arrow button on the keyboard or the down arrow button. Either button acts as a toggle between the interface and implementation sections.
Module browsing is another module navigation tool. In the Code Editor, hold down the Ctrl key and place the mouse cursor over an identifier name. The identifier will be highlighted in blue and underlined. Click on the identifier and Delphi will take you to the place in the source where that identifier is declared.
In this regard, the module browser is like the module navigation feature. It goes beyond that, however. With the module browser, you can click on a VCL identifier as well as your own identifiers. Let me illustrate with an example. Before starting, however, I should point out that this exercise will work only if you have the Professional or Client/ Server version of Delphi. It requires the Delphi source code to work. Perform these steps:
1. Create a new application. Place a button and a memo on the form.
2. Choose Project|Options from the main menu. Click on the Directories/Conditionals tab of the Project Options dialog box. Type the following in the Search path field:
$(DELPHI)\source\vcl;$(DELPHI)\source\rtl\win
Click OK to close the Project Options dialog box.
3. Double-click the button and add this text in the OnClick event handler for the button:
Memo1.Clear;
The Clear method of TMemo clears the memo of its contents. Are you curious about what the VCL source looks like for the Clear method? Keep going. . .
4. Hold down the Ctrl key on the keyboard and click on Clear.
5. After a few moments, the VCL StdCtrls unit is displayed in the Code Editor with the cursor on the TCustomEdit.Clear method (the Clear method is defined in the TCustomEdit class, one of TMemo's ancestor classes). The method looks like this:
procedure TCustomEdit.Clear;
SetWindowText(Handle, `');
Interesting. Just one line of code. But where does SetWindowText come from? Next step, please.
6. Hold down the Ctrl key again and click on SetWindowText. After a few seconds the Windows unit is opened and the cursor is on this line:
function SetWindowText; external user32 name `SetWindowTextA';
This line tells you that SetWindowText is a Windows function contained in the DLL called USER32. Case closed. You're not quite done yet, though.
7. Now look at the tab in the top-right corner of the Code Editor window. See the back and next browse buttons? Click the back button (the one that points to the left). The Code Editor switches to the previous browse point (the Clear method in the StdCtrls unit).
8. Click the next button. The Code Editor displays the SetWindowText import in the Windows unit.
9. Click on the drop-down arrow next to the back button. You will see a list of source code locations in the browser history list. Click a location to switch the Code Editor cursor to that location.
The module browser is a great tool for navigating not only your own code, but also the VCL source code and the source code of any third-party component libraries you have installed. Remember, reading the VCL source code can teach you a lot, so don't be afraid to browse through the source.
Using Bookmarks
You can set bookmarks in your code to temporarily mark your place in a source file. For example, you often must temporarily leave a block of code on which you are working to review previously written code or to copy code from another location. By dropping a bookmark at that point in your code before running off to do your other work, you can return to that section of code with a simple keystroke. You can have up to 10 bookmarks set at any one time.
To set a bookmark at a particular location, press Ctrl+Shift and the number of the bookmark to set. For example, to set bookmark 0 (the first bookmark), place the editor cursor at the location you want to mark and then press Ctrl+Shift+0 (Ctrl+K+0 will work as well). When you set a bookmark, an icon is placed in the Code Editor gutter to indicate that a bookmark exists on that line. The icon shows the number of the bookmark. Figure 9.18 shows the Code Editor with a bookmark dropped on a line.
FIGURE 9.18. The Code Editor with a bookmark set.
To return to the bookmark, press Ctrl plus the number of the bookmark to which you want to return. Using the same example, you would type Ctrl+0 to go back to the bookmark. (You can also set bookmarks and go to bookmarks using the Code Editor context menu.) To clear a bookmark, place the editor cursor anywhere on the line containing the bookmark and again press Ctrl+Shift+0.
NOTE: Bookmarks can be set for each file you have open in the Code Editor. For example, you can have bookmark #0 set in one source file and another bookmark #0 set in another source file. This means that bookmarks cannot be found across source files. If you set bookmark #0 in Unit1.pas, you cannot press Ctrl+0 in Unit2.pas and expect to be taken to the bookmark in Unit1.pas.
To illustrate the use of bookmarks, do the following:
1. Open any source file in the Code Editor.
2. Scroll almost to the bottom of the file and click on a line of code.
3. Press Ctrl+Shift+0 to set a bookmark. The bookmark icon shows in the Code Editor gutter.
4. Press Ctrl+Home to move to the top of the source file.
5. Now press Ctrl+0 to jump back to the bookmark. The Code Editor changes to show the line of code where the bookmark was set, and the cursor is placed exactly where it was when you set the bookmark.
6. Type Ctrl+Shift+0 again to clear the bookmark. The bookmark is cleared and the bookmark icon disappears from the Code Editor gutter.
Note that bookmarks are temporary. When you close the source file and reopen it, the bookmark is not preserved. Note also that to set and remove bookmarks you must type the number keys on the main keypad. The numeric keypad is ignored when setting and removing bookmarks.
You can use the incremental search option to quickly find a short series of characters. To start an incremental search, choose Search|Incremental Search from the main menu or press Ctrl+E on the keyboard. To understand how the incremental search
works, it is easiest to do an exercise. Do the following:
1. Create a new text file from the Object Repository. (It doesn't matter whether you currently have a project open.)
2. Type the following text:
Learning to write Windows
programs a bit at a time
is not so bad. Isn't it
time you got back to work?
3. Move the cursor back to the top of the file (Ctrl+Home).
4. Press Ctrl+E to start the incremental search. You will be searching for the word back. Note that the Code Editor status bar says Searching for:.
5. Type a b on the keyboard. The letter b in the word bit is highlighted. That's not what you are looking for.
6. Now type an a on the keyboard. The next occurrence of ba is found, this time in the word bad. That's still not what you are looking for.
7. Type a c on the keyboard. The letters bac in the word back are highlighted. Now type a k. The Code Editor status bar now says Searching for: back and the word back is highlighted. Congratulations, you found what you were looking for!
8. Press Esc (or Enter) on the keyboard to stop the incremental search. Close the text file without saving it.
That's all there is to it. The incremental search is handy when you are searching for short amounts of text.
TIP: If you make a mistake when typing the characters while doing an incremental search, you can use the Backspace key to remove from the search string the last character typed.
Finding Matching Brackets and Parentheses
The Code Editor has a feature to help you find a bracket or parenthesis that matches the bracket or parenthesis the cursor is currently on. To find a matching bracket, place the cursor before a bracket (it doesn't matter whether it's the opening or closing bracket). Now press Alt+[ on the keyboard. The cursor jumps to the bracket that matches the bracket on which you started.
Press Alt+[ again, and the cursor jumps back to where you started. The same keystrokes work for parentheses as well as brackets. Getting lost in the maze of parentheses and brackets is still a possibility, but at least now you know how to find your way out again.
Like most of the different windows you encounter in Delphi, the Code Editor has its own context menu. The Code Editor context menu can essentially be divided into two parts: editor items and debugger items. I will leave the debugger items of the context menu for tomorrow when I discuss debugging, but I'll go over the editor items on the context menu now. Table 9.4 contains a list of the context menu items that pertain to the editor, along with a description of each.
TABLE 9.4. THE CODE EDITOR CONTEXT MENU ITEMS.
Close Page Closes the active page in the edit window. If the file on the page has been modified since it was last saved, you are prompted to save the file.
Open File At Cursor Opens the file under the cursor. This option has an effect only when the text under the cursor represents a source code file. For example, if you have a file in your uses list called MyUnit2, you could click on the filename and choose this menu item to open the file. The file will be placed in a new editor window and focus will be set to the window.
New Edit Window Opens a new copy of the Code Editor. This is convenient if you want to compare two source files side by side.
Browse Symbol At Cursor Starts the browser with the current symbol as the browse target.
Topic Search Displays the help topic for the item under the cursor (if it can be found). Same as pressing F1 on the keyboard.
Add to Interface Adds a property, function, or procedure to an ActiveX component. This item is disabled if the project is not an ActiveX project.
Toggle Bookmarks Toggles a bookmark (0 through 9) on or off. The bookmark is set on the source code line containing the editing cursor.
Goto Bookmarks Moves the source code editor to a bookmark.
View As Form If the active file in the Code Editor is displaying a form's contents as text, choosing this option will again display the form in the Form Designer.
Read Only Toggles the currently active file between read-only and read/write mode. When set to read-only, the file cannot be modified, although text can be selected and copied to the Clipboard. The status bar displays Read Only to indicate the file is read-only. When the file is closed and reopened, it is again in read/write mode.
Message View Displays or hides the Delphi message window. The message window automatically appears when there are compiler or linker errors or warnings, but can be specifically shown or hidden with this command.
View Explorer Sets focus to the Code Explorer window. If the Code Explorer is not docked, this command will bring it to the top of all other windows.
Properties Displays the Environment Options dialog box so that the editor options can be set.
Depending on the current state of the Code Editor and the particular type of file open, some of the items in Table 9.4 can be disabled at any given time.
The editor options occupy three pages of the Environment Options dialog box. To view this dialog box, choose Tools|Environment Options from the main menu.
TIP: You can also choose Properties from the Code Editor context menu to view the editor options. The difference with this method is that only the four pages pertaining to the editor options will be displayed. When displayed this way, the dialog box is titled Editor Properties rather than Environment Options. The figures in the following sections were taken using this method.
The four pages of the Environment Options that are specific to the Code Editor are as follows:
Code Insight
Let's examine these pages in the following sections.
The Editor Page
The Editor page of the Editor Properties dialog box enables you to control how the editor wor


text:
Bath Rugby Digest: James Bond, fantasy calamity, Attwood lands, poor Nicol
We take an alternative look at what's been happening in and around the club...
Daniel EvansHead of sport content
It's been a busy and interesting past week in the world of Bath Rugby.
We've seen a star performance in the Six Nations, a new signing announced at the club and the shock loan move of Dave Attwood.
We've taken an alternative look at what's been happening in and around the Blue, Black and Whites. Here's the latest edition of the Bath Rugby Digest...
He should have picked him!
Player-turned-pundit Alex Corbisiero made a fundamental error when picking his Six Nations fantasy team... he didn't pick Anthony Watson!
Watson scored two tries in the opening quarter of England's 46-15 win against Italy in Rome.
At least Corbisiero - who knows Watson from his London Irish and England days - had the decency to admit it in public.
Mercer back in the England mix but Thomas and Dunn miss out as preparations begin for Wales clash
Special agents...
Not for the first time, James Bond actor and rugby fan Daniel Craig was waiting in the wings after an England of British and Irish Lions victory.
He popped into the changing room after the game, much to the delight of the players...
Spare a thought for Andy...
It wasn't a great weekend for former Bath skipper Andy Nicol, who was at the Principality Stadium in Cardiff as Wales thrashed Scotland 34-7.
At least someone was kind enough to buy him dinner...
DANIEL EVANS: No Bath Rugby player will be more important than Freddie Burns during the Six Nations
Touch down for Attwood...
The shock news from last week was Dave Attwood's loan to Toulon until the end of the season.
He's landed safely in Provence in the South of France. The fit-again could make his debut against Stade Francais in the Top14 on February 17.
Bath Rugby Digest: Beno's rap, chasing Watson, charity challenge, fitness favourites
Batty is back...
Ross Batty came through 46 minutes of the win against Ospreys unscathed.
It was his first game for Bath since having neck surgery last May and his 150th for the club.
Here's what he told Bath Rugby TV after the game at the Liberty Stadium...
Bath Rugby's Anglo-Welsh Cup semi-final kick-off and date confirmed
Hell of a score...
Bath Rugby held a vote on the best try at the Rec so far this season.
Created by Zach Mercer, fourth place was this cracker from Paul Grant. What will be first?
Bath RugbyBath Rugby sign up three more players for the senior academyThe University of Bath trio have all had experience in blue, black and white before
Bath RugbyBath Rugby's top 10 try-scorers of the 2017/18 seasonWe've totted up all the tries in the Premiership, Champions Cup and Anglo-Welsh Cup
Bath RugbyTeam News: George Ford will lead Leicester Tigers against Bath Rugby in The ClashThe England fly-half was playing for the opposition in the first staging of the annual Premiership match at Twickenham last year
Bath RugbyDANIEL EVANS: From footnote to forefront, Bath Rugby now really need Anglo-Welsh Cup winThe domestic trophy was not even on their radar before the season started, but now there's not much else to take home
Football NewsJerry Gill praises Bath City's 'great response' for victory at Poole Town - after empathising with Manchester United boss Jose MourinhoThe Romans chief reflects on a strong victory in Dorset

redpajama_set_name: RedPajamaCommonCrawl


90' Free Kick Free kick for FC CFR 1907 Cluj in their own half.
90' Throw In Throw-in for FC CFR 1907 Cluj in their own half.
90' Throw In FC CFR 1907 Cluj awarded a throw-in in their own half.
90' Goal Kick It's a goal kick for the away team in Malmo.
90' Injured player returns De Luca, Giuseppe Giuseppe De Luca has recovered and rejoins the match in Malmo.
90' Muresan, Andrei Andrei Muresan (FC CFR 1907 Cluj) gets a yellow card.
89' Throw In Ball safe as FC CFR 1907 Cluj is awarded a throw-in in their half.
88' Injury De Luca, Giuseppe Play has been interrupted briefly in Malmo to check on Giuseppe De Luca, who is grimacing with pain.
87' Throw In Can FC CFR 1907 Cluj get the ball into an attacking position from this throw-in in Malmo FF's half?
87' Free Kick FC CFR 1907 Cluj awarded a free kick in their own half.
86' Offside Tucudean, George Andrew Dallas blows against FC CFR 1907 Cluj's George Tucudean for offside.
84' Free Kick FC CFR 1907 Cluj awarded a free kick in their own half.
83' Throw In Andrew Dallas signals a FC CFR 1907 Cluj throw-in in Malmo FF's half.
83' Throw In FC CFR 1907 Cluj to take a throw-in in Malmo FF territory.
83' Throw In Throw-in for FC CFR 1907 Cluj at Stadion.
82' Omrani, Billel Billel Omrani (FC CFR 1907 Cluj) has been booked and must now be careful not to get a second yellow card.
80' Offside De Luca, Giuseppe FC CFR 1907 Cluj's Giuseppe De Luca is whistled for offside at Stadion.
79' Shot off target Muresan, Andrei FC CFR 1907 Cluj attack but Andrei Muresan's header doesn't find the target.
79' Corner Kick De Luca, Giuseppe FC CFR 1907 Cluj have been awarded a corner by Andrew Dallas.
79' Throw In Andrew Dallas signals a FC CFR 1907 Cluj throw-in in Malmo FF's half.
78' Throw In Ball safe as FC CFR 1907 Cluj is awarded a throw-in in their half.
77' yellow_red_card Culio Culio in FC CFR 1907 Cluj has been yellow-carded a second time by Andrew Dallas and is being sent off.
76' Throw In Can FC CFR 1907 Cluj get the ball into an attacking position from this throw-in in Malmo FF's half?
76' Free Kick Free kick for FC CFR 1907 Cluj in the half of Malmo FF.
73' Throw In FC CFR 1907 Cluj awarded a throw-in in their own half.
73' Shot on target Bordeianu, Mihai Mihai Bordeianu gets his shot on target but fails to score for FC CFR 1907 Cluj.
69' Shot off target Tucudean, George FC CFR 1907 Cluj's George Tucudean breaks free at Stadion. But the strike goes wide of the post.
68' Throw In Andrew Dallas awards the away team a throw-in.
64' Throw In Throw-in for FC CFR 1907 Cluj in their own half.
64' De Luca, GiuseppeHoban, Ovidiu The away team replace Ovidiu Hoban with Giuseppe De Luca.
62' Culio Culio (FC CFR 1907 Cluj) has received a yellow card from Andrew Dallas.
59' Throw In FC CFR 1907 Cluj awarded a throw-in in their own half.
58' Bordeianu, MihaiDjokovic, Damjan Toni Conceicao is making the team's second substitution at Stadion with Mihai Bordeianu replacing Damjan Djokovic.
57' Throw In Can FC CFR 1907 Cluj capitalize from this throw-in deep inside Malmo FF's half?
53' Throw In Throw-in FC CFR 1907 Cluj.
49' Free Kick Free kick for FC CFR 1907 Cluj in their own half.
48' Throw In Ball safe as FC CFR 1907 Cluj is awarded a throw-in in their half.
47' Throw In Can FC CFR 1907 Cluj get the ball into an attacking position from this throw-in in Malmo FF's half?
46' Free Kick Andrew Dallas signals a free kick to FC CFR 1907 Cluj in their own half.
45' Corner Kick Camora Corner awarded to FC CFR 1907 Cluj.
45' Shot on target Hoban, Ovidiu Ovidiu Hoban (FC CFR 1907 Cluj) goes close with a header but the ball is scrambled away by Malmo FF defenders.
45' Throw In Andrew Dallas signals a FC CFR 1907 Cluj throw-in in Malmo FF's half.
45' Shot on target Tucudean, George George Tucudean for FC CFR 1907 Cluj drives towards goal at Stadion. But the finish is unsuccessful.
45' Goal Kick Goal kick for FC CFR 1907 Cluj at Stadion.
44' Goal Kick FC CFR 1907 Cluj have a goal kick.
43' Mailat, SebastianDeac, Ciprian The away team have substituted Ciprian Deac with Sebastian Mailat. Toni Conceicao is thus making his first change.
41' Injury Deac, Ciprian Andrew Dallas waits before resuming play because Ciprian Deac for FC CFR 1907 Cluj is still down.
41' Throw In FC CFR 1907 Cluj to take a throw-in in Malmo FF territory.
40' Injured player returns Culio Culio returns to the field for FC CFR 1907 Cluj after picking up a slight injury.
38' Injury Culio The match has been stopped briefly for attention to the injured Culio.
38' Free Kick FC CFR 1907 Cluj awarded a free kick in their own half.
37' Injured player returns Deac, Ciprian FC CFR 1907 Cluj's Ciprian Deac is on his feet again at Stadion.
36' Djokovic, Damjan0-1 Goal! The away team take a 0-1 lead through Damjan Djokovic.
35' Injury Deac, Ciprian Attention is being given to FC CFR 1907 Cluj's Ciprian Deac and play has been suspended briefly.
34' Free Kick Free kick FC CFR 1907 Cluj.
34' Goal Kick It's a goal kick for the away team in Malmo.
32' Throw In Throw-in for FC CFR 1907 Cluj in their own half.
30' Offside Tucudean, George At Stadion, FC CFR 1907 Cluj are penalized for being offside.
29' Throw In Throw-in for FC CFR 1907 Cluj close to the penalty box.
29' Throw In Malmo FF needs to be cautious. FC CFR 1907 Cluj have an attacking throw-in.
28' Djokovic, Damjan Damjan Djokovic is booked for the away team.
27' Throw In Throw-in high up the field for FC CFR 1907 Cluj in Malmo.
26' Free Kick Free kick FC CFR 1907 Cluj.
25' Throw In Ball safe as FC CFR 1907 Cluj is awarded a throw-in in their half.
25' Throw In Andrew Dallas awards the away team a throw-in.
23' Free Kick In Malmo a free kick has been awarded the away team.
18' Throw In Throw-in FC CFR 1907 Cluj.
16' Throw In Can FC CFR 1907 Cluj capitalize from this throw-in deep inside Malmo FF's half?
16' Corner Kick Deac, Ciprian FC CFR 1907 Cluj have been awarded a corner by Andrew Dallas.
15' Throw In FC CFR 1907 Cluj to take a throw-in in Malmo FF territory.
9' Free Kick Andrew Dallas signals a free kick to FC CFR 1907 Cluj.
9' Corner Kick Deac, Ciprian Corner awarded to FC CFR 1907 Cluj.
9' Shot on target Tucudean, George FC CFR 1907 Cluj's George Tucudean is on target but unsuccessful.
8' Free Kick Andrew Dallas signals a free kick to FC CFR 1907 Cluj in their own half.
7' Shot off target Omrani, Billel Billel Omrani of FC CFR 1907 Cluj gets in a strike, but is off target.
6' Throw In Throw-in for FC CFR 1907 Cluj close to the penalty box.
6' Throw In Andrew Dallas signals a throw-in for FC CFR 1907 Cluj, close to Malmo FF's area.
5' Throw In Andrew Dallas signals a FC CFR 1907 Cluj throw-in in Malmo FF's half.
5' Offside Djokovic, Damjan FC CFR 1907 Cluj are too eager and fall into an offside trap.
2' Goal Kick Andrew Dallas awards FC CFR 1907 Cluj a goal kick.


text:
New Apartments Palm Beach, QLD Canopy Palm Beach - 3-7 Twenty Fourth Avenue, Palm Beach
Canopy Palm Beach3-7 Twenty Fourth Avenue, Palm Beach QLD 4221
Request floorplan via agent
1, 2 & 3 bedroom configurations
Estimated completion
Not Confirmed
What information would you like?
Project brochure
Pricing & floorplans
Request from agentRequest from agent
View the privacy policy
Apartments in Canopy Palm Beach
Request PricingRequest Pricing
BDA Architecture
Hutchinson Builders
Local Government Area:
Gold Coast (City)
Palm Beach, QLD
Estimated Completion Date:
Nearby Public Transport:
Bus 700 / 764 / 765
Building Height:
28.1 Metres
Floor Count:
Number of Buildings:
Number of Residences:
Meet the team behind Canopy Palm Beach
What is a developer
A developer is a person or company that buys land, finances real estate deals and appoints a builder and architect to orchestrate their vision through masterplanning, design and construction.
What is an architect
An architect is instrumental in the vision, planning, design and construction supervision to which they provide a structure or space that serves the people.
What is a builder
A builder is a person or company that has been appointed to a development to oversee, coordinate, construct or repair properties. Builders can also be self directed.
Location of Canopy Palm Beach
Display suite location
26 Pryor Street, Eltham
Ask a question about Canopy Palm Beach
Be the first one to leave a question or comment on this project
What would you like to say about this project?
Nearby education
14 University Drive (off Cottesloe Drive) Robina QLD 4226
Southern Cross Drive Bilinga QLD 4225
University of Southern Queensland
37 Sinnathamby Boulevard Springfield Central Qld 4300
176 Messines Ridge RdMount Gravatt, Qld 4122
St Lucia QLD 4072
81km away
Elanora SHS - Special Education Program
Cnr 19th Avenue & Avocado Street, Elanora QLD 4221
Elanora State High School
Palm Beach-Currumbin SHS - Special Education Program
Thrower Drive, Palm Beach QLD 4221
Palm Beach-Currumbin State High School
Marymount College (Burleigh Waters)
261-283 Reedy Creek Road, Burleigh Waters QLD 4220
Palm Beach State School
13-19 Nineteenth Avenue, Palm Beach QLD 4221
Palm Beach SS - Special Education Program
Tallebudgera Outdoor and Environmental Education Centre
1525 Gold Coast Highway, Palm Beach QLD 4221
Burleigh Heads SS - Special Education Program
Lower Gold Coast Highway, Burleigh Heads QLD 4220
Burleigh Heads State School
Check out the construction update photos our members have been uploading
Thank you for your photo!
The urban community thrives on the help of its user. Check back soon to see your photo live.
Make sure you upload valid image with size less than 8MB.
1073-1077 Gold Coast Highway, Palm Beach
13-15 Haig Street, Kirra Beach
Sea Palm Beach
16 Seventh Avenue, Palm Beach
Subscribe to Project Updates
Stay up to date with the latest information, brochures, construction timelines, and any other information we receive about Canopy Palm Beach.
How would you describe yourself SelectI'm looking for my first homeI'm looking for my next homeI'm looking to investI work in the property industry
I'd like to know more about Canopy Palm Beach - 3-7 Twenty Fourth Avenue, Palm Beach
Over 12 months
Up to $400,000
What is your preferred suburb?
By submitting this form, you agree to the Aussie privacy policy.
Property Industry - Other
Estimated completion date
Visiting a display suite
Not Contacted
Info via email
Phone call request
To be contacted
Looking for more info
Mortgage Plan
What did you like about it?
submission_mode
Which one sounds like you?
Next Home Buyer
In addition to brochure & pricing, would you like an invitation to the display suite?
Which property are you interested in?
1 Bed | 1 Bath | 1 Car - From
Do you plan to get a mortgage for this property?
Fantastic! What's your name?
What's your phone number?
If it's your first time on Urban, we will verify your number via SMS.
Please enter the verification code we sent to +00000000. Change phone number
Didn't receive your code? Resend
Would you like to be contacted by the developer?
So where should we send the brochure and pricing?
Request from agentRequest floorplan via agent
+1+7+20+27+30+31+32+33+34+36+39+40+41+43+44+45+46+47+48+49+51+52+53+54+55+56+57+58+60+61+62+63+64+65+66+81+82+84+86+90+91+92+93+94+95+98+212+213+216+218+220+221+222+223+224+225+226+227+228+229+230+231+232+233+234+235+236+237+238+240+241+242+243+244+248+249+250+251+252+253+254+255+256+257+258+260+261+262+263+264+265+266+267+268+269+297+298+299+350+351+352+353+354+355+356+357+358+359+370+371+372+373+374+375+376+377+378+380+381+382+385+386+387+389+420+421+423+500+501+502+503+504+505+507+509+590+591+592+593+594+595+596+597+598+599+670+673+675+676+678+679+682+685+687+689+852+853+855+856+880+881+882+886+960+961+962+963+964+965+966+967+968+970+971+972+973+974+975+976+977+992+993+994+995+996+998+1242+1246+1264+1268+1284+1345+1441+1473+1649+1664+1670+1671+1684+1758+1767+1784+1868+1869+1876+9725
Schedule a call with a project expert to access the latest floorplans and pricing
Speaking to a project expert is the only way to get the most up-to-date pricing & floorplans
Your next steps:
We've emailed you the brochure & subscribed you to project updates.
A representative from the development will be in touch to assist with your enquiry.
An Aussie Mortgage Broker will also call you shortly to discuss your home loan needs.
We've sent your request to .
Want to speed up the process? Call the agent to access floorplans now.
Do you plan on getting a home loan when you are ready to purchase?
Final step, getting finance ready. Speak to an Aussie Home Loans broker & see how much you can borrow
Current Suburb
Great! Please confirm this is the best number and Aussie mortgage broker can reach you on?
Buyer Type
No, I don't need finance
By submitting this form, you agree to the Aussie Privacy Policy .
We're not agents.
We're not developers.
We're urban.com.au.
We're on a mission to radically improve the quality of Urban communities being developed across Australia.
Developments Melbourne
Developments Sydney
Developments Brisbane
Developments Perth
Developments Canberra
Developments Adelaide
Developments Parramatta
New apartments
New apartments Melbourne
New apartments Sydney
New apartments Brisbane
New apartments Perth
New apartments Canberra
New apartments Adelaide
New apartments Parramatta
New townhouses
New townhouses Melbourne
New townhouses Sydney
New townhouses Brisbane
New townhouses Perth
New townhouses Canberra
New townhouses Adelaide
New townhouses Parramatta
Download our app and stay up to date with the market
Add your number and we'll send you a link to download the app
+0+1+2+3+4+5+6+7+8+9+10+11+12+13+14+15+16+17+18+19+20+21+22+23+24+25+26+27+28+29+30+31+32+33+34+35+36+37+38+39+40+41+42+43+44+45+46+47+48+49+50+51+52+53+54+55+56+57+58+59+60+61+62+63+64+65+66+67+68+69+70+71+72+73+74+75+76+77+78+79+80+81+82+83+84+85+86+87+88+89+90+91+92+93+94+95+96+97+98+99+100+101+102+103+104+105+106+107+108+109+110+111+112+113+114+115+116+117+118+119+120+121+122+123+124+125+126+127+128+129+130+131+132+133+134+135+136+137+138+139+140+141+142+143+144+145+146+147+148+149+150+151+152+153+154+155+156+157+158+159+160+161+162+163+164+165+166+167+168+169+170+171+172+173+174+175+176+177+178+179+180+181+182+183+184+185+186+187+188+189+190+191+192+193+194+195+196+197+198+199+200+201+202+203
Urban Portal
© Copyright 2015 - 2020 First Chance Group Pty Ltd.


Conservatories Minigaff. The Advanced Group are the best Double Glazing & Triple Glazing professionals inside the UK.
Installing a Double Glazed UPVC Conservatory in your home can be the most effective investments you possibly can make in both enhancing the valuation on your own home along with making your home even more energy efficient. That investment can easily both make you money and also help you save money providing amazing value.
Not all UPVC Conservatories are created equal and the majority of people are convinced just to have double gazing ensures they are experiencing the benefits. Conservatories Minigaff. Present day high energy-efficiency Double Glazed sun rooms or conservatories are leaps ahead of outdated double glazed conservatories. They perform significantly better in all ways really making the difference in all types of houses.
Here at Advanced Double & Triple Glazing we make all of our Double & Triple Glazed sun rooms or conservatories in our factory ensuring all Double and Triple Glazed UPVC Conservatory orders are professionally created to order and customised to fit your house. The Advanced Group Windows, Doors & Conservatories have lots of different styles, features, colours and glazing options so you can choose the most suitable glazing choice for your house.
The fact we construct each of our Triple Glazed conservatories or sun rooms ensures that we can always be seriously competitive on price without compromise to the quality of the Double Glazed conservatories we make. Conservatories Minigaff. Triple Glazed conservatory choices incorporate each of the regular configurations which includes Casement Windows, Tilt & Turn, Sash Windows and Conservatories etc.
The Advanced Group Windows, Doors & Conservatories are here now to assist you in finding the appropriate glazing solution for your home. Call now to talk to our specialists in order to benefit from a FREE home survey by one of our expert Double & Triple Team. Conservatories Minigaff.
If you want the optimum quality Double Glazed conservatories or sun rooms at the most competitive prices then call The Advanced Group Windows & Doors Today on 08000 502 502 for a Totally free no obligation quotation.


ForenteQ Limited is a UK and Irish distributor of innovative forensic science equipment. We are passionate about helping you solve crime. We are committed to the delivery of high quality, state of the art equipment that provides a novel approach to evidence recovery and imaging that delivers results. Our suppliers are mainly from across the EU and North America.
We are committed to service and after sales support to minimise critical equipment downtime. We are able to offer on-site training, product servicing, calibration, warranty and post warranty care.
Founded by Paul Butler, M.Sc, who has over 20 years of experience in test and measurement commercial sales including 8 years with Foster and Freeman as International Regional Sales Manager.
Our offices are located in Warwick, central England which has excellent communication networks and is in easy reach of the UK's major cities. We are situated in offices in an attractive business park close to Warwick Castle which has excellent facilities including meeting/conference rooms.
ForenteQ Limited is committed to the highest level of service and after sales care for its' products. The company achieved ISO9001:2015 accredition in 2018. A copy of the corporate quality policy and ISO certificate can be downloaded below.


text:
CCTV Script 25/02/14
Published Wed, Feb 26 20144:50 PM EST
— This is the script of CNBC's news report for China's CCTV on February 25, Tuesday.
Welcome to the CNBC Business Daily.
Whatsapp is set to take on Skype and Viber.
Facebook's Mark Zuckerberg has announced that his latest acquisition will offer free voice calls in the second quarter of this year.
Speaking at the Mobile World Congress in Barcelona, Zuckerberg defended the 19 billion dollar deal, and said that the addition of voice calls could increase the company's user base from to 450 million to one billion.
CNBC's Jon Fortt has all the details:
Mark Zuckerberg was the big headliner on this first day of the Mobile World Congress in Barcelona.
He talked about the Whatsapp acquisition and he talked about his desire to connect more people, particularly in emerging markets, who either can't afford wireless connections, or aren't sure why they should have one.
But on the Whatsapp acquisition in particular, he was pressed on whether it was really worth $16-19 billion dollars.
Take a listen to what he had to say:
"I could be wrong. I mean, there is some chance that this is the one service that gets to a billion people and ends up being not that valuable. I don't think I am. I thin you can look at other messaging apps that are out there - whether its KaKao, or Line or Wechat, that are already monetizing at a level of $2-3 per person with pretty early efforts and I think that shows that if we can do a pretty good job of helping Whatsapp to grow, then this is just going to be a huge business."
Lots of other news out of the conference so far, notably, Nokia coming up with a lower end phone that runs Android - the X Phone.
It'll be interesting to see if Microsoft retains that once it acquires the company in just a few days or weeks, not sure how new CEO Satya Nadella will feel about that.
There were announcements from the likes of HP and Lenovo, convertible tablets.
Huawei's come up with a smart watch, and there's more to come.
Lots of attention on emerging markets, that's seen as the new growth area.
The question is, whether payments or some new technology will be a key way to monetize those new subscribers.
For CNBC, I'm Jon Fortt.
Li Sixuan, from CNBC's Singapore headquarters.
Follow us on Twitter: @CNBCWorld