【MFC】CListCtrl,多选后删除,整个程序关闭,也不提示异常,找不到问题,求助!

张天星 2017-05-31 11:36:38
【MFC】CListCtrl,多选后删除,整个程序关闭,也不提示异常,找不到问题,求助!

void C天星定时器Dlg::OnBnClickedDel()
{

POSITION pos = pList.GetFirstSelectedItemPosition(); //pos选中的首行位置
if (pos == NULL)
AfxMessageBox(_T("没有选中任何行!"));
else
{
while (pos) //如果选择多行
{
int nIdx = -1;
nIdx = pList.GetNextSelectedItem(pos);

if (nIdx >= 0 && nIdx<pList.GetItemCount())
{
pList.DeleteItem(nIdx);
}
}
}
return;
}//到这里异常退出,调试转到cmdtarg.cpp


这个是删除事件中的内容,感觉这个事件没有问题啊……但调试过程中,运行到最后一个大括号,直接进入cmdtarg.cpp

AFX_STATIC BOOL AFXAPI _AfxDispatchCmdMsg(CCmdTarget* pTarget, UINT nID, int nCode,
AFX_PMSG pfn, void* pExtra, UINT_PTR nSig, AFX_CMDHANDLERINFO* pHandlerInfo)
// return TRUE to stop routing
{
ENSURE_VALID(pTarget);
UNUSED(nCode); // unused in release builds

union MessageMapFunctions mmf;
mmf.pfn = pfn;
BOOL bResult = TRUE; // default is ok

if (pHandlerInfo != NULL)
{
// just fill in the information, don't do it
pHandlerInfo->pTarget = pTarget;
pHandlerInfo->pmf = mmf.pfn;
return TRUE;
}

switch (nSig)
{
default: // illegal
ASSERT(FALSE);
return 0;
break;

case AfxSigCmd_v:
// normal command or control notification
ASSERT(CN_COMMAND == 0); // CN_COMMAND same as BN_CLICKED
ASSERT(pExtra == NULL);
(pTarget->*mmf.pfnCmd_v_v)();//…………………………………………………………………………刚才删除那里结束之后,调试就直接跳到这一步了。
break;



…………
…………
下面贴上我所有的代码:

天星定时器Dlg.cpp

// 天星定时器Dlg.cpp : 实现文件
//

#include "stdafx.h"
#include "天星定时器.h"
#include "天星定时器Dlg.h"
#include "afxdialogex.h"
#include "DATADlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// C天星定时器Dlg 对话框



C天星定时器Dlg::C天星定时器Dlg(CWnd* pParent /*=NULL*/)
: CDialogEx(IDD_MY_DIALOG, pParent)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void C天星定时器Dlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
DDX_Control(pDX, IDC_LIST, pList);
}

BEGIN_MESSAGE_MAP(C天星定时器Dlg, CDialogEx)
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_NEW, &C天星定时器Dlg::OnBnClickedNew)
ON_WM_TIMER()
ON_WM_CLOSE()
ON_BN_CLICKED(IDC_MOD, &C天星定时器Dlg::OnBnClickedMod)
ON_BN_CLICKED(IDC_DEL, &C天星定时器Dlg::OnBnClickedDel)
END_MESSAGE_MAP()


// C天星定时器Dlg 消息处理程序

BOOL C天星定时器Dlg::OnInitDialog()
{
CDialogEx::OnInitDialog();

// 设置此对话框的图标。 当应用程序主窗口不是对话框时,框架将自动
// 执行此操作
SetIcon(m_hIcon, TRUE); // 设置大图标
SetIcon(m_hIcon, FALSE); // 设置小图标

// TODO: 在此添加额外的初始化代码

pList.InsertColumn(0, _T("剩余时间"), LVCFMT_LEFT, 90);
pList.InsertColumn(1, _T("目标时间"), LVCFMT_LEFT, 150);
pList.InsertColumn(2, _T("重复周期"), LVCFMT_LEFT, 100);
pList.InsertColumn(3, _T("备注提醒"), LVCFMT_LEFT,400);

Load();


return TRUE; // 除非将焦点设置到控件,否则返回 TRUE
}

// 如果向对话框添加最小化按钮,则需要下面的代码
// 来绘制该图标。 对于使用文档/视图模型的 MFC 应用程序,
// 这将由框架自动完成。

void C天星定时器Dlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // 用于绘制的设备上下文

SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

// 使图标在工作区矩形中居中
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;

// 绘制图标
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialogEx::OnPaint();
}
}

//当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR C天星定时器Dlg::OnQueryDragIcon()
{
return static_cast<HCURSOR>(m_hIcon);
}



void C天星定时器Dlg::OnBnClickedNew()
{
DATADlg newdata;
newdata.DoModal();
data1tolist();
}


void C天星定时器Dlg::OnTimer(UINT_PTR 行)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
COleDateTime 当前时间,目标时间;
COleDateTimeSpan 剩余时间;
CString str;
当前时间 = COleDateTime::GetCurrentTime();
目标时间.ParseDateTime(pList.GetItemText(行,1));
剩余时间 = 目标时间 - 当前时间;
if (剩余时间.GetDays() > 0 )
str.Format(_T("%d日"), 剩余时间.GetDays());
else
str = "";
str = str+剩余时间.Format(_T("%H:%M:%S"));
pList.SetItemText(行, 0, str);
if (data1.提醒时间<当前时间)
{
KillTimer(行);
}
CDialogEx::OnTimer(行);
}


void C天星定时器Dlg::Load()
{
CFile file;
int i = file.Open(_T(".天星定时器配置.zzw"), CFile::modeRead);
if (!i)
{
return;
}
while (file.Read(&data1, sizeof(data1))==sizeof(data1))
{
data1tolist();
}
file.Close();
}

void C天星定时器Dlg::listTOdata1(int i)
{

CString str;
TCHAR c[200];
pList.GetItemText(i, 3, data1.提醒内容, sizeof(data1.提醒内容));
pList.GetItemText(i, 1, c, sizeof(c));
data1.提醒时间.ParseDateTime(c);
pList.GetItemText(i, 2, c, sizeof(c));
str = c;
if (c == _T("不重复"))
_tcscpy(data1.重复类型, _T("不重复"));
else if (_T('周') == c[1])
{
_tcscpy(data1.重复类型, _T("按周重复"));
_tcscpy(data1.重复周期, str.Mid(2, 3));

}
else
{
TCHAR d[10];
int i = str.Find(_T("重复")), j = str.GetLength();
_tcscpy(d, str.Mid(i - 1, 1));
if (_T('日') == d[0])
_tcscpy(data1.重复类型, _T("按日重复"));
else if (_T('月') == d[0])
_tcscpy(data1.重复类型, _T("按月重复"));
else if (_T('年') == d[0])
_tcscpy(data1.重复类型, _T("按年重复"));
_tcscpy(data1.重复周期, str.Mid(1, j - 4));

}
return;
}

void C天星定时器Dlg::zzwSave()
{
CFile file;
int i = file.Open(_T(".天星定时器配置.zzw"), CFile::modeCreate | CFile::modeWrite);
if (!i)
{
AfxMessageBox(_T("保存文件的时候失败!"));
}
i = 0;
int sCount = pList.GetItemCount();
while (i<sCount)
{
listTOdata1(i);
file.Write(&data1, sizeof(data1));
i++;
}
file.Close();
}

void C天星定时器Dlg::data1tolist()
{
COleDateTime 当前时间, 剩余时间;
CString str, Text;
//SYSTEMTIME sys_time;
//当前时间.GetAsSystemTime(sys_time);
当前时间 = COleDateTime::GetCurrentTime();
int 行 = pList.GetItemCount();
//剩余时间
剩余时间 = data1.提醒时间 - 当前时间;
str = 剩余时间.Format();
pList.InsertItem(行, str);
//目标时间
str = data1.提醒时间.Format();
pList.SetItemText(行, 1, str);
str.Format(data1.重复周期);
Text.Format(data1.重复类型);
if (Text == _T("不重复"))
str = Text;
else if (Text == _T("按日重复"))
Text = _T("每") + str + _T("日重复");
else if (Text == _T("按周重复"))
Text = _T("每周") + str + _T("重复");
else if (Text == _T("按月重复"))
Text = _T("每") + str + _T("月重复");
else if (Text == _T("按年重复"))
Text = _T("每") + str + _T("年重复");
else if (Text == _T("按自定义重复"))
Text = _T("每") + str + _T("日重复");
pList.SetItemText(行, 2, Text);
pList.SetItemText(行, 3, data1.提醒内容);
SetTimer(行, 1000, NULL);
}

void C天星定时器Dlg::OnClose()
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
zzwSave();

CDialogEx::OnClose();
}


void C天星定时器Dlg::OnBnClickedMod()
{

// TODO: 在此添加控件通知处理程序代码
}


void C天星定时器Dlg::OnBnClickedDel()
{

POSITION pos = pList.GetFirstSelectedItemPosition(); //pos选中的首行位置
if (pos == NULL)
AfxMessageBox(_T("没有选中任何行!"));
else
{
while (pos) //如果选择多行
{
int nIdx = -1;
nIdx = pList.GetNextSelectedItem(pos);

if (nIdx >= 0 && nIdx<pList.GetItemCount())
{
pList.DeleteItem(nIdx);
}
}
}
return;
}
...全文
254 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
Nosoft12345 2017-06-07
  • 打赏
  • 举报
回复
删除一个没有的节点,肯定会异常。
xiaohuh421 2017-06-05
  • 打赏
  • 举报
回复
while (pos) //如果选择多行 { int nIdx = -1; nIdx = pList.GetNextSelectedItem(pos); if (nIdx >= 0 && nIdx<pList.GetItemCount()) { pList.DeleteItem(nIdx); } } 这样删除是错误的. 因为, 当你删除一个后, 再你GetNextSelectedItem得到的索引已经是错误的了. 正确的做法是, 在循环中, 每次都用GetFirstSelectedItemPosition, 重新定位.
hurryboylqs 2017-06-04
  • 打赏
  • 举报
回复
点【结贴】,然后给除你外的其他分数,直到该贴分数减少到0才可以结贴。
张天星 2017-06-03
  • 打赏
  • 举报
回复
我问题已经想办法解决了,现在就一个疑问,那个问题点数是什么意思,是类似问答的悬赏么?为什么我没有选中答案的选项?? 这个询问怎么关闭……
schlafenhamster 2017-06-03
  • 打赏
  • 举报
回复
参考

//节箍删除
void CMACReport::OnBnClickedButton2()
{
	// TODO: 在此添加控件通知处理程序代码
	int npos;
	POSITION pos=NodeList.GetFirstSelectedItemPosition();
	if (pos==NULL)
	{
		MessageBox("请选择要删除的行");
		return;
	}
	npos=(int)NodeList.GetNextSelectedItem(pos);
	NodeList.DeleteItem(npos);//	删除选中行	
	Combination();//删除行后面各行重新排列
}

//对增加、删除后的节箍列表重新排列
void CMACReport::Combination()
{
	//CArray<LIST,LIST> newItem;//存放列表中新的数据
	newItem.RemoveAll();
	LIST tmpList;
	int ncount=NodeList.GetItemCount();//获取行数
	for ( int i=0;i<ncount;i++)
	{
		for (int j=0;j<4;j++)
		{
			CString tempstr=NodeList.GetItemText(i,j);
			tmpList.nlistStr[j]=tempstr;
		}
		newItem.Add(tmpList);	
	}
  //重新排列
	NodeList.DeleteAllItems();
	CString indexstr;
	LIST  newlist;
	for (int i=0;i<ncount;i++)
	{
		newlist=newItem.GetAt(i);	  
		indexstr.Format("%d",i);
		int n= NodeList.InsertItem(i,indexstr);
		NodeList.SetItemText(n,1,newlist.nlistStr[1]);//添加起始深度信息
		NodeList.SetItemText(n,2,newlist.nlistStr[2]);//添加终止深度信息
		NodeList.SetItemText(n,3,newlist.nlistStr[3]);//添加套管长度信息

	}
}
jacksonfan 2017-06-02
  • 打赏
  • 举报
回复
倒着删除,先删除选中的最后一个
张天星 2017-06-02
  • 打赏
  • 举报
回复
引用 2 楼 zgl7903 的回复:
正常的列表删除后, 后面的索引也会往前移动,如果仍然使用原来的索引可能会导致范围越界 建议从尾端开始,向前逐个删除
我知道逻辑不对,后来修改了,可是改了之后还是闪退。 甚至我改成这样都还是闪退:

void C天星定时器Dlg::OnBnClickedDel()
{
	pList.DeleteItem(0);
	// TODO: 在此添加控件通知处理程序代码
}
张天星 2017-06-02
  • 打赏
  • 举报
回复
引用 1 楼 jason_wentzel 的回复:
删除逻辑不对,删除一个节点时,序号就已经变了,你要删除的时候只能从序号最大的开始,往小序号删除
我知道逻辑不对,后来修改了,可是改了之后还是闪退。 甚至我改成这样都还是闪退:

void C天星定时器Dlg::OnBnClickedDel()
{
	pList.DeleteItem(0);
	// TODO: 在此添加控件通知处理程序代码
}
zgl7903 2017-06-01
  • 打赏
  • 举报
回复
正常的列表删除后, 后面的索引也会往前移动,如果仍然使用原来的索引可能会导致范围越界 建议从尾端开始,向前逐个删除
孤客天涯 2017-06-01
  • 打赏
  • 举报
回复
删除逻辑不对,删除一个节点时,序号就已经变了,你要删除的时候只能从序号最大的开始,往小序号删除

16,472

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧