home *** CD-ROM | disk | FTP | other *** search
/ Prima Shareware 3 / DuCom_Prima-Shareware-3_cd1.bin / PROGRAMO / delphi / VCLFAQ / VCL1 / SEC5.FAQ < prev   
Encoding:
Text File  |  1995-03-27  |  19.8 KB  |  512 lines

  1. SECTION 5 - Delphi VCL
  2.  
  3. This document contains information that is most often provided
  4. to users of this section.  There is a listing of common
  5. Technical Information Documents that can be downloaded from 
  6. the libraries, and a listing of the most frequently asked
  7. questions and their answers.
  8.  
  9. Technical Information Documents related to VCL components:
  10.  
  11. None
  12.  
  13. Zip files related to VCL components:
  14.  
  15. TBD
  16.  
  17. Questions and answers:
  18.  
  19. Q.   "How can VCL components be created on the fly at run-time?"
  20.  
  21. A.   * The following code will create a modal password form at runtime.
  22.      The TPasswordForm type is a TForm descendent class defined either
  23.      in the current unit or in a separate unit referenced by the current
  24.      unit's uses clause.
  25.  
  26.      with TPasswordForm.Create(Application) do
  27.      begin                               ( i.e TForm1, TPasswordForm etc. } 
  28.         ShowModal;                       { Display form as a modal window }
  29.         Free;                            { Free the form when it is closed }
  30.      end;      
  31.  
  32.      * The following are the general steps to add a component to a form at 
  33.      run-time:  
  34.  
  35.      1. Declare an instance variable of the component type that you wish to
  36.         create {i.e. TButton }. Note: instance variables are used to point
  37.         to an actual instance of an object. They are not objects themselves.
  38.      2. Use the component's Create constructor to create an instance
  39.         of the component and assign the instance to the instance 
  40.         variable declared in step 1.  All components' Create constructors 
  41.         take a parameter - the component's owner.  Except in special 
  42.         circumstances, you should always pass the form as the owner 
  43.         parameter of the component's Create constructor.
  44.      3. Assign a parent to the component's Parent property (i.e. Form1,
  45.         Panel1, etc).  The Parent determines where the component will be 
  46.         displayed, and how the component's Top and Left coordinates are 
  47.         interpreted. To place a component in a groupbox, set the 
  48.         component's Parent property to the groupbox.  For a component
  49.         to be visible, it must have a parent to display itself within.
  50.      4. Set any other properties that are necessary  (i.e. Width, Height).
  51.      5. Finally, make the component appear on the form by setting the 
  52.         component's Visible property to True. 
  53.      6. If you created the component with an owner, you
  54.         don't need to do anything to free the component - it will be freed
  55.         when the owner is destroyed.  If you did not give the component an
  56.         owner when you created it, you are responsible for making sure
  57.         the component is freed when it is no longer needed.
  58.  
  59.      The following demonstrates how to add a TButton component to the 
  60.      current form at run-time:  
  61.  
  62.      var
  63.        TempButton : TButton;  { This is only a pointer to a TButton }    
  64.      begin 
  65.        TempButton := TButton.Create(Self); { Self refers to the form }
  66.        TempButton.Parent := Self;          { Must assign the Parent } 
  67.        TempButton.Caption := 'Run-time';   { Assign properties now }
  68.        TempButton.Visible := True;         { Show to button }
  69.      end; 
  70.  
  71.      Since the button was created with an owner, it will be freed 
  72.      automatically when its owner, the form, is freed.     
  73.  
  74.  
  75. Q.   "How can the event handler of a popup menu item determine which 
  76.       component was right-clicked upon to activate that menu?
  77.  
  78. A.    Use the PopupMenu.PopupComponent property 
  79.       to determine what control the menu was activated for.
  80.  
  81.       procedure TForm1.PopupItem1Click(Sender: TObject);
  82.       begin
  83.         Label1.Caption := PopupMenu1.PopupComponent.ClassName;
  84.       end;
  85.  
  86.       The form's ActiveControl property can also be used, however, 
  87.       the active control may not necessarily be the control that
  88.       caused the popup menu to appear. 
  89.  
  90.  
  91. Q.    "What are the capacity limits of the standard Delphi controls?"
  92.  
  93. A.    Any component that uses a TList to store information has an upper
  94.       bound of 16368 items. For example, a TTabControl can contain up to
  95.       16368 tabs and the Delphi Component Palette can contain up to
  96.       16368 palette pages.
  97.  
  98.       Many of the Delphi standard components are wrappers around standard
  99.       Windows controls.  Windows 3.1 imposes its own limits on these 
  100.       components.  For example: a TComboBox or TListbox can hold up to
  101.       5440 items and TMemo or TEdit (and related components) can hold up 
  102.       to 32k of text.
  103.  
  104.       Windows 3.1 resource space imposes a limit of 570 pages in a 
  105.       TNoteBook component. (It's difficult to get more than 500 window 
  106.       handles in any Windows application.)
  107.  
  108.       Note 1: Exceeding these limits will raise exceptions or cause Windows
  109.       to behave strangely.
  110.  
  111.       Note 2: Many of the Windows-based capacity limits are much higher 
  112.       in the 16-bit WOW box of Windows NT and in Windows 95.  In future
  113.       32 bit releases of Delphi, virtually all of these limits will 
  114.       disappear.
  115.  
  116.  
  117. Q.    How can I determine the Length in pixels of a string after a
  118.       specific font has been aplied to it.
  119.  
  120. A.    Use the Canvas methods TextHeight and TextWidth to
  121.       determine the text height and width of a string in
  122.       pixels.  Be sure to assign the font into the Canvas before
  123.       drawing or taking measurements.
  124.  
  125.       All visual components have a Canvas property, but
  126.       usually this property is protected so that only direct descendents
  127.       can draw on the Canvas.  Since you write much of your code
  128.       inside methods of a TForm descendent, you always have access to 
  129.       your form's inherited Canvas property.  The TPaintBox component
  130.       makes its Canvas property public so that you can draw on the
  131.       component from OnPaint event methods in the form.
  132.  
  133.       If a component doesn't have a Canvas property you can use the
  134.       following function to get the text width based on the font passed.
  135.  
  136.       function GetTextWidth(CanvasOwner: TForm; Text : String;
  137.                           TextFont :  TFont): Integer;
  138.       var
  139.         OldFont : TFont;
  140.       begin
  141.         OldFont := TFont.Create;
  142.         try
  143.           OldFont.Assign( CanvasOWner.Font );
  144.           CanvasOWner.Font.Assign( TextFont );
  145.           Result := CanvasOwner.Canvas.TextWidth(Text);
  146.           CanvasOWner.Font.Assign( OldFont );  
  147.         finally
  148.           OldFont.Free;
  149.         end;
  150.       end;
  151.  
  152.  
  153. Q.   Why do some visual components like TPanel and TEdit not have a
  154.      Canvas property?
  155.  
  156. A.   All descendents of TCustomControl have a Canvas property, however,
  157.      most are protected to prevent 'outsiders' from drawing on the
  158.      component.  Descendents of a component can always access the 
  159.      protected properties they inherit from the component 
  160.      (such as Canvas), but users of the component cannot.
  161.  
  162.      type
  163.         TCanvasPanel = class(TPanel)
  164.         public
  165.           property Canvas;
  166.         end;
  167.  
  168.      If you want to draw on a component that doesn't have a public 
  169.      canvas property, consider using a different component that was 
  170.      intended for arbitrary drawing (TPaintBox), or layer components to 
  171.      achieve the desired result (client-align a TPaintBox inside a TPanel
  172.      to get a bevelled, drawable area).
  173.  
  174.  
  175. Q.   "How can I get a horizontal scrollbar on a list box?"
  176.  
  177. A.   Send a LB_SetHorizontalExtent message to the listbox's window handle.
  178.      For example, the message could be sent in the form's OnCreate:
  179.  
  180.      procedure TForm1.FormCreate(Sender: TObject);
  181.      begin
  182.       SendMessage(Listbox1.Handle, LB_SetHorizontalExtent, 
  183.                   1000, Longint(0));
  184.      end;
  185.  
  186. Q.   "Does Delphi have a component that supports serial communications?"
  187.  
  188. A.   No. However, there are serial communications libraries (and soon 
  189.      Delphi components) for Delphi available from third party vendors
  190.      such as TurboPower, SaxComm, and and others.
  191.  
  192.  
  193. Q.   "How can the tab stops be set in a TMemo control?"
  194.  
  195. A.   To change the tab stops for a multiline edit control
  196.      (i.e. a TMemo) send the EM_SetTabStops message to the
  197.      component.  The Tabs array indicates where the tab stops 
  198.      will be located.  Since the WParam parameter to 
  199.      SendMessage is 1, then all tab stops will be set to the 
  200.      value passed in the Tabs array.  Remember to set the
  201.      WantTabs property of TMemo to True to enable the tabs.
  202.  
  203.      procedure TForm1.FormCreate( Sender : TObject );
  204.      const
  205.         TabInc : LongInt = 10;
  206.      begin
  207.        SendMessage( Memo1.Handle, EM_SetTabStops, 1,
  208.           Longint( @TabInc ) );
  209.      end;
  210.  
  211.  
  212. Q.   "Where is the best place to open a splash screen on program
  213.      start up?"
  214.  
  215. A.   The best place to open a splash screen is in the project source 
  216.      file after the first Application.FormCreate and before the
  217.      Application.Run.  This is accomplished by creating a form on
  218.      the fly and then displaying it before the application is actual
  219.      opened.
  220.  
  221.      program Project1;
  222.  
  223.      uses Forms,  
  224.           Unit1 in 'UNIT1.PAS' {Form1}, 
  225.           Splash;
  226.  
  227.      {$R *.RES}
  228.      var
  229.        SplashScreen : TSplashScreen;  {in the Splash unit}
  230.      begin
  231.      Application.CreateForm(TForm1, Form1);
  232.      SplashScreen := TSplashScreen.Create(Application);
  233.      try
  234.        SplashScreen.Show;
  235.        SplashScreen.Update;
  236.        {
  237.         do other CreatForms or anyother processing 
  238.         before the app is to be opened
  239.        }
  240.      finally               {Make sure the splash screen gets released}
  241.        SplashScreen.Free; 
  242.      end;   
  243.      Application.Run;
  244.      end.
  245.  
  246.  
  247. Q.   "Why does the OnExit event of a TEdit component not execute when 
  248.      the user clicks on a speed button?  Is there a way to make a 
  249.      an OnExit event execute when a speed button is pressed?"
  250.  
  251. A.   A speed button never actually gets focus, so the active
  252.      control never loses its focus, consequently the active
  253.      control's OnExit event never occurs. 
  254.  
  255.      One way to execute the active control's OnExit event is to
  256.      explicitly call it in the OnClick event of the speedbutton. 
  257.      For example:
  258.  
  259.      procedure TForm1.SpeedButton1Click(Sender: TObject);
  260.      begin
  261.        If ActiveControl is TEdit then 
  262.           (ActiveControl as TEdit).OnExit(ActiveControl);
  263.      end;
  264.  
  265.   
  266. Q.   "When I open the child windows at run-time each one is 
  267.      positioned slightly down and to the right of the previous
  268.      window.  My problem is that if I then close some of the child 
  269.      windows and then open a new one, the new one is placed 
  270.      down and to the right of where the last child window was 
  271.      before I closed it, even though it is no longer there! 
  272.      Is this as designed?"  
  273.  
  274. A.   That's how MDI windows works. VCL doesn't override Windows
  275.      default behavior in this situation.
  276.  
  277.      Untested suggestion: In the FormCreate procedure try 
  278.      setting the Top, Left, Width & Height properties to the values
  279.      that you require.  The MDI child form's FormCreate is called 
  280.      before the window is displayed.
  281.  
  282.  
  283. Q.   "Why can't my program find any of the resources that I put in a .RES 
  284.      file if that .RES file is the same name as my form's unit name?"
  285.  
  286. A.   If the name of an included .RES file is the same as the name
  287.      of a .DPR file Delphi wll overwrite it with it's own .RES file.  
  288.      In addition, the project RES file is for the Delphi project
  289.      manager only; don't edit or add resources to this RES file.  
  290.  
  291.  
  292. Q.   "How can you do scrolling functions in a TForm component using 
  293.       keyboard commands?  For example, scrolling the form up and down 
  294.       with the PgUp and PgDn keys.  
  295.  
  296. A.    Form scrolling is accomplished by modifying the VertScrollbar 
  297.       or HorzScrollbar Postion properties of the form.  The following
  298.       code demonstrates how to do this:
  299.  
  300.       procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word;
  301.       Shift: TShiftState);
  302.       const
  303.         PageDelta = 10;
  304.       begin
  305.         With VertScrollbar do
  306.           if Key = VK_NEXT then  Position := Position+PageDelta
  307.           else if Key = VK_PRIOR then Position := Position-PageDelta;
  308.       end;
  309.  
  310.       Note: This may not work well if the active control uses PgUp & PgDn,
  311.       too, like a TMemo.
  312.  
  313.  
  314. Q.    "Is there a way to fill a TListbox or TMemo in one shot?"
  315.  
  316. A.    To fill multiple lines of a TListbox or TMemo component the SetText
  317.       method can be used.  The null terminated string passed to the 
  318.       SetText method is a concatination of each line of text delimeted
  319.       by a carriage return character #13 in between.  For example, 
  320.      the follow statement:
  321.  
  322.       Listbox1.Items.SetText('aaaaa'#13'bbbbb'#13'ccccc')
  323.  
  324.       will display the following in a listbox window:
  325.  
  326.       aaaaa
  327.       bbbbb
  328.       ccccc
  329.  
  330.       Note: The preferred method of filling a listbox or memo is with the
  331.       Add method of their Items and Lines properties, respectfully.
  332.  
  333.  
  334. Q.    "Is it possible to create something like the Control Array in Visual
  335.       Basic?   For example, I want a group of buttons with a common event
  336.       handler whereby the event handler picks up an integer value for the
  337.       particular button. In Visual Basic this would be done via the
  338.       Control Array index."
  339.  
  340. A.    One way do to this is to set the Tag field for each button to a
  341.       different number and then create a common OnClick event handler
  342.       that looks at the Sender's Tag field.  Assign the same OnClick
  343.       event handler to all the buttons in the group.  And then the
  344.       OnClick event handler would look something like this:
  345.  
  346.       procedure TForm1.Button1Click(Sender: TObject); var cap: string;
  347.       begin
  348.         case TButton(sender).Tag of
  349.           1: ShowMessage('1st Button Pressed');
  350.           2: ShowMessage('2nd Button Pressed');
  351.           3: ShowMessage('3rd Button Pressed');
  352.         end;
  353.       end;
  354.  
  355.  
  356. Q.    "How can a new component be added to a page of a
  357.       TTabbedNoteBook at run time?  How do I determine 
  358.       what the parent will be for the new component?"
  359.  
  360.  
  361. A.    To add a component to a TabbedNotebook page at run-time a
  362.       pointer to the desired page must be assigned to the new
  363.       component's Parent property before it can be shown.  The way to 
  364.       access all the pages of a TTabbedNotebook at run-time is with 
  365.       the Objects array property of the TabbedNotebook's Pages property.
  366.       In other words, the page components are stored as objects attached
  367.       to the page names in the Pages string list property.  The follow
  368.       demonstrates the creation of a button on the second page of
  369.       TabbedNotebook1:
  370.  
  371.       var 
  372.         NewButton : TButton;
  373.       begin
  374.         NewButton := TButton.Create(Self);
  375.         NewButton.Parent := TWinControl(TabbedNotebook1.Pages.Objects[1])
  376.       ...               
  377.      
  378.      Note: this can also be done with the TNotebook component as well.
  379.  
  380.  
  381. Q.   "Are there any vertical ( side of the page ) tab components
  382.      available, commercial, shareware or freeware."
  383.  
  384. A.   TurboPower's Orpheus product will support this. GO TURBOPOWER
  385.      for more information.
  386.  
  387.  
  388. Q.   "Is there an easy way to get CopyToClipboard, CutToClipboard etc. 
  389.      to know to use the TEdit that has focus?  
  390.  
  391. A.   Simply check to see if the ActiveControl is of type TEdit and then 
  392.      do the desired cut, copy or paste operation. For example:
  393.  
  394.      if (ActiveControl is TEdit) then
  395.         TEdit(ActiveControl).CopyToClipboard;     
  396.  
  397.  
  398. Q.   "Does a TDBGrid component have an OnMouseDown, OnMouseUp and 
  399.      OnMouseMove events?"
  400.  
  401. A.   The events are there, but they aren't published.  You could 
  402.      create a simple decendant of TDBGrid and publish them.
  403.  
  404.  
  405. Q.   "Does Delphi grab system resources when displaying and closing
  406.      modal dialogs?  For example, the following code decreases the
  407.      system resources every time it is used to show a modal dialog."
  408.  
  409.      ModalForm1 := TModalForm1.Create(Self);
  410.      ModalForm1.ShowModal;
  411.  
  412. A.   Without an OnClose event handler that sets Action parameter to
  413.      caFree, your code is creating a new form with each call to
  414.      TModalForm1.Create(Self), but the previously created form is
  415.      never destroyed.  All previous instances of the "ModalForm1"
  416.      forms are floating around in Windows.
  417.  
  418.     The Free method of a form can also be used to free its resources.
  419.     This is demonstrated below:
  420.  
  421.      try
  422.        ModalForm1.ShowModal;
  423.       { other stuff here }
  424.      finally
  425.        ModalForm1.Free;
  426.      end;
  427.  
  428.  
  429. Q.   What is the best way to create a radio button group and
  430.      place radio buttons on it?  It seems that you can create a
  431.      Radio Group then drop Radio Buttons on it or you can 
  432.      create the group and enter values into the Items properties
  433.      for the titles (captions) of the radio buttons and have
  434.      Delphi place them in the group.      
  435.  
  436. A.   If you're going to use a radio group, you need to create your
  437.      radio buttons using the Items string list.  Radio buttons
  438.      don't have to be in a group, which is why the plain radio 
  439.      button component is available.
  440.  
  441.  
  442. Q.   "Is there a way to make sure the window that is holding a form 
  443.      or an image component is byte-aligned?" 
  444.  
  445. A.   Override the CreateParams method:
  446.  
  447.      procedure TMyForm.CreateParams(var Params:TCreateParams);
  448.      begin
  449.        inherited CreateParams(Params);
  450.        Style := Style or CS_BYTEALIGNWINDOW;
  451.      end; 
  452.  
  453.      Note: Byte alignment is less of a big deal than the Windows docs
  454.      imply.  It is only significant on monochrome, EGA, and 16 color
  455.      VGA video modes. All higher video modes are always byte-aligned.
  456.  
  457.  
  458. Q.   What is the order of event handlers when a form is created 
  459.      and shown?
  460.  
  461. A.   When a form is created the event handlers are executed in the
  462.      following order:  OnCreate, OnShow, OnPaint, OnActivate, OnResize
  463.      and OnPaint again. 
  464.  
  465.  
  466. Q.   "Why does the error 'Cannot change Visible in OnShow or OnHide'
  467.      occur when the FormStyle property of a form is changed in the
  468.      OnActivate event? 
  469.  
  470. A.   The FormStyle property defines how the window gets created and 
  471.      is usually set in the OnCreate event, however, it can changed 
  472.      after the window handle has been created, just not during the
  473.      OnActivate, OnShow or OnHide events.  The issue here is with the
  474.      mode that the system is in during OnShow and OnHide events.
  475.  
  476.  
  477. Q.   "How can I make components look sunken and raised?
  478.  
  479. A.   To make a component look raised or lowered place it on  
  480.      a TBevel or TPanel component which both have properties to
  481.      raise or lower their frames.
  482.  
  483.  
  484. Q.   Where is the source code for the tabbed controls (i.e.
  485.      TTabbedNotebook)?
  486.  
  487. A.   The source code files shipped with Delphi does not contain the
  488.      source for the tabbed controls because of legal reasons. However,
  489.      the interface source for the tabbed controls is provided
  490.      in the DELPHI\DOC directory with an INT extension.
  491.     
  492.      Note:  Registered owners of the Delphi RTL source code can request
  493.      the TTabSet and TTabbedNotebook source code from Borland Corporate
  494.      Affairs.  Instructions are in the RTL source readme.
  495.  
  496.  
  497. Q.    "What is the memo field size in Delphi?"
  498.  
  499. A.    Microsoft's edit control that is built-in to Windows and used 
  500.       by Delphi's TEdit and TMemo wrapper classes has a maximum 
  501.       capacity of 32k.  The Delphi wrapper classes do some special
  502.       things  to allow every edit and memo control on a form to
  503.       contain up to 32k each.  Normally all edit controls in an
  504.       application would be limited to 32k collectively.
  505.  
  506.  
  507. Q.    "How can I make a field in the TGrid component not show up?"
  508.  
  509. A.    This can be accomplished by either removing the field entirely 
  510.       from the Fields Editor's field list or by setting the Visible
  511.       property of the field to False. 
  512.