⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 189.htm

📁 水木清华的BBS文章
💻 HTM
📖 第 1 页 / 共 5 页
字号:
------------------------------------------------------------------------ <br>

Section 8. Tools for Delphi <br>

8.1. Is there YACC and LEX for Delphi? <br>

  <br>

There is a YACC and LEX written by  Albert Graef (ag@muwiinfa.geschichte.uni-mai <br>

nz.de) for Turbo Pascal that works with Delphi.  This can be found on many share <br>

ware sites (search for Pascal and YACC). <br>

  <br>

One location is /msdos/turbopas/tply30a1.zip and /msdos/turbopas/tply30a2.zip in <br>

 the Simtel archives. <br>

  <br>

  <br>

  <br>

8.2. How can I write code to display JPEG files? <br>

  <br>

nomssi@physik.tu-chemnitz.de has a Pascal library based of the Independent JPEG <br>

Group's free JPEG library.  It is available from the following locations: <br>

  <br>

ftp://druckfix.physik.tu-chemnitz.de/pub/nv/ <br>

http://www.tu-chemnitz.de/~nomssi/pub/pasjpeg.zip <br>

  <br>

------------------------------------------------------------------------ <br>

Section 9. Basic Programming Techniques <br>

9.1. How do I create a dynamic array of objects? <br>

  <br>

The easiest way to create an array of objects is to use a TList control.  I ofte <br>

n find it helpful to create specialized classes that derive from TList. The foll <br>

owing class shows how to create a list for a specific type of object that has a <br>

little better error reporting than the basic TList.  For you own list you may ne <br>

ed to implement more methods. <br>

  <br>

TListOfMyObject = class (TList) <br>

  Private <br>

    Function GetItems (Index : Ordinal) : TmyObject ; <br>

  public <br>

  public <br>

    Property Items [Index : Ordinal] : TmyObject Read GetItems ; <br>

    Procedure Add (AObject : TmyObject) ; <br>

  End ; <br>

  <br>

Function TListOfMyObject.GetItems (Index : Ordinal) : TmyObject ; <br>

  Begin <br>

  If Index >= Count Then <br>

    raise Exception.CreateFmt ('Index (%d) outside range 1..%d', [Index, Count - <br>

1 ]) ; <br>

  Result := Inherited Items [Index] ; <br>

  End ; <br>

  <br>

Procedure TListOfMyObject.Add (AObject : TmyObject) ; <br>

  Begin <br>

  Inherited Add (AObject) ; <br>

  End ; <br>

  <br>

9.2. Where is the Wincrt unit in Delphi 2.0? <br>

  <br>

There is no WinCrt unit in Delphi 2.0. It has been replaced by a project options <br>

 setting.  On the linker page there is an option to create a console application <br>

. Check this rather than use the WinCrt unit. <br>



  <br>

9.3. What should the base class be for my component? <br>

  <br>

If you are deriving from an existing component then the class of the component y <br>

ou wish to derive from should be the base class.  Several of the registered VCL <br>

component classes are immediate ancestors of corresponding custom classes (e.g. <br>

TMemo descends from TCustomMemo).  These custom classes implement most of the fu <br>

nctionality of the control but they do not publish many of the properties that t <br>

hey define.   In most cases you are probably better off deriving your component <br>

from the custom class rather than the well known registered class. <br>

  <br>

If you are creating a component from scratch then TCustomControl is most likely <br>

your best choice.  This is used for visual, windowed controls. <br>

  <br>

Other less likely alternatives are: <br>

  <br>

TGraphicControl - For visual controls that have no associated window.  These can <br>

not receive input focus. <br>

  <br>

TComponent - Non-visual component. <br>

  <br>

TWinControl - To create a control that derives from an existing control that was <br>

hat derives from an existing control that was <br>

 not created specifically for Delphi. <br>

  <br>

9.4. What is the difference between the Free and Destroy methods ? <br>

  <br>

From Xavier Van Dessel <br>

  <br>

Free is a static method on TObject and Destroy is a virtual/dynamic method. <br>

This means that any call to Free will compile to a straight call into <br>

TObject.Free. The implementation of TObject.Free is very simple: <br>

  <br>

Procedure TObject.Free; <br>

Begin <br>

  If Self<>Nil Then <br>

    TObject.Destroy; <br>

End; <br>

  <br>

As you can see, the only thing Free does, is check whether the object that is <br>

being freed, really exists. If it exists (the pointer Self points to <br>

something), then the Destroy method is called. The reason for this complex way <br>

of releasing storage is that Destroy is a virtual/dynamic method, and thus <br>

should only be called when it is possible to determine the class the object <br>

belongs <br>

class the object <br>

belongs to. But this can only be done if an object really exists, otherwise you <br>

belongs to. But this can only be done if an object really exists, otherwise you <br>

  <br>

would get GPF's and exceptions. <br>

An example will clarify this: <br>

  <br>

Class AnObject(Object) <br>

  FObject1, <br>

  FObject2 : TObject; <br>

  Constructor Create; Override; <br>

  Destructor Destroy; Override; <br>

End; <br>

  <br>

Constructor AnObject.Create; <br>

Begin <br>

  FObject1:=TObject.Create; <br>

  Raise Exception('Dummy Exception'); <br>

  FObject2:=TObject.Create; <br>

End; <br>

  <br>

Destructor AnObject.Destroy; <br>

Begin <br>

  FObject1.Free; <br>

  FObject2.Free; <br>



  Inherited Destroy; <br>

End; <br>

  <br>

This Object creates 2 sub-objects, but for some reason there occurs an <br>

exception between the 2 creations. As the exception occurs in the Create of <br>

AnObject, the Destroy Destructor will be executed automatically. FObject1 <br>

exists, and therefore it will be freed (by calling its Destroy Destructor <br>

method). But FObject2 is still Nil. So Free will find out that in fact FObject2 <br>

  <br>

does not exist anywhere, and the Destroy method will NOT be called. Note that <br>

all attributes of AnObject get initialised (before the Create) into binary <br>

zeroes, which causes all sub-objects to be Nil pointers. <br>

  <br>

You should NEVER override Free, but you should always override the Destroy <br>

Destructor method. Don't forget to code the 'Override' keyword in the <br>

declaration in the class, otherwise you code should not get executed. <br>

In the implementation of Destroy, you should ALWAYS call Inherited Destroy, <br>

preferably as last statement (as in the example above). <br>

  <br>

------------------------------------------------------------------------ <br>

  <br>

Section 10. Advanced Programming Techniques <br>

mming Techniques <br>

10.1. Is there a Delphi equivalent to C++'s I/O Stream classes? <br>

  <br>

Yes and no.  Delphi allows you to create your own "Text-File Device Driver" whic <br>

h allows you to use standard Delphi I/O procedures for non-standard I/O streams <br>

such as Unix <LF> files or network connections.  These are not as powerful as C+ <br>

+ I/O Streams but it is possible to get around their limitations. <br>

  <br>

The procedure for creating a Text-File Device Driver is reasonably well document <br>

ed in the "Object Pascal Langue Guide" and there is one example in the VCL sourc <br>

e in PRINTER.PAS. <br>

  <br>

Delphi also has stream classes for writing objects to a stream.  These are not a <br>

s "general purpose" as C++'s I/O streams. <br>

  <br>

10.2. How can I get the text equivalent for an enumerated type? <br>

  <br>

Use the function GetEnumName located in the module TypInfo. <br>

  <br>

Type <br>

        TMyType = (Value1, Value2) ; <br>

... <br>

Var <br>

Var <br>

        TypeValue : TmyType ; <br>

... <br>

WriteLn (GetEnumName (TypeInfo (TMyType), Ord (TypeValue)) ; <br>

  <br>

The module TypInfo has many other functions for obtaining information about type <br>

s. <br>

  <br>

The book "Secrets of Delphi 2.0" has a lot of information on how to us the TypIn <br>

fo module. <br>

  <br>

------------------------------------------------------------------------ <br>

Section 11. Component Virtual Methods <br>

11.1. How can I find out when my component has had its window handle created? <br>

  <br>

A control's window handle is created by the CreateWnd method.  If you have proce <br>

ssing that needs to be performed after the window handle is created then you can <br>

 override CreateWnd and do <br>

  <br>

Procedure TMyClass.CreateWnd ; <br>

  Begin <br>

  Inherited CreateWnd ; { Don't forget or you'll never get a window handle. } <br>

  <br>

  <br>

  { Your processing goes here. } <br>

  End ; <br>

  <br>

11.2. How can I tell when all the components on my form have been loaded? <br>

  <br>

The Loaded method is called for each component on a form after all controls on t <br>

he form have been loaded from the stream. <br>

  <br>

Procedure TMyClass.Loaded ; <br>

  Begin <br>

  Inherited Loaded ; { Clears the csLoading in ComponentState } <br>

  <br>

  { Your processing goes here. } <br>

  End ; <br>

  <br>

11.3. Where is the best place to draw my control? <br>

  <br>

You could intercept the WM_PAINT message and set up your control's canvas howeve <br>

r will VCL do all this work for you if you simply override the Paint method in y <br>

our control. <br>

  <br>

Procedure TMyClass.Paint ; <br>



  Begin <br>

  { You only need to call inherited Paint if your class inherits <br>

    directly from TCustomControl or TGraphicControl.  You may need <br>

    to call this if your control inherits from an existing control. } <br>

  <br>

  Inherited Paint ; <br>

  <br>

  <br>

  <br>

  { Your processing goes here. } <br>

  End ; <br>

  <br>

11.4. How do I change the Window Style for my control. <br>

  <br>

The CreateParams method is used to set up the window style and all the other arg <br>

uments that are passed to CreateWindowEx to create the control's window.To chang <br>

e the window style use something like this which creates a window with or withou <br>

t a vertical scroll bar. <br>

  <br>

procedure TMyControl.CreateParams(var Params: TCreateParams) ; <br>

  Begin <br>

  Inherited CreateParams (Params) ; <br>

  Inherited CreateParams (Params) ; <br>

  IF IWantAScrollBar Then <br>

    Params.Style := Params.Style OR WS_VSCROLL <br>

  Else <br>

    Params.Style := Params.Style AND NOT WS_VSCROLL ; <br>

  End ; <br>

  <br>

------------------------------------------------------------------------ <br>

Section 12. Windows API Functions <br>

  <br>

12.1. I am trying to scroll the contents of my control but I get an ugly flicker <br>

 effect.  How can I eliminate this? <br>

  <br>

The easiest way to scroll the elements of a control is to change all of their co <br>

ordinates then to force a repaint of the control.  Unfortunately this produces t <br>

he flicker effect. <br>

  <br>

The best way to reduct this flickering is to use the ScrollWindow or ScrollWindo <br>

wEx Windows API function. <br>

  <br>

Another source of flickering can be from Windows using two messages to paint: WM <br>

_PAINT and WM_ERASEBKGND.  You may want to intercept all of the WM_ERASEBKGND me <br>

ssages and do all of your painting, including the background, in response to WM_ <br>



PAINT messages in the Paint method. <br>

  <br>

12.2. How can I restart windows? <br>

  <br>

Use the ExitWindowsEx function. <br>

  <br>

12.3. How can I batch updates to when changing the appearance of my control? <br>

  <br>

Sending the WM_SETREDRAW message to your control can either set or clear the fla <br>

g used to determine if a control is redrawn. <br>

------------------------------------------------------------------------ <br>

  <br>

Section 13. Control Borders <br>

13.1. How come my control does not have a 3D border even when I have CTL3D set t <br>

o True? <br>

  <br>

CTL3D has no effect unless csFramed is set in ComponentStyle. Try something like <br>

 this inside your constructor: <br>

  <br>

  ComponentStyle := ComponentStyle + [csFramed] ; <br>

  <br>

13.2 How do I implement a BorderStyle property? <br>

13.2 How do I implement a BorderStyle property? <br>

  <br>

The trick to having a control border is that the border must be created when the <br>

 control's Window handle is created. <br>

  <br>

FBorderStyle : TBorderStyle ; <br>

Procedure SetBorderStyle (Style : TBorderStyle) ; <br>

Property BorderStyle : TBorderStyle Read FBorderStyle write SetBorderStyle ; <br>

procedure CreateParams(var Params: TCreateParams) ; Override ; <br>

  <br>

procedure TMyControl.CreateParams(var Params: TCreateParams) ; <br>

  Begin <br>

  Inherited CreateParams (Params) ; <br>

  If FBorderStyle = bsSingle Then <br>

 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -