Borland C++ Builder


Editing string lists in the code-editing window

Suppose you need to modify a string list that contains database parameters, SQL query statements, list box items, or similar information. You'll typically double-click the appropriate property in the Object Inspector to display the String List Editor. Unfortunately, this is a modal window, and you have to explicitly save your changes before you can return to the code-editing window to make further changes to your source code.

However, if you look closely at the String List Editor window, you'll notice a Code Editor... button at the bottom. When you click this button, C++Builder will open a new page in the code-editing window and load the string list text into it.

Unlike in the String List Editor, you don't have to explicitly save the text you enter for a string list via the code-editing window. As soon as you move to a different page in the code-editing window or start building your project, C++Builder will save the text you've entered into the appropriate property of the component that contains the text.

You'll probably find modifying string lists using the code-editing window to be much faster than using the String List Editor. In addition, if you're displaying a string list in the code-editing window, you can choose New Edit Window from the code-editing window's pop-up menu to create the best of both worlds--a separate window for editing string lists that's non-modal.


Attaching captions to nonvisual objects

Nonvisual components don’t have caption properties of their own and all the components of one kind look alike. Identifying them at design time becomes increasingly difficult with each nonvisual component you add.

You can identify a nonvisual component at design time by selecting the ‘Show component captions’ option in the Environment Options dialog. You can now see the name property of the component displayed beneath its icon.


Trap your own hot keys

Windows has many default hot keys that your interface takes advantage of. However, you sometimes need to add your own hot keys to your form. How do you trap the hot keys when the user enters them?

To solve this problem, first set your form's KeyPreview property to True. Next, add this line of code to your forms OnKeyDown event handler:


if (ssCtrl in Shift) and (chr (Key) in ["A","a"] ) 
  MessageBox(0, "Ctrl-A captured", "INFO", MB_OK);

The  OnKeyDown event will trap the keystrokes and perform the specified code in response.


Determining the Windows OS

Microsoft may eventually create a single desktop operating system. Until that happens, your applications probably need to be flexible enough to run on all Windows versions. Of course, you can use conditional compilation and create an executable for each target platform.

However, your application may need to dynamically determine the Windows OS. There's a simple technique for doing just that. You can use the GetVersionEx Windows API call. GetVersionEx accepts a single variable parameter of type TOSVersionInfo. Then, you can interrogate the return values. Here's an example:


//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
TOSVersionInfo VersionInfo;

  VersionInfo.dwOSVersionInfoSize = sizeof(TOSVersionInfo);
  GetVersionEx(&VersionInfo);
  switch (VersionInfo.dwPlatformId) {
    case  VER_PLATFORM_WIN32s: {
      Label1->Caption = "win32s";
      break;
    }
    case  VER_PLATFORM_WIN32_WINDOWS: {
      Label1->Caption = "win32_windows";
      break;
    }
    case  VER_PLATFORM_WIN32_NT: {
      Label1->Caption = "win32_nt";
      break;
    }
  }
}

The GetVersionEx call returns additional information in the TOSVersionInfo structure as shown below.


typedef struct _OSVERSIONINFO{ 

    DWORD dwOSVersionInfoSize; 
    DWORD dwMajorVersion; 
    DWORD dwMinorVersion; 
    DWORD dwBuildNumber; 
    DWORD dwPlatformId; 
    TCHAR szCSDVersion[ 128 ]; 
} OSVERSIONINFO;


Scale your form resolution automatically

You're always creating software that looks great at your monitor's resolution. Unfortunately, if you designed your application on a high-resolution screen, it may be larger than the available screen space on the client screen. You can solve this problem by letting C++ Builder automatically add scroll bars at run-time.

However, using C++ Builder's automatic scaling produces more professional results. At run-time, C++ Builder asks the system for the screen resolution and stores it in the PixelsPerInch property of your application's Screen object. Next, it uses the PixelsPerInch value to resize the form for the current resolution.

Here are some things to remember, to make this technique work effectively: set the Scaled property of your form(s) to TRUE, use only TrueType fonts, use Windows small fonts when you develop, and set the AutoScroll property of your form(s) to FALSE.


Enhance your data access

Would you like to decrease your code maintenance while increasing your application performance? This technique will help you do both of those things.

Use Data Modules to consolidate all the tables your application needs. You add a Data Module to your project and then place data access components on it. For instance, if multiple forms in your application access the same table, place a single TTable component and TDataSource component in the data module. Set their DatabaseName, TableName, and DataSet properties appropriately. Include the name of the data module form in each of the other forms uses clause. Later, when you add data controls to your forms, you'll set their DataSource property to a TDataSource component in the data module.

What are the advantages of this technique? It saves you coding time in two ways. First, you don't have the bother of adding the necessary data access to controls to each form. Second, if the same data field is accessed on different forms and the user changes the data field value in the first form, you don't have to write the code to change the value on the second form. C++Builder does it for you! Otherwise it would be your responsibility to keep the data controls synchronized.

Finally, it results in a slight performance increase. This is due to the fact that C++Builder isn't verifying the DatabaseName and TableName properties multiple times for a single table.


How's your memory?

Here's a technique for determining the amount of available memory on your system. More importantly, your application can use this technique to detect the available memory of their client machine. Armed with that information, your application can dynamically change its processes to optimize performance. For example, to perform bitmap manipulation with double buffering on machines with ample memory, you can use the GlobalMemoryStatus Windows API call. GlobalMemoryStatus accepts a single variable parameter of type TMemoryStatus. Then, you can interrogate the return values. Here's an example:


//---------------------------------------------------------------------------

void __fastcall TForm1::Button1Click(TObject *Sender)
{
TMemoryStatus MemoryStatus;

  MemoryStatus.dwLength = sizeof(MemoryStatus);
  GlobalMemoryStatus(&MemoryStatus);
  Label1->Caption = "Total Physical Memory: " +
IntToStr(MemoryStatus.dwTotalPhys);
}

The GlobalMemoryStatus call returns additional information in the MemoryStatus structure as shown below.


typedef struct _MEMORYSTATUS { // mst  
    DWORD dwLength;        // sizeof(MEMORYSTATUS) 
    DWORD dwMemoryLoad;    // percent of memory in use 
    DWORD dwTotalPhys;     // bytes of physical memory 
    DWORD dwAvailPhys;     // free physical memory bytes 
    DWORD dwTotalPageFile; // bytes of paging file 
    DWORD dwAvailPageFile; // free bytes of paging file 
    DWORD dwTotalVirtual;  // user bytes of address space 
    DWORD dwAvailVirtual;  // free user bytes 
} MEMORYSTATUS, *LPMEMORYSTATUS;


Cancel that drag operation!

Have you ever started moving a component while designing your form and realized you selected the wrong component? No doubt, you can think of other instances when you would like to cancel a design-time drag operation you've already begun. Here's a tip that let's you do just that.

After you've begun the drag but before you release the mouse button, press the Esc key. The control will snap back to its original position!


Get the message

C++Builder provides an easy way to display informational dialogs to your user.  The MessageDlg function displays a message dialog box in the center of the screen. Its declaration resembles this:


extern PACKAGE int __fastcall MessageDlg(const System::
AnsiString Msg, TMsgDlgType DlgType, TMsgDlgButtons Buttons, int HelpCtx);

At first glance you're lead to believe you can't display variable information in the dialog. However, that's not true. You can concatenate your variable name to the string. Here's an example that uses this technique:


void __fastcall TForm1::Button1Click(TObject *Sender)
{
  String ErrorDescr = "Call 911";
  MessageDlg("Error Code: 123 "+ErrorDescr, mtConfirmation,TMsgDlgButtons()
<< mbOK, 0);
}


Primary Colors

When you choose a value for the Color property, C++Builder allows you to create your own color. This could be important when you're trying to match the color in a client's logo. There are only a few steps to creating your own custom colors.

First, double-click on the Color property of the component, instead of clicking the list arrow. After you double-click, the Color dialog appears. Click the basic color closest to the final color you want, then click Define Custom Colors>> button. The Color dialog expands to display a spectrum of colors. The color spectrum has cross hairs that you move until the color you want is displayed. When you're satisfied with your choice, click the Add to Custom Colors buttons. Now your unique color is stored in the Color dialog box.

For your convenience, custom colors remain in the color dialog for the current project. Even as you start new projects or visit older ones, your color one-of-a-kind color remains part of the Color dialog.


Let's play catch

The VCL exception classes all have a Message property that contains a textual description of the exception that occurred. You can use this property to display a message to the user. This example illustrates the technique.


void __fastcall TForm1::Button1Click(TObject *Sender)
{
  try {
   Form1->Image1->Picture->LoadFromFile("filename.ext");
  }
  catch (EInvalidGraphic& info)
  {
    Application->MessageBox(info.Message.c_str(),
    "My Program - Error",MB_ICONHAND|MB_OK);
  }
}

Sometimes the VCL messages may not be descriptive enough for your liking. In those cases you can create your own error message, but often the Message property is sufficient.