|
-
May 4th, 2008, 12:55 PM
#1
MFC, ListCtrl selection question
Project_Main_Code.cpp
Code:
#include "Project_Main_Header.h"
#include "resource.h"
CMyApp myApp;
BOOL CMyApp::InitInstance()
{
//Create dialog box as the main window
m_pMainWnd = new CMainDialog;
m_pMainWnd->ShowWindow(m_nCmdShow);
m_pMainWnd->UpdateWindow();
return TRUE;
}
BEGIN_MESSAGE_MAP(CMainDialog,CDialog)
//Message Handlers for the button pressed
ON_BN_CLICKED(IDC_BUTTON_EXIT,OnDialogExit)
ON_BN_CLICKED(IDC_BUTTON_ADD,OnAddTask)
ON_BN_CLICKED(IDC_BUTTON_DELETE,OnDeleteTask)
ON_BN_CLICKED(IDC_BUTTON_INSA,OnInsertAbove)
ON_BN_CLICKED(IDC_BUTTON_INSB,OnInsertBelow)
//Message Handler to repaint the dialog box
ON_WM_PAINT()
//Message Handler to check if any changes has been made in Edit Box
ON_EN_CHANGE(IDC_EDIT_TASKTITLEWRITE,OnUpdateEditCtrl)
//Message Handler to check if any selections made in ListCtrl
ON_NOTIFY(LVN_ITEMCHANGED,IDC_LIST_TASK,OnUpdateListCtrl)
END_MESSAGE_MAP()
CMainDialog::CMainDialog()
{
//Constructor to create the dialog box
Create(IDD_MAIN_DIALOG);
}
BOOL CMainDialog::OnInitDialog()
{
CDialog::OnInitDialog();
//Initialization function call for ListCtrl.
OnInitListCtrl();
OnInitCalCtrl();
//Disables the buttons initially
GetDlgItem(IDC_BUTTON_ADD)->EnableWindow(FALSE);
GetDlgItem(IDC_BUTTON_DELETE)->EnableWindow(FALSE);
GetDlgItem(IDC_BUTTON_INSA)->EnableWindow(FALSE);
GetDlgItem(IDC_BUTTON_INSB)->EnableWindow(FALSE);
//Modifies the DWSTYLE. Changes to a window without a system
//close button on Top-Right corner of the dialog box.
ModifyStyle(WS_SYSMENU,0,0);
return TRUE;
}
void CMainDialog::OnInitCalCtrl()
{
//Create a local Month Calendar Control Object
CMonthCalCtrl *l_MonthCalCtrl = (CMonthCalCtrl*)GetDlgItem(IDC_MONTHCALENDAR);
//Set the cursor in the month calendar object to the current date
l_MonthCalCtrl->SetCurSel(COleDateTime::GetCurrentTime());
//Create a local DateTimeCtrl object
CDateTimeCtrl *l_DateTimeCtrl = (CDateTimeCtrl*)GetDlgItem(IDC_DATETIMEPICKER);
//Set the current time in the object
l_DateTimeCtrl->SetTime(COleDateTime::GetCurrentTime());
}
void CMainDialog::OnInitListCtrl()
{
//Retrieve Dialog item for List Ctrl
//And store it in pListCtrl
pListCtrl = (CListCtrl*) GetDlgItem(IDC_LIST_TASK);
//Insert all columns displayed on the list control
pListCtrl->InsertColumn(0,"Start Time",LVCFMT_LEFT,100);
pListCtrl->InsertColumn(1,"Month",LVCFMT_CENTER,100);
pListCtrl->InsertColumn(2,"Date",LVCFMT_CENTER,100);
pListCtrl->InsertColumn(3,"Day",LVCFMT_CENTER,100);
pListCtrl->InsertColumn(4,"Year",LVCFMT_CENTER,100);
pListCtrl->InsertColumn(5,"Title",LVCFMT_CENTER,270);
}
void CMainDialog::DoDataExchange(CDataExchange *pDX)
{
CDialog::DoDataExchange(pDX);
//DoDataExchange functions for the title, monthctrl and time.
DDX_Text(pDX, IDC_EDIT_TASKTITLEWRITE, m_sTitle);
DDX_MonthCalCtrl(pDX,IDC_MONTHCALENDAR,m_cMonth);
DDX_DateTimeCtrl(pDX,IDC_DATETIMEPICKER,m_cTime);
}
void CMainDialog::OnUpdateEditCtrl()
{
//As soon as any changes have been made in the Editbox,
//Enables the add button
GetDlgItem(IDC_BUTTON_ADD)->EnableWindow(TRUE);
}
void CMainDialog::OnUpdateListCtrl(NMHDR * pNotifyStruct, LRESULT * result )
{
UpdateData(FALSE);
//As soon as any selections have been made in the list control,
//Enables the insert above and insert below objects.
GetDlgItem(IDC_BUTTON_INSA)->EnableWindow(TRUE);
GetDlgItem(IDC_BUTTON_INSB)->EnableWindow(TRUE);
//pListCtrl must be retrieved again
//as the variable is modified in the memory
//during run-time of application
//I.E : Code crashes if the item is not retrieved again.
pListCtrl = (CListCtrl*) GetDlgItem(IDC_LIST_TASK);
//Retrieve the index of the item selected (Row #)
int l_nSelected = pListCtrl->GetSelectionMark();
//Concatenate the strings, based on the column entries
CString l_tempStr = pListCtrl->GetItemText(l_nSelected,1)
+ " " + pListCtrl->GetItemText(l_nSelected,2) + " "
+ pListCtrl->GetItemText(l_nSelected,3) + " " +
pListCtrl->GetItemText(l_nSelected,4);
//Set the string in edit control box (Day)
//Object must be fetched again
l_EditBoxDay = (CEdit*) GetDlgItem(IDC_EDIT_TASKDAY);
l_EditBoxDay->SetWindowText(l_tempStr);
//Set the string for the time (Column 0)
l_tempStr = pListCtrl->GetItemText(l_nSelected,0);
//Set the string in edit control box (Time)
l_EditBoxTime = (CEdit*) GetDlgItem(IDC_EDIT_TASKTIME);
l_EditBoxTime->SetWindowText(l_tempStr);
//Set the string for the title
l_tempStr = pListCtrl->GetItemText(l_nSelected,5);
//Set the string in edit control box (Title)
l_EditBoxTitle = (CEdit*) GetDlgItem(IDC_EDIT_TASKTITLEDISP);
l_EditBoxTitle->SetWindowText(l_tempStr);
}
void CMainDialog::OnPaint()
{
//Repaints the client area
CPaintDC dc (this);
}
void CMainDialog::OnDialogExit()
{
//Destroys the window
DestroyWindow();
}
void CMainDialog::OnInsertAbove()
{
//Method to call DoDataExchange.
//UpdateData() is used, as DoDataExchange
//Cannot be called directly.
UpdateData();
//pListCtrl must be retrieved again
//as the variable is modified in the memory
//during run-time of application
//I.E : Code crashes if the item is not retrieved again.
pListCtrl = (CListCtrl*) GetDlgItem(IDC_LIST_TASK);
//Fetch the row # from the selection made
int l_listCtrlRow = pListCtrl->GetSelectionMark();
//Insert the time as a selectable item
pListCtrl->InsertItem(l_listCtrlRow,m_cTime.Format("%I:%M %p"));
//Set the corresponding texts onto the same column (Unselectable)
//Sets the Month, Day, Date and Year based on the format given
pListCtrl->SetItemText(l_listCtrlRow,1,m_cMonth.Format("%B"));
pListCtrl->SetItemText(l_listCtrlRow,2,m_cMonth.Format("%d"));
pListCtrl->SetItemText(l_listCtrlRow,3,m_cMonth.Format("%A"));
pListCtrl->SetItemText(l_listCtrlRow,4,m_cMonth.Format("%Y"));
//Sets the title
pListCtrl->SetItemText(l_listCtrlRow,5,m_sTitle);
//Creates a local CEdit object to clear the box
CEdit *pEditBox = (CEdit*) GetDlgItem(IDC_EDIT_TASKTITLEWRITE);
pEditBox->SetSel(0,-1);
pEditBox->Clear();
//Disables the Add, Insert Above and Insert Below buttons
GetDlgItem(IDC_BUTTON_ADD)->EnableWindow(FALSE);
GetDlgItem(IDC_BUTTON_INSA)->EnableWindow(FALSE);
GetDlgItem(IDC_BUTTON_INSB)->EnableWindow(FALSE);
}
void CMainDialog::OnInsertBelow()
{
//Method to call DoDataExchange.
//UpdateData() is used, as DoDataExchange
//Cannot be called directly.
UpdateData();
//pListCtrl must be retrieved again
//as the variable is modified in the memory
//during run-time of application
//I.E : Code crashes if the item is not retrieved again.
pListCtrl = (CListCtrl*) GetDlgItem(IDC_LIST_TASK);
//Fetch the row # from the selection made
int l_listCtrlRow = pListCtrl->GetSelectionMark() + 1;
//Insert the time as a selectable item
pListCtrl->InsertItem(l_listCtrlRow,m_cTime.Format("%I:%M %p"));
//Set the corresponding texts onto the same column (Unselectable)
//Sets the Month, Day, Date and Year based on the format given
pListCtrl->SetItemText(l_listCtrlRow,1,m_cMonth.Format("%B"));
pListCtrl->SetItemText(l_listCtrlRow,2,m_cMonth.Format("%d"));
pListCtrl->SetItemText(l_listCtrlRow,3,m_cMonth.Format("%A"));
pListCtrl->SetItemText(l_listCtrlRow,4,m_cMonth.Format("%Y"));
//Sets the title
pListCtrl->SetItemText(l_listCtrlRow,5,m_sTitle);
//Creates a local CEdit object to clear the box
CEdit *pEditBox = (CEdit*) GetDlgItem(IDC_EDIT_TASKTITLEWRITE);
pEditBox->SetSel(0,-1);
pEditBox->Clear();
//Disables the Add, Insert Above and Insert Below buttons
GetDlgItem(IDC_BUTTON_ADD)->EnableWindow(FALSE);
GetDlgItem(IDC_BUTTON_INSA)->EnableWindow(FALSE);
GetDlgItem(IDC_BUTTON_INSB)->EnableWindow(FALSE);
}
void CMainDialog::OnAddTask()
{
//Method to call DoDataExchange.
//UpdateData() is used, as DoDataExchange
//Cannot be called directly.
UpdateData();
//pListCtrl must be retrieved again
//as the variable is modified in the memory
//during run-time of application
//I.E : Code crashes if the item is not retrieved again.
pListCtrl = (CListCtrl*) GetDlgItem(IDC_LIST_TASK);
//Assign the amount of items into the variable
m_itemCount = pListCtrl->GetItemCount();
//Insert the time as a selectable item
pListCtrl->InsertItem(m_itemCount,m_cTime.Format("%I:%M %p"));
//Set the corresponding texts onto the same column (Unselectable)
//Sets the Month, Day, Date and Year based on the format given
pListCtrl->SetItemText(m_itemCount,1,m_cMonth.Format("%B"));
pListCtrl->SetItemText(m_itemCount,2,m_cMonth.Format("%d"));
pListCtrl->SetItemText(m_itemCount,3,m_cMonth.Format("%A"));
pListCtrl->SetItemText(m_itemCount,4,m_cMonth.Format("%Y"));
//Sets the title
pListCtrl->SetItemText(m_itemCount,5,m_sTitle);
//Creates a local CEdit object to clear the box
CEdit *pEditBox = (CEdit*) GetDlgItem(IDC_EDIT_TASKTITLEWRITE);
pEditBox->SetSel(0,-1);
pEditBox->Clear();
//Disables the add, insert above and below button
GetDlgItem(IDC_BUTTON_ADD)->EnableWindow(FALSE);
GetDlgItem(IDC_BUTTON_INSA)->EnableWindow(FALSE);
GetDlgItem(IDC_BUTTON_INSB)->EnableWindow(FALSE);
//Enables the delete button
GetDlgItem(IDC_BUTTON_DELETE)->EnableWindow(TRUE);
}
void CMainDialog::OnDeleteTask()
{
//pListCtrl must be retrieved again
//as the variable is modified in the memory
//during run-time of application
//I.E : Code crashes if the item is not retrieved again.
pListCtrl = (CListCtrl*) GetDlgItem(IDC_LIST_TASK);
//Check if the user has made any selections in List Control
if(pListCtrl->GetSelectionMark() == -1)
MessageBox("Select a Task to Delete","Error");
else
{
//Delete the selected item
pListCtrl->DeleteItem(pListCtrl->GetSelectionMark());
//Check if there's any item remaining in the list control
//and disable the delete button, if itemcount = 0
if(pListCtrl->GetItemCount()==0)
GetDlgItem(IDC_BUTTON_DELETE)->EnableWindow(FALSE);
//Unselect on the List Control
pListCtrl->SetSelectionMark(-1);
//Disable the Insert Above and Insert Below buttons
GetDlgItem(IDC_BUTTON_INSA)->EnableWindow(FALSE);
GetDlgItem(IDC_BUTTON_INSB)->EnableWindow(FALSE);
//Clear the readable-only edit boxes
//All the objects needs to be fetched again
//(Same case with pListCtrl)
l_EditBoxDay = (CEdit*) GetDlgItem(IDC_EDIT_TASKDAY);
l_EditBoxDay->SetWindowText("");
l_EditBoxTime = (CEdit*) GetDlgItem(IDC_EDIT_TASKTIME);
l_EditBoxTime->SetWindowText("");
l_EditBoxTitle = (CEdit*) GetDlgItem(IDC_EDIT_TASKTITLEDISP);
l_EditBoxTitle->SetWindowText("");
}
}
void CMainDialog::PostNcDestroy()
{
delete this;
}
Ok, I'm having a serious problem with the list control and it updating the text to a read-only edit control box.
Under the OnUpdateListCtrl function, where it triggers as soon as the user selects an item in the list control box, it's supposed to update the read-only edit control box based on the selection made. Now, the problem occurs on this particular line -
int l_nSelected = pListCtrl->GetSelectionMark();
This returns the integer of the row # (0, from the first one), but it returns it a tad-bit late. Let me demonstrate what I mean -
Suppose the program had two items and I clicked on the second item - this properly returns an integer of 1. NOW suppose that I clicked on the first item, it's supposed to return an integer of 0, right? well it doesn't. It returns 1. Again, if I were to click on the second item (Where it should return 1), it returns 0. This becomes a problem because the read-only edit control box updates the information one-step too late.
This function acts immediately upon WM_NOTIFY message, tricking the list control to think that it hasn't made the selection change just yet.
I believe I have pinpointed the problem correctly, but I do not know of the correct fix. I was thinking about using CPoint in the OnUpdateListCtrl, but I believe that's taking things way too far in terms of the correction. There has to be an easier fix for this.
Can anyone tell me any suggestions? I'd greatly appriciate any help.
Last edited by l46kok; May 4th, 2008 at 12:59 PM.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|