Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Pro Visual C++-CLI And The .NET 2.0 Platform (2006) [eng]-1

.pdf
Скачиваний:
71
Добавлен:
16.08.2013
Размер:
24.18 Mб
Скачать

338 C H A P T E R 9 B A S I C W I N D O W S F O R M S A P P L I C A T I O N S

#pragma region Windows Form Designer generated code

void InitializeComponent(void)

{

this->groupBox2 = (gcnew System::Windows::Forms::GroupBox()); this->groupBox1 = (gcnew System::Windows::Forms::GroupBox()); this->SuspendLayout();

//

//groupBox2

this->groupBox2->Location = System::Drawing::Point(125, 153); this->groupBox2->Name = L"groupBox2";

this->groupBox2->Size = System::Drawing::Size(152, 134); this->groupBox2->TabIndex = 3;

this->groupBox2->TabStop = false; this->groupBox2->Text = L"Use";

//groupBox1

//

this->groupBox1->Location = System::Drawing::Point(125, 12); this->groupBox1->Name = L"groupBox1";

this->groupBox1->Size = System::Drawing::Size(152, 135); this->groupBox1->TabIndex = 2;

this->groupBox1->TabStop = false; this->groupBox1->Text = L"You";

//

// Form1

//

this->AutoScaleDimensions = System::Drawing::SizeF(6, 13); this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font; this->ClientSize = System::Drawing::Size(352, 330); this->Controls->Add(this->groupBox2); this->Controls->Add(this->groupBox1);

this->Name = L"Form1";

this->Text = L"Using Group Boxes"; this->ResumeLayout(false);

}

#pragma endregion

void BuildRadios()

{

this->SuspendLayout();

//Text for RadioButton places on Form directly array<String^>^ rbText1 = gcnew array<String^> {

L"Can", L"You", L"Click", L"More", L"Than", L"One"

};

//Build a RadioButton for each rbText1

radio1 = gcnew array<RadioButton^>(6); for (int i = 0; i < radio1->Length; i++)

{

radio1[i] = gcnew RadioButton();

C H A P T E R 9 B A S I C W I N D O W S F O R M S A P P L I C A T I O N S

339

radio1[i]->Location = Drawing::Point(20, 20+(40*i)); radio1[i]->Text = rbText1[i];

}

//Add RadioButtons to Form Controls->AddRange(radio1);

//Text for RadioButton places in first GroupBox array<String^>^ rbText2 = gcnew array<String^> {

L"Can", L"If", L"You"

};

//Build a RadioButton for each rbText2

radio2 = gcnew array<RadioButton^>(3); for (int i = 0; i < radio2->Length; i++)

{

radio2[i] = gcnew RadioButton();

radio2[i]->Location = Drawing::Point(40, 30+(35*i)); radio2[i]->Text = rbText2[i];

}

//Add RadioButtons to GroupBox groupBox1->Controls->AddRange(radio2);

//Text for RadioButton places in second GroupBox array<String^>^ rbText3 = gcnew array<String^> {

L"Different", L"Group", L"Boxes"

};

//Build a RadioButton for each rbText3

radio3 = gcnew array<RadioButton^>(3); for (int i = 0; i < radio3->Length; i++)

{

radio3[i] = gcnew RadioButton();

radio3[i]->Location = Drawing::Point(40, 30+(35*i)); radio3[i]->Text = rbText3[i];

}

// Add RadioButtons to GroupBox2 groupBox2->Controls->AddRange(radio3);

this->ResumeLayout(false);

}

};

}

Only a couple of things are new here. First, notice now that you add the GroupBox to the form and then add the RadioButtons to the GroupBox, as opposed to adding the RadioButtons to the form. You can also add the RadioButtons to the GroupBox and then add the GroupBox to the form. Which of the previous methods you choose is not important, as long as the controls are defined and instantiated before being added.

The second new thing is the location where you put the RadioButtons. The location is relative to the GroupBox and not the form. Notice that the same code is used to specify the location of the

RadioButtons for both GroupBoxes.

As you can see, you can combine the auto-generated GUI tool code and the hand-coded code together, but you have to be careful. You can’t add your code within the InitializeComponent() method, because the GUI design tool will overwrite it any time you change the form using the design

340 C H A P T E R 9 B A S I C W I N D O W S F O R M S A P P L I C A T I O N S

tool. Because this is the case, I had to create the BuildRadios() method to add my hand-designed code instead of embedding it directly within the InitializeComponent() method.

Figure 9-11 shows what GroupingRadios.exe looks like when you execute it. Try to click the radio buttons. Now you are able to select three different ones.

Figure 9-11. Groups of radio buttons

The Panel Control

The Panel control is similar in many ways to the GroupBox control. It also groups controls visually into a box and binds them so that they act as a group. It differs in that you can enable it to support scrolling, thus letting the Panel control contain more controls than its area would normally allow.

A feature that both the Panel and GroupBox controls share is that when you disable the Panel, all the controls within the Panel are also disabled. You do this by setting the Enable property to false. Another feature I particularly like is that you can make the Panel invisible by setting the Visible property to false. Using this feature, you can make the form less cluttered by hiding Panels that are not currently relevant.

Listing 9-10 shows how it is now possible to enable, disable, and make Panels reappear. It also highlights how to enable autoscrolling within a Panel.

Listing 9-10. The Code for Disabling and Hiding Panels

#pragma once

namespace

Panels

{

 

using

namespace System;

using

namespace System::ComponentModel;

using

namespace System::Collections;

using

namespace System::Windows::Forms;

using

namespace System::Data;

using

namespace System::Drawing;

C H A P T E R 9 B A S I C W I N D O W S F O R M S A P P L I C A T I O N S

341

public ref class Form1 : public System::Windows::Forms::Form

{

public:

Form1(void)

{

InitializeComponent();

}

protected:

~Form1()

{

if (components)

{

delete components;

}

}

private:

System::Windows::Forms::Panel^ Rightpanel; System::Windows::Forms::Button^ button2; System::Windows::Forms::Button^ button1; System::Windows::Forms::Panel^ Leftpanel; System::Windows::Forms::Button^ bnHide; System::Windows::Forms::Button^ bnDisable;

System::ComponentModel::Container ^components;

#pragma region Windows Form Designer generated code

void InitializeComponent(void)

{

this->Rightpanel = (gcnew System::Windows::Forms::Panel()); this->button2 = (gcnew System::Windows::Forms::Button()); this->button1 = (gcnew System::Windows::Forms::Button()); this->Leftpanel = (gcnew System::Windows::Forms::Panel()); this->bnHide = (gcnew System::Windows::Forms::Button()); this->bnDisable = (gcnew System::Windows::Forms::Button()); this->Rightpanel->SuspendLayout(); this->Leftpanel->SuspendLayout();

this->SuspendLayout();

//

// Rightpanel

//

this->Rightpanel->AutoScroll = true; this->Rightpanel->BorderStyle =

System::Windows::Forms::BorderStyle::Fixed3D; this->Rightpanel->Controls->Add(this->button2); this->Rightpanel->Controls->Add(this->button1); this->Rightpanel->Location = System::Drawing::Point(161, 22); this->Rightpanel->Name = L"Rightpanel"; this->Rightpanel->Size = System::Drawing::Size(121, 60); this->Rightpanel->TabIndex = 3;

342 C H A P T E R 9 B A S I C W I N D O W S F O R M S A P P L I C A T I O N S

//

//button2

this->button2->Location = System::Drawing::Point(20, 62); this->button2->Name = L"button2";

this->button2->Size = System::Drawing::Size(75, 23); this->button2->TabIndex = 1;

this->button2->Text = L"button 2";

//button1

//

this->button1->Location = System::Drawing::Point(20, 7); this->button1->Name = L"button1";

this->button1->Size = System::Drawing::Size(75, 23); this->button1->TabIndex = 0;

this->button1->Text = L"button 1";

//

//Leftpanel

this->Leftpanel->BorderStyle = System::Windows::Forms::BorderStyle::FixedSingle;

this->Leftpanel->Controls->Add(this->bnHide); this->Leftpanel->Controls->Add(this->bnDisable);

this->Leftpanel->Location = System::Drawing::Point(28, 22); this->Leftpanel->Name = L"Leftpanel";

this->Leftpanel->Size = System::Drawing::Size(120, 95); this->Leftpanel->TabIndex = 2;

//bnHide

//

this->bnHide->Location = System::Drawing::Point(17, 62); this->bnHide->Name = L"bnHide";

this->bnHide->Size = System::Drawing::Size(75, 23); this->bnHide->TabIndex = 1;

this->bnHide->Text = L"Hide"; this->bnHide->Click +=

gcnew System::EventHandler(this, &Form1::bnHide_Click);

//

//bnDisable

this->bnDisable->Location = System::Drawing::Point(17, 7); this->bnDisable->Name = L"bnDisable";

this->bnDisable->Size = System::Drawing::Size(75, 23); this->bnDisable->TabIndex = 0;

this->bnDisable->Text = L"Disable"; this->bnDisable->Click +=

gcnew System::EventHandler(this, &Form1::bnDisable_Click);

//Form1

//

this->AutoScaleDimensions = System::Drawing::SizeF(6, 13); this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font; this->ClientSize = System::Drawing::Size(310, 139); this->Controls->Add(this->Rightpanel);

C H A P T E R 9 B A S I C W I N D O W S F O R M S A P P L I C A T I O N S

343

this->Controls->Add(this->Leftpanel); this->Name = L"Form1";

this->Text = L"A hidden fourth button"; this->Rightpanel->ResumeLayout(false); this->Leftpanel->ResumeLayout(false); this->ResumeLayout(false);

}

#pragma endregion

private:

System::Void bnDisable_Click(System::Object^ sender, System::EventArgs^ e)

{

Rightpanel->Enabled = !Rightpanel->Enabled;

}

private:

System::Void bnHide_Click(System::Object^ sender, System::EventArgs^ e)

{

Rightpanel->Visible = !Rightpanel->Visible;

}

};

}

What’s interesting in this form is the ability to use a button to disable and hide Panels. Another neat feature is that you can use the Enable and Visible properties as toggles:

Rightpanel->Enabled = !Rightpanel->Enabled;

Rightpanel->Visible = !Rightpanel->Visible;

To get RightPanel to scroll, you have to set its client size smaller than the visual area needed to view all controls. Basically, because a control is going to be obscured, the Panel automatically creates the appropriate scroll bar (either vertical or horizontal) so that the control can be exposed.

Figure 9-12 shows what Panels.exe looks like when you execute it and click the Disable Panel button. I guess I could have also clicked the Hide Panel button, but then the RightPanel would have disappeared and you wouldn’t be able to tell that it was disabled.

Figure 9-12. Disabling and hiding panels

The Text Controls

There is obviously a need to enter text into most Win Forms applications. To handle this, the .NET Framework provides three highly configurable text controls: TextBox, MaskedTextBox, and RichTextBox. All three text controls are very powerful. In fact, the simplest of the three, the TextBox control, has so much functionality that you will probably use it most, if not all, of the time. A few possible exceptions

344 C H A P T E R 9 B A S I C W I N D O W S F O R M S A P P L I C A T I O N S

are when you want a specifically formatted sequence of characters, in which case you would select MaskedTextBox, or if you require font styles such as boldface, italic, or underline within the text being entered, in which case you would choose RichTextBox.

As is the common theme in the .NET Framework class library, the text controls derive from a common abstract base class, TextBoxBase. This class provides a common set of functionality that you can use for all three text controls, and it’s also a great starting point for those programmers who need to write a text control to meet specific needs.

The abstract TextBoxBase class is composed of numerous properties and methods that can handle text input from the user. Being that TextBoxBase is an abstract class, you can’t instantiate from it; instead, you need to use one of its child classes. Here are some common TextBoxBase-specific properties:

AcceptsTab is a Boolean that represents, in a multiline text control, whether the Tab key will be used as a control character or as a means to move to the next control. The default is false.

CanUndo is a Boolean that represents whether the control can undo the previous operation that occurred. The default is false.

MaxLength is an Int32 that represents the maximum number of characters allowed to be entered into the control. The default is 0, which means the allowable number of characters enterable is only restricted by the memory of the computer.

Modified is a Boolean that represents whether the content of the control has been modified since the control was created or the contents were set. The default is false.

Multiline is a Boolean that represents whether the control is made up of more than one line. The default is false.

ReadOnly is a Boolean that represents whether the control is read-only. The default is false.

SelectedText is a String containing selected text from the control. The default is a zero-length

String (not null).

SelectionLength is an Int32 that represents the length of the selected text. If the SelectionLength property is set to a value larger than the length of text within the control, it’s automatically set to the number of characters in the control minus the SelectionStart property.

SelectionStart is an Int32 that represents the starting location of the selected text within the control. If the SelectionStart property is set to a value larger than the number of characters within the control, it’s automatically set to the value after the last character in the control.

Text is a String that represents the text of the control.

WordWrap is a Boolean that represents, in a multiline text control, whether a word wraps automatically to the beginning of a line when necessary. If the value is false, the control will scroll horizontally when text is entered beyond the width of the control. The default is true.

Here are some common TextBoxBase-specific methods:

AppendText() adds text to the end of the current text of the control.

Clear() sets the text in the control to be empty.

ClearUndo() removes the last undo operation from the undo buffer.

Copy() takes the selected text and places it on the Clipboard. The control is unaffected.

Cut() removes the selected text from the control and places it on the Clipboard.

Paste() copies the text in the Clipboard to the current location of the cursor in the control.

Select() selects text within the control using a start location and a length.

C H A P T E R 9 B A S I C W I N D O W S F O R M S A P P L I C A T I O N S

345

SelectAll() selects all the text within the control.

Undo() restores the contents in the text control back to the previous state before the last operation.

TextBox

As stated earlier, you can configure the TextBox control in many ways, ranging from long to short, normal to password hidden, and single to multilined. If you enable this control, you have a built-in undo buffer. You can cut and paste to it. The functionality this control has is simply amazing.

Along with the properties provided by TextBoxBase, the TextBox control adds a few properties of its own:

AcceptReturn is a Boolean that represents, in a multiline control, whether pressing the Enter key creates a new line of text or passes control to the default button of the form. If this property is set to false, then Ctrl-Enter must be pressed to create a new line of text. The default is true.

CharacterCasing is a CharacterCasing enum class that notifies the control as characters are entered into the control that it should convert the character to uppercase, lowercase, or leave the character as typed. The default is CharacterCasing::Normal or to leave the characters as they are typed.

PasswordChar is a Char that represents the character to be used to replace all the characters typed in, thus hiding the password from view. The default is the value 0, meaning do not use

PasswordChar.

TextAlign is a HorizontalAlignment enum class that represents whether the text should be right justified, left justified, or centered when entered. The default is HorizontalAlignment::Left, or left justified.

MaskedTextBox

The basic idea behind the MaskedTextBox is it provides a mask by which to enter text data. Then, using an assortment of properties and methods, it ensures that the user is adhering to the specified mask.

Here are some common properties and an event that you would use to ensure the data entered matches the mask:

BeepOnError is a Boolean property that enables or disables the system beep when an invalid character is entered onto the mask entry. If this property is set to true, then invalid keystrokes will beep. The default is false.

MaskCompleted is a Boolean property that becomes true when all required mask entries have been populated.

MaskFull is a Boolean property that becomes true when all mask entries are populated.

MaskInputRejected is an event that provides a way for you to customize the handling of invalid keystroke entries onto the mask.

Having valid characters entered onto the mask does not necessarily mean that you have a valid value to match the given type of the data entry field. In other words, you can enter numbers into a date field, as is required by the mask, and still enter an invalid date. To ensure that a valid data type will result from the entry in the MaskedTextBox, you must assign an instance of the data type expected to be entered to the ValidatingType property:

mtbDoB->ValidatingType = DateTime::typeid;

I will cover the typeid operator in detail in Chapter 18.

346 C H A P T E R 9 B A S I C W I N D O W S F O R M S A P P L I C A T I O N S

Then to see if the input data of the control matches the data type assigned, you add a handler to the TypeValidationCompleted event, which triggers when the control loses focus. Finally, you examine the IsValidInput property of TypeValidationEventArgs argument passed by the event. If the value is true, then the data entered into the control parses to the data type assign by the ValidatingType property, and the value is placed in TypeValidationEventArgsReturnValue property.

Note If you are implementing your own data type, you need to implement the static Parse() method before assigning an instance of it to the ValidatingType property.

If you just want the text value returned from the MaskedTextBox and not a specific data type, then the control provides a number of properties to provide the value in the format you require:

Text is a String property that returns what the user currently sees in the control.

OutputText is a String property that returns a value based on the values specified in the

IncludeLiteral and IncludePrompt properties. The IncludeLiteral property specifies whether the literals specified in the mask are included, while the IncludePrompt specifies whether the prompt characters are included. Both of these properties default to true.

InputText is a String property that returns only what the user actually entered in the control.

The MaskedTextBox control’s mask must be made up of one or more of the characters defined in Table 9-1. The characters used by MaskedTextBox are based on those used by the Masked Edit Control in Visual Basic 6.0.

Table 9-1. MaskedTextBox Masking Characters

Masking Character

Description

0

A mandatory digit between 0 and 9.

9

An optional digit between 0 and 9.

#

An optional digit between 0 and 9 or a +, - or space. If the position of

 

this mask entry is left blank, then the value is space.

L

A mandatory letter between a–z and A–Z.

?

An optional letter between a–z and A–Z.

&

A mandatory letter. If the AsciiOnly property is set, then this mask

 

behaves the same as L.

C

An optional letter. If the AsciiOnly property is set, then this mask

 

behaves the same as ?.

A

A mandatory alphanumeric. If the AsciiOnly property is set, then the

 

only characters allowed are a–z and A–Z.

a

An optional alphanumeric. If the AsciiOnly property is set, then the

 

only characters allowed are a–z and A–Z.

.

A decimal placeholder. The UI culture will determine the actual

 

decimal placeholder used.

,

A thousands placeholder. The UI culture will determine the actual

 

thousands placeholder used.

C H A P T E R 9 B A S I C W I N D O W S F O R M S A P P L I C A T I O N S

347

Table 9-1. MaskedTextBox Masking Characters

Masking Character

Description

:

A time separator. The UI culture will determine the actual time

 

separator used.

/

A date separator. The UI culture will determine the actual date

 

separator used.

$

A currency symbol. The UI culture will determine the actual currency

 

symbol used.

<

Converts all subsequent characters to lowercase.

>

Converts all subsequent characters to uppercase.

|

Disables previous > or < masks.

\

Turns a mask character into a literal. A [\\] will turn into a \ literal.

All other characters

A literal that will appear in a static location within the control. The user

 

will not be able to move or delete the literal.

 

 

The next example (see Listing 9-11) demonstrates some features of the TextBox and MaskedTextBox control. First it creates a TextBox and a MaskedTextBox to handle input. When the user clicks the Submit button, the text gets inserted into the front of the read-only, multiline text box. This multiline text box can be made editable if you enter “Editable” in the bottom password text box.

You should notice the following thing about this example. I set the multiline text box properties AcceptTab and AcceptReturn to true. This causes the pressing of the Tab key to create a tab character in the multiline text box (when editable, obviously) and causes the Enter key to create a new line of text. This differs from the default functionality of the remaining controls, which jump to the next control on the Tab key and causes the AcceptButton to be triggered when the Enter key is pressed.

Listing 9-11. Some TextBox and MaskedTextBox Code

#pragma once

namespace

TextEntry

{

 

using

namespace System;

using

namespace System::ComponentModel;

using

namespace System::Collections;

using

namespace System::Windows::Forms;

using

namespace System::Data;

using

namespace System::Drawing;

public ref class Form1 : public System::Windows::Forms::Form

{

public:

Form1(void)

{

InitializeComponent();

DoB = DateTime::MinValue;