[ Pobierz całość w formacie PDF ]
.htm (37 of 79) [10/10/2000 1:14:53 AM]Ch 22 -- Creating Descendants of Existing ComponentsFClockAttributes->Shape = stEllipse;}///////////////////////////////////////// SetRunning///////////////////////////////////////void __fastcall TMyClock::SetRunning(Boolean Run){if (Run){SetTimer(Handle, FTimer, 50, NULL);FRunning = True;}else{KillTimer(Handle, FTimer);FRunning = False;}}///////////////////////////////////////// Paint///////////////////////////////////////void __fastcall TMyClock::Paint(void){Color = ClockAttributes->Color;switch (ClockAttributes->Shape){int X;file:///D|/DOWNLOAD/charlie_calvert's_borland_c++_builder_unleashed/ch22.htm (38 of 79) [10/10/2000 1:14:53 AM]Ch 22 -- Creating Descendants of Existing Componentscase stEllipse: Canvas->Ellipse(0, 0, Width, Height); break;case stRectangle: Canvas->Rectangle(0, 0, Width, Height); break;case stRoundRect:Canvas->RoundRect(0, 0, Width, Height, Width - 100, Height);break;case stSquare:{if (Width Rectangle(Width - X, 0, Width + X, Width);}else{X = Height / 2;Canvas->Rectangle((Width / 2) - X, 0, (Width / 2) + X, Height);}break;}case stCircle:{if (Width Ellipse(Width - X, 0, Width + X, Width);}else{file:///D|/DOWNLOAD/charlie_calvert's_borland_c++_builder_unleashed/ch22.htm (39 of 79) [10/10/2000 1:14:53 AM]Ch 22 -- Creating Descendants of Existing ComponentsX = Height / 2;Canvas->Ellipse((Width / 2) - X, 0, (Width / 2) + X, Height);}break;}}}///////////////////////////////////////// WM_TIMER///////////////////////////////////////void __fastcall TMyClock::WMTimer(TMessage &Message){AnsiString S = TimeToStr(Time());Canvas->Font = Font;Canvas->TextOut(Width / 2 - Canvas->TextWidth(S) / 2,Height / 2 - Canvas->TextHeight(S) / 2, S);}///////////////////////////////////////// WM_DESTROY///////////////////////////////////////void __fastcall TMyClock::WMDestroy(TMessage &Message){KillTimer(Handle, FTimer);FTimer = 0;TCustomControl::Dispatch(&Message);}//------------------------------------file:///D|/DOWNLOAD/charlie_calvert's_borland_c++_builder_unleashed/ch22.htm (40 of 79) [10/10/2000 1:14:53 AM]Ch 22 -- Creating Descendants of Existing Components//-- TColorClock --------------------//------------------------------------///////////////////////////////////////// WM_DESTROY///////////////////////////////////////void __fastcall TColorClock::Paint(){Canvas->Brush->Color = FFaceColor;TMyClock::Paint();}///////////////////////////////////////// SetColor///////////////////////////////////////void __fastcall TColorClock::SetColor(TColor Color){FFaceColor = Color;InvalidateRect(Handle, NULL, True);}//------------------------------------//-- TClockEditor --------------------//------------------------------------void __fastcall TClockEditor::Edit(void){TColorDialog *C = new TColorDialog(Application);if (C->Execute())((TColorClock *)(Component))->FaceColor = C->Color;file:///D|/DOWNLOAD/charlie_calvert's_borland_c++_builder_unleashed/ch22.htm (41 of 79) [10/10/2000 1:14:53 AM]Ch 22 -- Creating Descendants of Existing Components}//------------------------------------//-- TColorNameProperty --------------//------------------------------------TPropertyAttributes __fastcall TColorNameProperty::GetAttributes(void){return TPropertyAttributes() FaceColor = ColorDialog1->Color;}}To run this program, you should first select the menu item that creates the clock and makes it visible on the form.The nextlogical step is to start the clock running; then, if you'd like, you can also change its color.You get an AccessViolation if you click the latter two buttons before selecting the first.The problem is that calling a method or propertyof the TClock object before the object itself has been created is an error.To prevent this error from happening, you couldenable and disable the second two buttons.The code for the clock components uses inheritance, virtual methods, and properties.TClock has two pieces of privatedata:int FTimer;Boolean FRunning;One is an identifier for the timer, and the other is a Boolean value that specifies whether the clock is running.Windows timers are managed by two Windows API calls.When you want to start a timer, use SetTimer; when you wantto stop a timer, use KillTimer.SetTimer takes four parameters:Handle is the HWND of your current window.IDEvent is an integer identifier that uniquely identifies the timer inside the window that created it.You can makeup this value off the top of your head, although I generally set the IDTimer for the first timer in a window to 1, thesecond timer to 2, and so on.Because you're going to have only one timer in each instance of a TClock window,you can set its IDEvent to 1.Elapse is the length of time between calls to the timer, measured in milliseconds.TimerFunc is a callback function that is not used in this program.One of the developers' big goals was to create aWindows product that didn't need to use callbacks, and I see no reason to open that can of worms now if I can avoidit.(If you want to create a callback in BCB, you will be able to do so, but it's usually not necessary.)A typical call to SetTimer looks like this:SetTimer(Handle, FTimer, 50, NULL);50 specifies that the timer is called once every 50 milliseconds.SetTimer returns zero if the call fails.This is a realpossibility, so programs that include error checking should inspect this value and put up a MessageBox if the call fails.KillTimer takes two parameters, the first being the handle of your window and the second being the unique identifierassociated with that timer:KillTimer(Handle, FTimer);When you're not using the callback function, timer events are sent to your window by way of messages:void __fastcall WMTimer(TMessage &Message);BEGIN_MESSAGE_MAPMESSAGE_HANDLER(WM_TIMER, TMessage, WMTimer);MESSAGE_HANDLER(WM_DESTROY, TMessage, WMDestroy);END_MESSAGE_MAP(TCustomControl);This classic dynamic method is of the kind covered in Chapter 4, "Events." The response to this event is a simple procedurethat calls TextOut and gets the time from the VCL:file:///D|/DOWNLOAD/charlie_calvert's_borland_c++_builder_unleashed/ch22.htm (44 of 79) [10/10/2000 1:14:53 AM]Ch 22 -- Creating Descendants of Existing Componentsvoid __fastcall TMyClock::WMTimer(TMessage &Message){AnsiString S = TimeToStr(Time());Canvas->TextOut(Width / 2 - Canvas->TextWidth(S) / 2,Height / 2 - Canvas->TextHeight(S) / 2, S);}The calls to SetTimer and KillTimer are managed primarily through a property called Running:__property Boolean Running={read=FRunning, write=SetRunning};The write mechanism, a procedure called SetRunning, is a fairly straightforward tool:void __fastcall TMyClock::SetRunning(Boolean Run){if (Run){SetTimer(Handle, FTimer, 50, NULL);FRunning = True;}else{KillTimer(Handle, FTimer);FRunning = False;}}If the user sets the Running property to True, this procedure is executed and a call is made to the SetTimer function.Ifthe user sets Running to False, KillTimer is called and the clock immediately stops functioning
[ Pobierz całość w formacie PDF ]