Microsoft KB Archive/816188

= How to use a ComboBox control to edit data in a ListView control in Visual C++ .NET or in Visual C++ 2005 =

Article ID: 816188

Article Last Modified on 12/30/2005

-

APPLIES TO


 * Microsoft Visual C++ 2005 Express Edition
 * Microsoft Visual C++ .NET 2003 Standard Edition

-





For a Microsoft Visual C# .NET version of this article, see 320344.



For a Microsoft Visual Basic .NET version of this article, see 320342.

IN THIS TASK

 * SUMMARY
 * Learn about the technique
 * Create the inherited ListView control
 * Create the sample application
 * Verify that it works



SUMMARY
This step-by-step article describes how to use a ComboBox control to edit the data in a ListView control. This method replaces the standard text box approach of editing the data in a ListView control.

back to the top

Learn about the technique
By using the LabelEdit property of the ListView control, you can allow the user to edit the contents of the ListView control. To edit the data in the ListView control, you can use a standard text box. Occasionally, you may want another control to edit the control. This article describes how to use a ComboBox control to edit the data in a ListView control when the ListView control is in Details view.

When the user selects a row in the ListView control, a calculation is performed to locate the bounding rectangle for the first column of the row that the user clicked. That calculation considers that the column may not be visible or may not be fully visible when the user click the row and when the ComboBox control is sized and is displayed appropriately.

In addition to positioning and sizing the ComboBox control, this sample application also watches for the following two messages on the ListView control:
 * WM_VSCROLL
 * WM_HSCROLL.

These messages occur whenever the user scrolls through the ListView control vertically or horizontally. Because the ComboBox control is not physically part of the ListView control, the ComboBox control does not automatically scroll with the ListView control. Therefore, whenever either one of these two messages occurs, the ComboBox control must be hidden. To watch for these messages, you must create a custom UserControl class that inherits from the ListView class. In this custom control, the WndProc method is overridden to allow all messages to be checked for scrolling.

Note To override the WndProc method, both your code and any code that calls it must have unmanaged code permissions (SecurityPermission with the UnmanagedCode flag specified).

back to the top

Create the inherited ListView control
 Start Microsoft Visual Studio .NET 2003 or Microsoft Visual Studio 2005. On the File menu, point to New, and then click Project. In the New Project dialog box, click Visual C++ Projects under Project Types, and then click Windows Control Library (.NET) under Templates.

Note In Visual Studio 2005, click Visual C++ under Project Types, and then click Windows Forms Control Library under Templates. In the Name box, type MyListView. In the Location box, type C:\Test, and then click OK.  Replace all of the code in the UserControl class with the following code:
 * 1) pragma once

using namespace System; using namespace System::ComponentModel; using namespace System::Collections; using namespace System::Windows::Forms; using namespace System::Data; using namespace System::Drawing;

namespace MyListView {   ///     /// Summary for MyListViewControl ///    ///    /// WARNING: If you change the name of this class, you must change the ///         'Resource File Name' property for the managed resource compiler tool ///         that is associated with all .resx files that this class depends on. ///         Otherwise, the designers cannot interact properly with localized ///         resources that are associated with this form. public __gc class MyListViewControl : public System::Windows::Forms::ListView {      public: MyListViewControl(void) {           InitializeComponent; }   protected: void Dispose(Boolean disposing) {           if (disposing && components) {               components->Dispose; }           __super::Dispose(disposing); }   private: ///        /// Required designer variable. ///        System::ComponentModel::Container* components;

///        /// Required method for Designer support - do not modify /// the contents of this method with the code editor. ///        void InitializeComponent(void) {       }

private: static const int WM_HSCROLL = 0x114; static const int WM_VSCROLL = 0x115;

protected: void WndProc(Message *msg) {           // Look for the WM_VSCROLL or the WM_HSCROLL messages. if ((msg->Msg == WM_VSCROLL) || (msg->Msg == WM_HSCROLL)) {               // Move focus to the ListView control to cause the ComboBox control to lose focus. this->Focus; }           // Pass the message to default handler. __super::WndProc(msg); }    }; }  Note You must add the common language runtime support compiler option (/clr:oldSyntax) in Visual C++ 2005 to successfully compile the whole code sample. To add the common language runtime support compiler option in Visual C++ 2005, follow these steps:  Click Project, and then click  Properties.

Note  is a placeholder for the name of the project.</li> Expand Configuration Properties, and then click General.</li> Click to select Common Language Runtime Support, Old Syntax (/clr:oldSyntax) in the Common Language Runtime support project setting in the right pane, click Apply, and then click OK.</li></ol>

For more information about the common language runtime support compiler option, visit the following Microsoft Web site:

/clr (Common Language Runtime Compilation)

http://msdn2.microsoft.com/en-us/library/k8d11d4s.aspx

</li> Save and build the project.</li></ol>

back to the top

Create the sample application
<ol> Follow these steps to create a new Windows Forms Application in Microsoft Visual C++ .NET: <ol style="list-style-type: lower-alpha;"> On the File menu, point to New, and then click Project.</li> In the New Project dialog box, click Visual C++ Projects under Project Types, and then click Windows Forms Application (.NET) under Templates.

Note In Visual Studio 2005, click Visual C++ under Project Types, and then click Windows Forms Application under Templates.</li> In the Name box, type Q816188, and then click OK. By default, a form that is named Form1 is created.</li></ol> </li> Follow these steps to add the control that you created in the &quot;Create the inherited ListView control&quot; section of this article to your Windows application: <ol style="list-style-type: lower-alpha;"> On the Tools menu, click Add/Remove Toolbox Items.</li> In the Customize Toolbox dialog box, click the .NET Framework Components tab, and then click Browse.</li> In the Open dialog box, locate the control that you created in the &quot;Create the inherited ListView control&quot; section, and then click Open. This step adds this control to the Toolbox so that you can use the control similarly to any other control.</li> Add a MyListView control to Form1.</li></ol> </li> Add a ComboBox control to Form1.</li> In the Properties window of the ComboBox control, set the value of the Name property to cbListViewCombo, and then set the Visible property to False .</li>  Add the following code to the class of Form1 above the constructor: private: ListViewItem *lvItem; </li>  Add the following code to the Load event of Form1: // Add some items to the combo box list. this->cbListViewCombo->Items->Add(S&quot;NC&quot;); this->cbListViewCombo->Items->Add(S&quot;WA&quot;);

// Set the view of the ListView control to Details. this->myListViewControl1->View = View::Details;

// Turn on full row select. this->myListViewControl1->FullRowSelect = true; // Add data to the ListView control. ColumnHeader *columnheader; ListViewItem *listviewitem;

// Create sample ListView data. listviewitem = new ListViewItem(S&quot;NC&quot;); listviewitem->SubItems->Add(S&quot;North Carolina&quot;); this->myListViewControl1->Items->Add(listviewitem);

listviewitem = new ListViewItem(S&quot;WA&quot;); listviewitem->SubItems->Add(S&quot;Washington&quot;); this->myListViewControl1->Items->Add(listviewitem); // Create column headers for the data. columnheader = new ColumnHeader; columnheader->Text = S&quot;State Abbreviation&quot;; this->myListViewControl1->Columns->Add(columnheader);

columnheader = new ColumnHeader; columnheader->Text = S&quot;State&quot;; this->myListViewControl1->Columns->Add(columnheader);

// Loop through and size each column header to fit the column header text. ColumnHeader *ch; IEnumerator *ie = this->myListViewControl1->Columns->GetEnumerator; while (ie->MoveNext) {   ch = __try_cast<ColumnHeader *> (ie->Current); ch->Width = -2; } </li> <li> Add the following code to the SelectedValueChanged event of the ComboBox control: // Set the text of the ListView item to match the ComboBox control. lvItem->Text = this->cbListViewCombo->Text;

// Hide the ComboBox control. this->cbListViewCombo->Visible = false; </li> <li> Add the following code to the Leave event of the ComboBox control: // Set text of the ListView item to match the ComboBox control. lvItem->Text = this->cbListViewCombo->Text;

// Hide the ComboBox control. this->cbListViewCombo->Visible = false; </li> <li> Add the following code to the KeyPress event of the ComboBox control: // Verify that the user presses the ESC key. switch (e->KeyChar) { case (char)(int)Keys::Escape: {   // Reset the original text value, and then hide the ComboBox control. this->cbListViewCombo->Text = lvItem->Text; this->cbListViewCombo->Visible = false; break; } case (char)(int)Keys::Enter: {   // Hide the ComboBox control. this->cbListViewCombo->Visible = false; break; } } </li> <li> Add the following code to the MouseUp event of the myListViewContro11 control: // Get the item on the row that the user clicks. lvItem = this->myListViewControl1->GetItemAt(e->get_X, e->get_Y); // Make sure that an item the user clicks. if (lvItem != NULL) { // Get the bounds of the item that the user clicks. Rectangle ClickedItem = lvItem->Bounds; // Verify that the column is completely scrolled off to the left. if ((ClickedItem.Left + this->myListViewControl1->Columns->get_Item(0)->Width) < 0) { // If the cell is out of view to the left, do nothing. return; } // Verify that the column is partially scrolled off to the left. else if (ClickedItem.Left < 0) { // Determine if the column extends beyond the right side of the ListView control. if ((ClickedItem.Left + this->myListViewControl1->Columns->get_Item(0)->Width) > this->myListViewControl1->Width) { // Set the width of the column to match the width of the ListView control. ClickedItem.Width = this->myListViewControl1->Width; ClickedItem.X = 0; } else { // The right side of the cell is in view. ClickedItem.Width = this->myListViewControl1->Columns->get_Item(0)->Width + ClickedItem.Left; ClickedItem.X = 2; }                 } else if (this->myListViewControl1->Columns->get_Item(0)->Width > this->myListViewControl1->Width) { ClickedItem.Width = this->myListViewControl1->Width; } else { ClickedItem.Width = this->myListViewControl1->Columns->get_Item(0)->Width; ClickedItem.X = 2; }              // Adjust the top to account for the location of the ListView control. ClickedItem.Y += this->myListViewControl1->Top; ClickedItem.X += this->myListViewControl1->Left;

// Assign calculated bounds to the ComboBox control. this->cbListViewCombo->Bounds = ClickedItem; // Set default text for the ComboBox control to match the item that the user clicks. this->cbListViewCombo->Text = lvItem->Text;

// Display the ComboBox control, and then make sure that it is on top with focus. this->cbListViewCombo->Visible = true; this->cbListViewCombo->BringToFront; this->cbListViewCombo->Focus; } </li></ol>

back to the top

Verify that it works

 * 1) Save and then run the sample.
 * 2) Click a row in the ListView control.

Notice that a combo box appears over the location of the first column of the current row.
 * 1) To hide the combo box, click an item in the combo box, press ESC, and then scroll through the ListView control or click another control.

Notice that the value that you clicked in the combo box is placed in the first column of the clicked row of the ListView control.

back to the top

<div class="idea_section">

Keywords: kbhowtomaster kblistview kbwindowsforms kbprogramming kbcombobox kbcode kbcontrol KB816188

-

[mailto:TECHNET@MICROSOFT.COM Send feedback to Microsoft]

© Microsoft Corporation. All rights reserved.