使用ComboBox控件对ListView控件中的数据进行编辑
2007-09-19 21:27
579 查看
by jingzhongrong
在默认状态下,ListView控件的编辑功能是通过提供一个类似Edit控件的栏来实现的。但是如果你想让界面更加友好或者希望使用其他类型的控件来编辑数据,以提高操作的便利性。如下图所示,我们利用一个ComboBox控件来让用户以选择的方式来编辑数据。
在上述图片中,使用ComboBox控件进行选择,选中的项目可以直接对ListView中的“插件状态”栏进行修改。其中还涉及对ComboBox控件和ListView控件的自绘,不属于此文所要描述的范围,略过这部分的代码以及实现。如果需要了解有关控件自绘的信息,可以自行到网上搜索。此文的编译环境是C++Builder 2007。
下面具体说明实现的方法。首先添加ListView控件以及ComboBox控件到程序中,并设置ComboBox控件的Visible属性默认为false。
1、每当用户单击ListView控件时,我们应该获取鼠标此时单击的位置,并根据位置计算出所在行以及所在的列(如上图,ComboBox出现在第二列中,只有当鼠标单击的位置在ListView第二列中才会出现ComboBox让用户进行选择)。
判断用户单击的行及列使用如下代码:
2、此时我们已经判断得出鼠标单击的位置是否应该显示出ComboBox控件。下面我们继续进行判断,此时我们应该考虑到这个列可能处于完全不可见的状态或者部分可见的状态,我们应该调整ComboBox的位置以及大小之后才能显示出来。
上述步骤中变量ClickedItem便是用于保存ComboBox应该的大小以及位置。我们根据下面的代码对ClickedItem进行修正。
3、此时的ClickedItem已经保存ComboBox应该出现的位置,我们下面显示出ComboBox来。
4、至此,我们已经将ComboBox控件显示出来。下面我们处理ComboBox进行选择。在ComboBox控件的OnChange事件中添加如下代码。
5、继续处理ComboBox控件,在OnExit事件中添加代码,隐藏ComboBox控件。
6、OnKeyPress事件对Esc键以及Enter键进行处理
7、在最后,我们应该对WM_VSCROLL和WM_HSCROLL两个消息进行处理。这两个消息会在用户垂直或者水平滚动ListView控件时引发。因为我们的ComboBox实际上并非ListView控件的一部分,因此,ComboBox控件并不会随着ListView控件的滚动而滚动。所以我们在这两个消息引发时将ComboBox控件隐藏起来。我们可以有几种方法来实现。可以继承TListView控件,然后对WndProc进行重载,然后在WndProc函数中过滤掉这两个消息。
下面我采用的是另外一种方法,需要在窗体OnCreate事件中加入以下代码:
相应的在头文件中增加以下代码:
下面是MyListViewWindowProc函数的实现
通过上述步骤,可以基本上可以实现使用ComboBox控件对ListView控件的项进行编辑。
By jingzhongrong 2007-9-19
在默认状态下,ListView控件的编辑功能是通过提供一个类似Edit控件的栏来实现的。但是如果你想让界面更加友好或者希望使用其他类型的控件来编辑数据,以提高操作的便利性。如下图所示,我们利用一个ComboBox控件来让用户以选择的方式来编辑数据。
在上述图片中,使用ComboBox控件进行选择,选中的项目可以直接对ListView中的“插件状态”栏进行修改。其中还涉及对ComboBox控件和ListView控件的自绘,不属于此文所要描述的范围,略过这部分的代码以及实现。如果需要了解有关控件自绘的信息,可以自行到网上搜索。此文的编译环境是C++Builder 2007。
下面具体说明实现的方法。首先添加ListView控件以及ComboBox控件到程序中,并设置ComboBox控件的Visible属性默认为false。
1、每当用户单击ListView控件时,我们应该获取鼠标此时单击的位置,并根据位置计算出所在行以及所在的列(如上图,ComboBox出现在第二列中,只有当鼠标单击的位置在ListView第二列中才会出现ComboBox让用户进行选择)。
判断用户单击的行及列使用如下代码:
//在ListView控件的OnMouseUp事件中添加如下代码 TListView *listview = (TListView*)Sender; TListItem *lv = listview->GetItemAt(X,Y); if(lv) //如果选中一项 { TPoint p(X,Y); TRect ClickedItem = lv->DisplayRect(drBounds); //获取选择的项目的边框 TRect rct(ClickedItem); int CellLeft = rct.Left, CellIndex = 0; //下面计算鼠标单击的位置处在哪一列中 for(int x = 0; x < listview->Columns->Count; x++) { rct.Left = CellLeft; rct.Right = CellLeft + listview->Column[x]->Width; if(PtInRect(rct,p)) //鼠标单击位置在x+1列中 { CellIndex = x + 1; break; } CellLeft += listview->Column[x]->Width; } //检查鼠标点击位置是否位于"插件状态"一列中(对应上图实现) if(CellIndex != 2) return; else //处于“插件状态”列中 { … //暂时省略此处代码 } } |
上述步骤中变量ClickedItem便是用于保存ComboBox应该的大小以及位置。我们根据下面的代码对ClickedItem进行修正。
//检查数据行是否已经完全滚动至左侧之外 if((ClickedItem.Left + listview->Column[0]->Width + listview->Column[1]->Width) < 0) return; //单元格在左侧之外无法看到不做处理 // //检查数据行是否部分被滚动至左侧之外 //By jingzhongrong else if(ClickedItem.Left + listview->Column[0]->Width < 0) { //检查此数据行是否已延伸至ListView的右侧之外 if((ClickedItem.Left + listview->Column[1]->Width + listview->Column[0]->Width) > listview->Width) { //将数据行(ComboBox)的宽度设置成ListView的宽度 ClickedItem.Left = 0; ClickedItem.Right = ClickedItem.Left + listview->Width; } else { //单元格的右侧位于视图之中 ClickedItem.Right = ClickedItem.Left + listview->Column[0]->Width + listview->Column[1]->Width; ClickedItem.Left = 0; } } //检查数据行是否已经完全滚动至右侧之外 else if(ClickedItem.Left + listview->Column[0]->Width > listview->Width) return; //单元格在右侧之外无法看到不做处理 //数据行被部分滚动至右侧之外 else if(listview->Column[1]->Width + listview->Column[0]->Width > listview->Width) { ClickedItem.Left += listview->Column[0]->Width; ClickedItem.Right = listview->Width - ClickedItem.Left; } else { ClickedItem.Left = listview->Column[0]->Width; ClickedItem.Right = listview->Column[1]->Width; } //进行调整 ClickedItem.Left += listview->Left; ClickedItem.Top += 25; //Columns Height ClickedItem.Right += ClickedItem.Left; |
this->ComboBox1->Top = ClickedItem.Top; this->ComboBox1->Left = ClickedItem.Left; this->ComboBox1->Width = ClickedItem.Width(); //对ComboBox显示的文本进行设置 //ComboBox应在初始化时添加选择项并将其Style属性设置为csDropDownList用来限制 //用户的选择 if(lv->SubItems->Strings[0] == "启用") this->ComboBox1->ItemIndex = 0; else this->ComboBox1->ItemIndex = 1; //By jingzhongrong this->ComboBox1->Visible = true; this->ComboBox1->BringToFront(); this->ComboBox1->SetFocus(); |
AnsiString str = this->ListView1->Selected->SubItems->Strings[0]; this->ListView1->Selected->SubItems->Strings[0] = ComboBox1->Text; ComboBox1->Visible = false; //判断ComboBox选择前后是否有更改过 if(str != ComboBox1->Text && ComboBox1->Text == "启用") { this->LoadPlugin(…); //加载插件 } else if(str != ComboBox1->Text && ComboBox1->Text == "禁用") { this->LoadPlugin(…); //卸载插件 } |
AnsiString str = this->ListView1->Selected->SubItems->Strings[0]; if(str == "") { ComboBox1->Visible = false; } else { this->ListView1->Selected->SubItems->Strings[0] = ComboBox1->Text; ComboBox1->Visible = false; if(str != ComboBox1->Text && ComboBox1->Text == "启用") { this->LoadPlugin(); //load } else if(str != ComboBox1->Text && ComboBox1->Text == "禁用") { this->LoadPlugin(); //unload } } this->ListView1->SetFocus(); |
switch(Key) { case VK_ESCAPE: //其他处理,此处省略 //… this->ComboBox1->Visible = false; this->ListView1->SetFocus(); break; case VK_RETURN: this->ComboBox1->Visible = false; this->ListView1->SetFocus(); break; } |
下面我采用的是另外一种方法,需要在窗体OnCreate事件中加入以下代码:
OldListViewWindowProc = ListView1->WindowProc; ListView1->WindowProc = MyListViewWindowProc; |
TWndMethod OldListViewWindowProc; void __fastcall MyListViewWindowProc(TMessage &Message); |
if(Message.Msg == WM_VSCROLL || Message.Msg == WM_HSCROLL) { ListView1->SetFocus(); } OldListViewWindowProc(Message); //调用默认的处理函数处理其他消息 |
By jingzhongrong 2007-9-19
相关文章推荐
- 如何使用 ComboBox 控件来编辑 Visual C# 中 ListView 控件中数据
- winform有一个combobox和一个textbox控件,如何进行动态绑定,使得combobox中的数据改变时,textbox中的数据也随之改变?
- 使用Repeater控件进行数据访问的综合实例
- 使用objectdatasource结合数据绑定控件进行简单三层架构的开发
- Mater-Details数据查询修改时,在用DetailsView进行新建,编辑(添加DropDownList控件)应用时需要注意的几点问题
- 不使用GridView自带编辑删除等等按钮,放置服务器控件的按钮。获取点击按钮的当前行以便进行编辑删除
- 使用objectdatasource结合数据绑定控件进行简单三层架构的开发
- 使用DataList控件进行数据访问的综合实例
- 使用objectdatasource结合数据绑定控件进行简单三层架构的开发
- 在Gridview控件中点击编辑链接,把这一行数据传给编辑界面进行修改
- 使用“捕捉”地理处理工具进行数据的自动编辑
- 使用objectdatasource结合数据绑定控件进行简单三层架构的开发
- 回发或回调参数无效。在配置中使用 或在页面中使用 启用了事件验证。出于安全目的,此功能验证回发或回调事件的参数是否来源于最初呈现这些事件的服务器控件。如果数据有效并且是预期的,则使用 ClientScriptManager.RegisterForEventValidation 方法来注册回发或回调数据以进行验证。
- 使用objectdatasource结合数据绑定控件进行简单三层架构的开发
- easyUI下拉框控件easyui-combobox使用后台json文件填充数据失败的问题
- 使用telerik combobox控件显示数据
- Devexpress 使用comboBoxEdit 和LookUpEditor 控件数据绑定
- 在Gridview控件中点击编辑链接,把这一行数据传给编辑界面进行修改
- 回发或回调参数无效。在配置中使用 或在页面中使用 启用了事件验证。出于安全目的,此功能验证回发或回调事件的参数是否来源于最初呈现这些事件的服务器控件。如果数据有效并且是预期的,则使用 ClientScriptManager.RegisterForEventValidation 方法来注册回发或回调数据以进行验证。
- C# 程序中如何向(DEV)ComboBoxEdit控件中添加下拉列表的值不使用数据绑定,就是使用代码添加