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

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

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

428 C H A P T E R 1 0 A D V A N C E D W I N D O W S F O R M S A P P L I C A T I O N S

(cli::safe_cast<System::ComponentModel::ISupportInitialize^> (this->eProvider))->BeginInit();

this->SuspendLayout();

//

// tbPword

//

this->tbPword->Location = System::Drawing::Point(103, 83); this->tbPword->Name = L"tbPword"; this->tbPword->PasswordChar = '*';

this->tbPword->Size = System::Drawing::Size(100, 20); this->tbPword->TabIndex = 9; this->tbPword->Validating +=

gcnew System::ComponentModel::CancelEventHandler(this, &Form1::textbox_Validating);

//

//lbPword

this->lbPword->AutoSize = true;

this->lbPword->Location = System::Drawing::Point(34, 83); this->lbPword->Name = L"lbPword";

this->lbPword->Size = System::Drawing::Size(53, 13); this->lbPword->TabIndex = 8;

this->lbPword->Text = L"&Password";

//bnLogin

//

this->bnLogin->Location = System::Drawing::Point(75, 131); this->bnLogin->Name = L"bnLogin";

this->bnLogin->Size = System::Drawing::Size(75, 23); this->bnLogin->TabIndex = 7;

this->bnLogin->Text = L"&Login"; this->bnLogin->Click +=

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

//

// tbName

//

this->tbName->Location = System::Drawing::Point(103, 31); this->tbName->Name = L"tbName";

this->tbName->Size = System::Drawing::Size(100, 20); this->tbName->TabIndex = 6;

this->tbName->Validating +=

gcnew System::ComponentModel::CancelEventHandler(this, &Form1::textbox_Validating);

//

// lbName

//

this->lbName->AutoSize = true;

this->lbName->Location = System::Drawing::Point(34, 31); this->lbName->Name = L"lbName";

this->lbName->Size = System::Drawing::Size(35, 13); this->lbName->TabIndex = 5;

this->lbName->Text = L"&Name";

C H A P T E R 1 0 A D V A N C E D W I N D O W S F O R M S A P P L I C A T I O N S

429

//

//eProvider

this->eProvider->ContainerControl = this;

//Form1

//

this->AutoScaleDimensions = System::Drawing::SizeF(6, 13); this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font; this->ClientSize = System::Drawing::Size(237, 185); this->Controls->Add(this->tbPword); this->Controls->Add(this->lbPword); this->Controls->Add(this->bnLogin); this->Controls->Add(this->tbName); this->Controls->Add(this->lbName);

this->Name = L"Form1"; this->Text = L"System Login";

(cli::safe_cast<System::ComponentModel::ISupportInitialize^> (this->eProvider))->EndInit();

this->ResumeLayout(false); this->PerformLayout();

}

#pragma endregion

private:

System::Void textbox_Validating(System::Object^ sender, System::ComponentModel::CancelEventArgs^ e)

{

try

{

TextBox ^tb = (TextBox^)(sender);

if (tb->Text->Equals(""))

eProvider->SetError(tb, "**Error** Missing Entry!"); else

eProvider->SetError(tb, "");

}

catch (Exception^)

{

// Not TextBox

}

}

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

{

if (tbName->Text->Equals(""))

eProvider->SetError(tbName, "**Error** Missing Entry!");

else

eProvider->SetError(tbName, "");

430 C H A P T E R 1 0 A D V A N C E D W I N D O W S F O R M S A P P L I C A T I O N S

if (tbPword->Text->Equals(""))

{

// Place the icon left side of control eProvider->SetIconAlignment(tbPword,

ErrorIconAlignment::MiddleLeft); eProvider->SetError(tbPword, "**Error** Missing Entry!");

}

else

eProvider->SetError(tbPword, "");

}

};

}

Figure 10-12 shows what ErrorProviderEx.exe looks like when you execute it.

Figure 10-12. The ErrorProvider control

NotifyIcon

If you’ve tried to add an icon to the notification area in your past life, you know that it wasn’t a simple task. Well, with the .NET Framework, it is. All it takes is a drag and drop of the NotifyIcon control from the Toolbox view to the Design view.

The NotifyIcon control also provides four properties that you’ll probably change:

Icon is an Icon object that represents the icon to display on the notification area. The default is null, which causes no icon to be displayed. (Why someone would do this, I’m not sure.)

Text is a String that represents the ToolTip text to be displayed when the mouse pauses over the icon in the notification area. The default is null, which causes no text to be displayed.

ContextMenu is a ContentMenu object that represents a pop-up menu displayed when the icon is right-clicked. The default is null, which causes no menu to be displayed. (I cover ContentMenus earlier in this chapter.)

Visible is a Boolean that represents whether the icon is displayed in the notification area. The default is true, which displays the icon.

Listing 10-11 shows the NotifyIcon control in action. To give the example some life, I added two buttons. The first toggles the icon in the notification area, and the second toggles the program display in the taskbar. When you write your own program, you may want to display either in the notification area or in the taskbar, but not in both. I also added a context menu so that you can exit the application if you happen to minimize the application while the taskbar icon is turned off.

C H A P T E R 1 0 A D V A N C E D W I N D O W S F O R M S A P P L I C A T I O N S

431

Listing 10-11. The NotifyIcon Control

namespace

NotifyIconEx

{

 

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();

}

protected:

~Form1()

{

if (components)

{

delete components;

}

}

private:

System::Windows::Forms::Button^ bnTaskBar; System::Windows::Forms::Button^ bnNotify; System::Windows::Forms::NotifyIcon^ notifyIcon; System::Windows::Forms::ContextMenuStrip^ menuExit; System::Windows::Forms::ToolStripMenuItem^ miExit; System::ComponentModel::IContainer^ components;

#pragma region Windows Form Designer generated code

void InitializeComponent(void)

{

this->components = (gcnew System::ComponentModel::Container()); System::ComponentModel::ComponentResourceManager^ resources =

(gcnew System::ComponentModel::ComponentResourceManager(Form1::typeid)); this->bnTaskBar = (gcnew System::Windows::Forms::Button()); this->bnNotify = (gcnew System::Windows::Forms::Button()); this->notifyIcon =

(gcnew System::Windows::Forms::NotifyIcon(this->components)); this->menuExit =

(gcnew System::Windows::Forms::ContextMenuStrip(this->components)); this->miExit = (gcnew System::Windows::Forms::ToolStripMenuItem()); this->menuExit->SuspendLayout();

this->SuspendLayout();

432 C H A P T E R 1 0 A D V A N C E D W I N D O W S F O R M S A P P L I C A T I O N S

//

//bnTaskBar

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

this->bnTaskBar->Size = System::Drawing::Size(131, 23); this->bnTaskBar->TabIndex = 3;

this->bnTaskBar->Text = L"Toggle TaskBar Icon"; this->bnTaskBar->Click +=

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

//bnNotify

//

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

this->bnNotify->Size = System::Drawing::Size(131, 23); this->bnNotify->TabIndex = 2;

this->bnNotify->Text = L"Toggle Notify Icon"; this->bnNotify->Click +=

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

//

//notifyIcon

this->notifyIcon->ContextMenuStrip = this->menuExit; this->notifyIcon->Icon = (cli::safe_cast<System::Drawing::Icon^>

(resources->GetObject(L"notifyIcon.Icon"))); this->notifyIcon->Text = L"Notify Icon Example";

this->notifyIcon->Visible = true;

//menuExit

//

this->menuExit->Items->AddRange(

gcnew cli::array< System::Windows::Forms::ToolStripItem^>(1) {this->miExit});

this->menuExit->Name = L"miExit"; this->menuExit->RightToLeft =

System::Windows::Forms::RightToLeft::No; this->menuExit->Size = System::Drawing::Size(153, 48);

//

//miExit

this->miExit->Name = L"miExit";

this->miExit->Size = System::Drawing::Size(152, 22); this->miExit->Text = L"E&xit";

this->miExit->Click +=

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

//Form1

//

C H A P T E R 1 0 A D V A N C E D W I N D O W S F O R M S A P P L I C A T I O N S

433

this->AutoScaleDimensions = System::Drawing::SizeF(6, 13); this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font; this->ClientSize = System::Drawing::Size(192, 106); this->Controls->Add(this->bnTaskBar); this->Controls->Add(this->bnNotify);

this->Icon = (cli::safe_cast<System::Drawing::Icon^> (resources->GetObject(L"$this.Icon")));

this->Name = L"Form1"; this->Text = L"Notify Icon";

this->menuExit->ResumeLayout(false); this->ResumeLayout(false);

}

#pragma endregion

private:

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

{

notifyIcon->Visible = !notifyIcon->Visible;

}

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

{

this->ShowInTaskbar = ! this->ShowInTaskbar;

}

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

{

Application::Exit();

}

};

}

There really isn’t much to the preceding code, and building it is a snap (or a few drags and drops, to be more accurate). You simply drag the NotifyIcon and two buttons to the form and change a few properties. Then you add the events to toggle the icon and taskbar entry.

Coding the context menu is only slightly more complex, but I covered that earlier.

You change the program’s icon and the NotifyIcon’s icon in the exact same way. Just doubleclick the app.ico in the Resource folder of Solution Explorer. This brings up a paint editor on which you can draw your icon.

Tip Within an icon file are multiple icons of different sizes. Remember to change all the different sizes or you will get mismatching icons when the system uses icons of different sizes. (To switch to an icon of a different size, rightclick in the graphic Design view, outside of your icon drawing area, and select the Current Icon Image Types menu item. Then select the submenu item for the icon size you want to edit.)

Figure 10-13 shows what NotifyIconEx.exe looks like when you execute it.

434 C H A P T E R 1 0 A D V A N C E D W I N D O W S F O R M S A P P L I C A T I O N S

Figure 10-13. The NotifyIcon control

Dialog Boxes

First things first: Dialog boxes are just Forms that are called or started differently and can, if you want, pass and/or return data and return a DialogResult. That’s it! Forget what you once knew about dialog boxes (if you were a classic Visual C++ MFC programmer)—things have gotten a lot easier.

Everything that you’ve learned so far in this chapter works the same for dialog boxes. All you need to do is learn a couple of optional features and how to call the dialog box itself, and then you’ll know all you need to develop dialog boxes.

Custom Dialog Boxes

Building a custom dialog box is almost exactly the same as creating the main Win Form, except it requires two additional steps. Here are the steps you follow to create a custom dialog box:

1.Right-click the project folder within Solution Explorer.

2.Select Add New Item from the drop-down menu item Add. A dialog box similar to the one in Figure 10-14 appears.

Figure 10-14. The Add New Item dialog box

C H A P T E R 1 0 A D V A N C E D W I N D O W S F O R M S A P P L I C A T I O N S

435

3.Select the Windows Form (.NET) icon from the Templates panel and give the dialog box a name. I used MyDialog.

4.Click Open. This will provide you with an empty form in the Design view.

5.Build the form exactly as you do the main form.

You can now work with this form in exactly the same way as you do with the application’s main form, except for a couple of minor things.

The first minor difference is that if you want to pass information to the dialog box or get information back from the dialog box, you need to add properties to your form to get and set the information:

public:

property String^ PassedValue1; // Trival

// or

Property String^ PassedValue2

{

void set(String^ value)

{

tbPassedValue->Text = value;

}

String^ get()

{

return tbPassedValue->Text;

}

}

Another method of doing this would be to change the constructor to send data to the dialog box, but I prefer properties. Plus, if you use the constructor to pass data to the dialog box, you still need to create properties or methods to send data back, so why not bite the bullet and use properties in both cases? This method is clean and safe (because you can verify the validity of the passed data) and it’s easy to use.

The second change that you can make, which is totally optional, is to change the style of the dialog box to look more like a dialog box and less like a form:

this->FormBorderStyle = System::Windows::Forms::FormBorderStyle::FixedToolWindow;

// Or this->FormBorderStyle =

System::Windows::Forms::FormBorderStyle::SizableToolWindow;

The third difference is that you want to have any buttons that close your dialog box return a DialogResult. The .NET Framework class library provides a number of possible DialogResults (see Table 10-2).

Table 10-2. DialogResults

Type

Description

Abort

Returns the value Abort. Usually you will have a button labeled Abort to

 

handle this.

Cancel

Returns the value Cancel. This is the value returned when the Esc key is pressed (if

 

enabled) or the close dialog box button is clicked. Also, you will have a button on

 

the form labeled Cancel.

436 C H A P T E R 1 0 A D V A N C E D W I N D O W S F O R M S A P P L I C A T I O N S

Table 10-2. DialogResults (Continued)

Type

Description

Ignore

Returns the value Ignore. Usually you will have a button labeled Ignore to

 

handle this.

No

Returns the value No. Usually you will have a button labeled No to handle this.

None

Returns nothing. You will use this with a modal dialog box, which is discussed later

 

in this section.

OK

Returns the value OK. This is the value returned when the Enter key is pressed (if

 

enabled). Also, you will have a button on the form labeled OK.

Retry

Returns the value Retry. Usually you will have a button labeled Retry to

 

handle this.

Yes

Returns the value Yes. Usually you will have a button labeled Yes to handle this.

 

 

To return a DialogResult value to the calling form, you need to assign to the button that will end the dialog the desired DialogResult value:

bnOK->DialogResult = DialogResult::OK;

When the button is clicked, it will automatically return the DialogResult it was set to (DialogResult::OK is set in the preceding code). By the way, you can still handle the Click event, if you need to, for the button. (You can even change its DialogResult in the handler if you really want to. For example, you could turn DialogResult::OK into DialogResult::Cancel if no text is entered in the dialog box.)

The final change you are probably going to want to make is to assign default buttons to respond to the Accept and Cancel conditions. You do this by assigning a button to the form’s AcceptButton and CancelButton properties:

AcceptButton = bnOK;

CancelButton = bnCancel;

Once you have performed the preceding additional steps, you have a complete custom dialog box. Listing 10-12 shows the code of a custom dialog box that takes in some text, places it in a text box, allows it to be updated, and then returns the updated text to the calling form. The dialog box also allows the user to abort or cancel the dialog box.

Listing 10-12. The MyDialog.h File

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 1 0 A D V A N C E D W I N D O W S F O R M S A P P L I C A T I O N S

437

namespace CustomDialog

{

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

{

public:

MyDialog(void)

{

InitializeComponent();

}

protected:

~MyDialog()

{

if (components)

{

delete components;

}

}

public:

property String^ PassedValue // PassedValue property

{

void set(String ^value)

{

tbPassedValue->Text = value;

}

String ^get()

{

return tbPassedValue->Text;

}

}

private:

System::Windows::Forms::Button^ bnCancel; System::Windows::Forms::Button^ bnAbort; System::Windows::Forms::Button^ bnOK; System::Windows::Forms::TextBox^ tbPassedValue; System::ComponentModel::Container ^components;

#pragma region Windows Form Designer generated code

void InitializeComponent(void)

{

this->bnCancel = (gcnew System::Windows::Forms::Button()); this->bnAbort = (gcnew System::Windows::Forms::Button()); this->bnOK = (gcnew System::Windows::Forms::Button()); this->tbPassedValue = (gcnew System::Windows::Forms::TextBox()); this->SuspendLayout();