We have a list view control; the task is to write simple code to help in navigating through the controls the way one navigates in an Excel sheet. We also need to edit the individual cells of the list view control again, just as we edit in an Excel sheet.
When I started to look for solutions on the Net, I found out that the code to do such a thing was quite complicated, although it ultimately achieved what I wanted. I started to write my own code; my main objective was to keep it as simple as possible while achieving the expected results.
How the Control Works
First, run the application. A list view control (3 rows by 9 columns) will appear in a dialog application. Press Tab and a combo box appears in the first column, first row of the list View control. Pressing Tab again will make the combo box disappear and an edit box appear in the second column, and so on. To navigate backwards, you need to press Shift+Tab. If you click anywhere except in the header and the last column (4th) in the list control, a corresponding control will appear. Scrolling the mouse will make all controls disappear; using the scroll bars will also have a similar effect. As soon as the control is removed from a cell, its contents are copied into the cell.
I think the very basic necessities of a navigatable-editable list view control are satisfied.
The Code Is Very Simple
After you start a dialog application, you put a list view control in it. Derive a class from CListCtrl. I have even derived classes from CEdit and CComboBox just in case I need more control on the controls. However, I do not make any use of it.
I define the following global variables:
CMyEdit *m_pedit = NULL; CMyCombo *m_pcombo = NULL; int row =0; int col =-1;
The OnInitDialog() function contains some standard code to get the List view control up and running. I declare the following public functions in the CMyListCtrl the class derived from CListCtrl.
LRESULT OnEdit(); LRESULT OnCombo(); void OnSetText();
Use PreTranslateMessage(...) to accommodate for the Tab and Shift+Tab keys. After the row column management is done, I call these three functions:
VerifyScrollPos(); vResetTopPosition(); vResetBottomPosition();
The first one sets the scroll bar position to get the control into view if required. I have presented various flvours of this feature. The code is there and commented out. The second adjusts the top position of the control, if it by chance goes above the header control. The third does the same to manage the position of the control if it goes below the Listview control.
I do a Send message and not a post message because I need to wait until the scrolling is over. The code then proceeds to switch on the column variable. I have pre-assigned the first column for combo boxes, and the second and third for edit boxes.
So, here is where I call OnEdit() or OnCombo().The OnCombo() function checks to see whether m_pcombo is NULL. If it is NULL, no combo box box is created; it creates one whose parent is the Listview control and places it at the current row and column cordinates. If the Edit box is already created, it just moves it to its current row and column cordinates.
The OnSetText() function just takes the current control's text and writes it to the current cell. Then I handle the NM_CLICK message handler of the list view control to make a control disappear from its previous position and appear in the clicked position; this is done in OnClick(...). The LVN_COLUMNCLICK message is handled to make all the controls disappear.
The OnNotify(..) function prompts me whenever the user is trying to resize a column of the List view control. I grab the opportunity and hide all the controls so that the next time the control can appear with new sizes.
I have tested to my heart's content and found that the behaviour is close to that of an Excel sheet. There might be still some bugs. Please feel free to fix them and notify me afterwards.
DownloadDownload demo project and source - 33 Kb