void CMFCConnectSqlDlg::OnRclickLISTData(NMHDR* pNMHDR, LRESULT* pResult)
{
CMFCConnectSqlDlg CSqlDlga; // ❌ 錯誤:重新建構一個全新的對話框物件
int nSelRows = CSqlDlga.m_List_Value.GetSelectedCount(); // 操作的是新物件的控制項,非當前視窗
// ...
theApp.M_ID = _ttoi(CSqlDlga.m_List_Value.GetItemText(n, 0));
}
Debug Assertion Failed 發生原因:CSqlDlga 是區域變數,其 m_List_Value 未經 SubclassDlgItem 或 DoDataExchange 關聯到真實視窗控制項,操作未初始化的 CListCtrl 觸發斷言。
this 指向當前對話框實例void CMFCConnectSqlDlg::OnRclickLISTData(NMHDR* pNMHDR, LRESULT* pResult)
{
// ✅ 直接使用 this->m_List_Value(或 m_List_Value)
int nSelRows = m_List_Value.GetSelectedCount();
if (nSelRows == 0) return;
POSITION pos = m_List_Value.GetFirstSelectedItemPosition();
while (pos != NULL)
{
int nItem = m_List_Value.GetNextSelectedItem(pos);
CString strText = m_List_Value.GetItemText(nItem, 0); // 第 0 欄
int nID = _ttoi(strText);
theApp.M_ID = nID; // 或儲存至陣列/容器處理多選
}
*pResult = 0;
}
| 錯誤做法 | 正確做法 |
|---|---|
CMFCConnectSqlDlg dlg; dlg.m_List... | this->m_List_Value 或直接 m_List_Value |
忽略 POSITION 迴圈處理多選 | GetFirstSelectedItemPosition + GetNextSelectedItem 迴圈 |
用 GetNextItem(-1, LVNI_SELECTED|LVNI_FOCUSED) 只取單一 | 多選時需迴圈,單選可用 GetNextItem(-1, LVNI_SELECTED) |
直接 _ttoi 轉換可能失敗 | 建議 int nID; if (strText.IsEmpty() || !IsNumeric(strText)) return; nID = _ttoi(strText); |
void CMFCConnectSqlDlg::OnRclickLISTData(NMHDR* pNMHDR, LRESULT* pResult)
{
std::vector selectedIDs;
POSITION pos = m_List_Value.GetFirstSelectedItemPosition();
while (pos)
{
int nItem = m_List_Value.GetNextSelectedItem(pos);
CString txt = m_List_Value.GetItemText(nItem, 0);
if (!txt.IsEmpty())
selectedIDs.push_back(_ttoi(txt));
}
if (!selectedIDs.empty())
{
theApp.M_ID = selectedIDs[0]; // 單一值需求
// 或 theApp.SelectedIDs = selectedIDs; // 多值需求
}
*pResult = 0;
}
CListCtrl::GetItemText 回傳 CString,VC6 下需包含 afxwin.h。OnRclick 中彈出選單,記得 ClientToScreen 轉換滑鼠座標。CListCtrl::GetItemText(int, int, CString&) 參考形式避免臨時物件複製。絕對不要在訊息處理函數中重新建構對話框類別實例。永遠使用 this(隱含或顯式)存取當前視窗的控制項成員變數。配合 POSITION 迴圈正確處理多選情況,即可穩定取得 CListCtrl 選取列的任意欄位資料。