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

📄 ch20.htm

📁 delphi自学的好教材!特别适合刚刚起步学习delphi的人员!同样对使用者具有参考价值!
💻 HTM
📖 第 1 页 / 共 5 页
字号:
<DL>	<DT></DT>	<DD><B>1. </B>Choose Component|Install Component from the main menu. The Install	Component dialog box is displayed.	<P>	<DT></DT>	<DD><B>2. </B>Click the Browse button to the right of the Unit file name field. When	the Unit file name dialog box comes up, locate the FlashingLabel.pas file and click	Open.	<P>	<DT></DT>	<DD><B>3. </B>Now look at the Package file name field. It should contain the file	DCLUSR40.DPK. If not, click the drop-down button and select DCLUSR40.DPK from the	list. If you don't see this package listed, click the Browse button and find the	file (it is in the \Delphi 4\Lib directory).	<P>	<DT></DT>	<DD><B>4. </B>Click OK to close the Install Component dialog box. Delphi displays	a message telling you that it is about to build and install the package. Click Yes	to continue.	<P>	<DT></DT>	<DD><B>5. </B>Delphi builds and installs the package. When the process is complete,	Delphi displays a message box telling you that the TFlashingLabel component has been	registered.	<P></DL><P>Your component will now appear on the Samples page of the Component palette. Checkthe Samples page on the Component palette and you will see a button that has theDelphi default component icon. If you pause over the button, the tooltip says FlashingLabel.</P><P>Start a new project and test the FlashingLabel component by dropping it on theform. Note that all the usual properties of a Label component are present in theObject Inspector, as well as the FlashRate and FlashEnabled properties. Note alsothat the default values you specified for these properties are displayed in the ObjectInspector.</P><P>I want to explain what you did in step 3. Delphi has a default package calledDCLUSR40 that can be used to install individual components. I had you install theFlashingLabel component in this package primarily because TFlashingLabel is a singlecomponent (not part of an overall component library), and that's what this packageis for. You could have created a new package rather than use the DCLUSR40 package,but it is easier to use the package provided.</P><P><H2><A NAME="Heading17"></A>Adding a Custom Bitmap to the Component's Button</H2><P>You might have noticed a problem with your newly installed component: The buttonfor the FlashingLabel component on the Component palette has the default Delphi bitmap.You can't have that! Fortunately, you can specify a bitmap for your new component.You have to create a bitmap and place it in a compiled resource file (a .dcr file).</P><BLOCKQUOTE>	<P><HR><strong>TIP:</strong> Sometimes you might want to take the button for the base class and	modify it slightly to represent your new component. In that case, start the Image	Editor and open one of the .dcr files in the \Delphi 4\Lib\Obj directory. You'll	have to hunt to find the exact bitmap. For example, the bitmap for the Label component	is in the file called Stdreg.dcr. Open that file, copy the TLABEL bitmap to the Clipboard,	begin a new resource file, and paste the bitmap from the Clipboard into a new bitmap	resource called TFLASHINGLABEL. Modify the bitmap as desired and then save the resource	project.<HR></BLOCKQUOTE><P>The bitmap for the component's button must be 24&#165;24 pixels. Most of the timea 16-color bitmap is sufficient. Delphi uses the lower-left pixel in the bitmap forthe transparent color, so keep that in mind when designing your component's bitmap.(Delphi bitmaps use the dark yellow color as the transparent color, so you can followthat convention if you want.)</P><BLOCKQUOTE>	<P><HR><strong>NOTE:</strong> Be sure you create a bitmap resource and not an icon resource. The	Component palette buttons are often called icons, but their images are bitmaps and	not icons.<HR></BLOCKQUOTE><P>After you create the resource file, Delphi automatically adds the component'sbitmap to the Component palette when you install the component's package. For thisto happen, you must follow a specific naming convention for the bitmap.</P><P>Specifically, the resource file must have a bitmap resource that exactly matchesthe classname of the component. For example, to create a bitmap for the FlashingLabelcomponent's button, you use Image Editor to create a resource file that containsa bitmap resource called TFLASHINGLABEL. You can name the resource file anythingyou want.</P><P>Now that you have created a resource file, you must tell Delphi to link the resourcefile with the component's code. To do that, add a line like this to your component'ssource code:</P><P><PRE>{$R Flashing.res} </PRE><P>The $R compiler directive tells the compiler to include the contents of a resourcefile with the unit's compiled code. Now rebuild the package. If you've done everythingcorrectly, the bitmap you created for the button will show up in the Component palette.</P><P><BLOCKQUOTE>	<P><HR><strong>NOTE:</strong>  Notice that the filename extension of the resource file in the preceding	code snippet is .res. The .res extension is used interchangeably with the .dcr extension.	Some component vendors use a unique naming convention for their compiled resources	and don't use either .res or .dcr. The filename extension is not important when using	the $R compiler directive. What is important, however, is that the file contains	valid resources.</BLOCKQUOTE><PRE></PRE><BLOCKQUOTE>	<P>As an alternative, you can also add the $R directive directly to the package source.	Most of the time this is not necessary, though. <HR><BR>	<HR><strong>CAUTION:</strong> You can add compiled resources only in one place. Place the $R	compiler directive in either the package source or in the component's unit, but not	both. If you add the same resources more than once, you will get a compiler error	and the package will not install.<HR>	<P><HR><strong>TIP:</strong> If you have a library of several components, you can use one resource	file for all of the component's bitmaps. You don't need to have a separate resource	file for each component in your library.<HR></BLOCKQUOTE><H2><A NAME="Heading18"></A>Writing Events for Components</H2><P>Writing events requires some planning. When I speak of events, I am talking abouttwo possibilities. Sometimes an event occurs as the result of a Windows message,and sometimes an event occurs as a result of a change in the component. An eventtriggered by a Windows message is more or less out of your control. You can respondto this type of event, but you generally don't initiate the event. The second typeof event is triggered by the component itself. In other words, as the component writer,you are in control of when this type of event occurs.</P><P>Working with events at this level can be confusing. I'll try to get past thatconfusion and show you how events can be used on a practical level. To do this, let'sadd an event to the TFlashingLabel class. First, however, let's cover a few of theevent basics.</P><P><H3><A NAME="Heading19"></A>Events Overview</H3><P>To begin with, you should understand that events are properties, and, as such,they have all the features that a regular property has. Events use a private datafield to store their values, as do other properties. In the case of an event, theunderlying data field contains the address of a function that will be called whenthe specified event occurs. Like properties, events can be published or non-published.Published events show up in the Object Inspector just as published properties do.<PRE></PRE><P>Second, events are <I>method pointers</I>. Method pointers are like function super-pointers:They can point not only to a function in a class instance, but they can also pointto a function in an instance of an unrelated class. As long as the function declarationsmatch (the same return type and the same function parameters), the method pointerhappily calls the function regardless of where it's located. For example, the OnClickevent of a TLabel object can point to an event-handling function in a TEdit object,a TForm object, a TListBox object, and so on. Method pointers are more complicatedthan that, but I won't go into the gory details.</P><BLOCKQUOTE>	<P><HR><strong>NOTE:</strong> Event handlers must always be procedures. An event might pass one	or more parameters depending on the type of the event, but it can't return a value.	You can get information back from the event handler, though, by using one or more	var parameters and enabling the user to change those parameters to achieve a particular	behavior.<HR></BLOCKQUOTE><P>You might deal with events on any one of several levels. For example, you mightwant to override the base class event handler for a particular event to add somefunctionality. Let's say you want something special to happen when the user clickson your component with the mouse. There's no use going to all the trouble of creatinga new event for a mouse click because the event already exists in the form of thebase class's OnClick event. You just tag onto that event rather than create a newevent to catch the mouse click.</P><P>Another way you might deal with events is by creating an event that you triggerfrom within the component. I will describe this type of event first. As I said, you'regoing to add an event to the TFlashingLabel component that you created earlier. Addingthis event requires that you also add a new property. The event will be called OnLimitReached,and the new property will be called FlashLimit. This event will be fired after thecomponent flashes the number of times specified by FlashLimit. If FlashLimit is 0(the default), the OnLimitReached event will never be fired.</P><P>Writing a user-defined event for a component can be divided into five basic tasks:</P><P><DL>	<DT></DT>	<DD><B>1. </B>Determine the event type.	<P>	<DT></DT>	<DD><B>2. </B>Declare the underlying data field.	<P>	<DT></DT>	<DD><B>3. </B>Declare the event.	<P>	<DT></DT>	<DD><B>4. </B>Create a virtual method that is called when the event is to be triggered.	<P>	<DT></DT>	<DD><B>5. </B>Write code to trigger the event.	<P></DL><P>Let's walk through these steps so that you better understand what is involved.<PRE></PRE><H4>Determining the Event Type</H4><P>Earlier, when I discussed properties, I said that a property is of a specifictype. The same is true of events. In the case of events, though, the type is a methodpointer that includes a description of the event handler's parameters. Yesterday,Day 19, &quot;Creating and Using DLLs,&quot; I talked a little about function pointerswhen I discussed DLLs.</P><P>As I have said several times, there are two basic types of events. One is the<I>notification event</I>. This event tells you that something happened, but it doesn'tgive you any other details. The function declaration of the event handler for a notificationevent looks like this:</P><P><PRE>procedure Clicked(Sender : TObject);</PRE><P>The only information you get in a notification event is the sender of the event.Delphi provides the TNotifyEvent type for notification events. Any events you createthat are notification events should be of the TNotifyEvent type.</P><P>The other type of event is an event that has more than one parameter and actuallypasses information to the event handler. If you want to, you can create this typeof event for your components. Let's say you want to use an event handler that isprototyped like this:</P><P><PRE>procedure LimitReached(Sender : TObject; var Stop : Boolean);</PRE><P>Using this type of event handler enables the user to modify the Stop parameter,thereby sending information back to the component. If you are going to create eventsthat have parameters, you need to declare your own method type.</P><P>Let's say you want to write an event type for the preceding method declarationand that the event type will be named TLimitReachedEvent. It would look like this:</P><P><PRE>TLimitReachedEvent =</PRE><PRE>  procedure(Sender : TObject; var Stop : Boolean) of object;</PRE><P>Although that's kind of confusing, all you have to do is copy this pattern andthen add or remove parameters as needed. After you have the event type defined, youcan declare an event to be of the type TLimitReachedEvent. (This won't make a lotof sense until you work through the whole process, so bear with me.)</P><BLOCKQUOTE>	<P><HR><strong>NOTE:</strong> Place the declaration for a new event type in the type section of	the unit just above the class declaration. For example:	<PRE>unit FlashingLabel;interfaceuses  Windows, Messages, SysUtils, Classes, Graphics, Controls,  Forms, Dialogs, StdCtrls, ExtCtrls;type  TLimitReachedEvent =    procedure(Sender : TObject; var Stop : Boolean) of object;  TFlashingLabel = class(TCustomLabel)  private{ Rest of unit follows. } </PRE>	<P><HR></BLOCKQUOTE><PRE></PRE><P>Try to determine to the best of your ability what type of events (if any) youneed for your component. If you need only notification events, you will create yourevents to be of the TNotifyEvent type. If your events will pass parameters to theevent handler, you need to define your own event type.</P><P><H3><A NAME="Heading20"></A>Declaring the Underlying Data Field</H3><P>Declaring the underlying data field is the simple part. All you have to do isdeclare a private data field with the same type as your event. It looks like this:</P><P><PRE>FOnLimitReached : TLimitReachedEvent;</PRE><P>As with properties, the data field's name is the same as the event name with the<I>F</I> on the front.</P><P><H4>Declaring the Event</H4><P>Now that you have determined the event type, you can declare the event for thecomponent. The declaration for an event looks almost identical to the declarationfor any other property. Here's a typical declaration for an event:</P><P><PRE>property OnSomeEvent : TNotifyEvent  read FOnSomeEvent write FOnSomeEvent;</PRE><P>For the most part, this looks like the property declarations that you dealt withearlier. Notice that there is no default specifier. Notice also that the read andwrite specifiers both point to the FOnSomeEvent data field. This illustrates thatevents use direct access and do not use read and write methods. Finally, notice thatin this example the event's type is TNotifyEvent.</P><P>The OnLimitReached event will pass parameters, so you must define a special typeand apply it to the event. Given that, your declaration for the OnLimitReached eventlooks like this:</P><P>property OnLimitReached : TLimitReachedEvent</P><P><PRE>  read FOnLimitReached write FO

⌨️ 快捷键说明

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