[ Pobierz całość w formacie PDF ]
.The VCL has no use forthis field; it is designed explicitly for you to use as you wish, for whatever purpose you want.file:///D|/DOWNLOAD/charlie_calvert's_borland_c++_builder_unleashed/ch02.htm (26 of 34) [10/10/2000 1:12:29 AM]Ch 2 -- Basic Facts About C++BuilderAll six menu items should be associated with the same event handler through their OnClick method.You can create theoriginal handler by open up the Menu Designer, turning to the Events page in the Object Inspector, and double-clicking theOnChange event.If you then select the OnChange event for the other menu items, you will see that it opens up into acombo box from which you can select all the compatible events.For each of the other five menu items, select the event youcreated for the first menu item.The event itself should look like this:void __fastcall TForm1::Rectangle1Click(TObject *Sender){Shape1->Shape = TShapeType(dynamic_cast(Sender)->Tag);}I will explain what this code means over the course of the next few paragraphs.NOTE: Just now I said that the events that appear in the drop-down combo for the Events page of the ObjectInspector must be compatible with a particular event.This means that they must have the same signature, whichis yet another term that needs explanation! The signature of an event is found in the header for the methodhandler associated with a particular event, and in particular it is represented by the parameters passed to thehandler.For instance, the signature for the Rectangle1Click method is represented by the fact that it is amethod that returns nothing and which accepts a single parameter of type TObject *.Methods that look likethis are of type TNotifyEvent.Here is the declaration for TNotifyEvent as it appears in CLASSES.HPP:typedef void __fastcall (__closure *TNotifyEvent)(System::TObject* Sender);When you see this signature for an event, you can assume that Sender contains an instance of the object thatsent the event.For instance, in the case currently under consideration, it is a TMenuItem that sent the event,and the specific TMenuItem that sent the message is passed in the Sender parameter.The items in the menu designate each of the possible shapes the TShape component can assume.You can find these wordslisted in the online help under the listing for TShapeType.Or, if you want to go back to the original source code, you findthe following enumerated type:enum TShapeType { stRectangle, stSquare, stRoundRect,stRoundSquare, stEllipse, stCircle }NOTE: You can also access the names of the members of enumerated type by using the GetEnumName andGetEnumValue functions from the TypInfo unit, which is pronounced "tip-info."In this particular case, you need to write only one line of code in response to the event that occurs when a user clicks aTMenuItem:Shape1->Shape = TShapeType(dynamic_cast(Sender)->Tag);This line of code sets the Shape1->Shape property to the shape that the user has selected in the combo box.The codeworks because of the correspondence between the ordinal members of an enumerated type and the numerical value youassigned to the tag property of a menu.In other words, the first element in an enumerated type has the value zero, as doesthe first tag property.You know, and I know, that the Sender variable contains an instance of the TMenuItem item class.However, the wondersof polymorphism allow BCB to declare this variable to be of type TObject.That way, a TNotifyEvent can acceptobjects of any type.(Polymorphism will be addressed later in the book in Chapter 21, "Polymorphism.")The programmer's knowledge of the Sender parameter needs to be shared with the compiler.In other words, you and I needto have some way of telling the compiler that the object is not really of type TObject, but that it is a just a polymorphicdisguise for a TMenuItem.This is an important step because the TObject class does not have a Tag field, and theTMenuItem class does have a Tag field.In this case, it is absolutely necessary to get at the Tag field because it containsthe code information about the shape the user wants to select.file:///D|/DOWNLOAD/charlie_calvert's_borland_c++_builder_unleashed/ch02.htm (27 of 34) [10/10/2000 1:12:29 AM]Ch 2 -- Basic Facts About C++BuilderTo cast a TObject as a TMenuItem you can use the dynamic_cast syntax.This syntax can be used as part of RTTI totest whether a component is of a particular type, or it can be used to actually make the cast.In this case I am daring and makethe cast without bother to test it first.This is safe in this case because I know the only object that can be passed here is aTMenuItem.However, if I wanted to be extra careful, I could write the following:if (dynamic_cast(Sender))Shape1->Shape = TShapeType(dynamic_cast(Sender)->Tag);This would ensure that no exceptions were raised if the cast should happen to fail, which it won't in this particular case.The final part of the ShapeDem program that is worthy of discussion involves making sure that the scrollbars cling to thebottom and right edges of the control.To do this, you need to respond to WM_SIZE messages, which come to BCBprogrammers under the friendly guise of an OnResize event:void __fastcall TForm1::FormResize(TObject *Sender){ScrollBar1->Max = ClientWidth - (ScrollBar2->Width + 1);ScrollBar2->Max = ClientHeight - (ScrollBar1->Height + 1);ScrollBar1->Left = 0;ScrollBar2->Top = 0;ScrollBar2->Left = ClientWidth - ScrollBar2->Width;ScrollBar2->Height = ClientHeight;ScrollBar1->Top = ClientHeight - ScrollBar1->Height;ScrollBar1->Width = ClientWidth - ScrollBar2->Width;}This code uses third grade math (the only kind I ever understood!) to ensure that the scrollbars are allowed as tall or as wideas the form, no matter how it is stretched or pulled by the user.Furthermore, it ensures that the Min and Max property for thecontrol ranges from zero to the exact size of the current client window.This ensures that you can use the OnChange eventfor the scrollbar to make the TShape object as large as the client window, but no larger.Notice also that the TForm object has properties called ClientWidth and ClientHeight.These properties calculatedthe client size of the current window; that is, the size of the window minus the menu, caption, and frame.If this was done foryou, you would have to write code that looked something like this:int Menu, Caption, Frame;Caption = GetSystemMetrics(SM_CYCAPTION);Frame = GetSystemMetrics(SM_CXFRAME) * 2;Menu = GetSystemMetrics(SM_CYMENU);ScrollBar1->Left = 0;ScrollBar2->Top = 0;ScrollBar1->Max = Width;ScrollBar2->Max = Height;file:///D|/DOWNLOAD/charlie_calvert's_borland_c++_builder_unleashed/ch02.htm (28 of 34) [10/10/2000 1:12:29 AM]Ch 2 -- Basic Facts About C++BuilderScrollBar2->Left = Width - Frame - ScrollBar2->Width;ScrollBar2->Height = Height - Frame - Caption- Menu;ScrollBar1->Top = Height - ScrollBar2->Width - Frame - Caption - Menu;ScrollBar1->Width = Width - ScrollBar2->Width - Frame;The point here is that without having to know about GetSystemMetrics and all its associated constants, you can stillwrite code that calculates the size of the TShape object down to the last pixel
[ Pobierz całość w formacie PDF ]