⬆️ ⬇️

Description of how to work with Virtual Grid Control in Visual C ++

Due to the small number of standard controls in Visual C ++, most of the components have to be added independently, especially if the question concerns the display of tabular data. For less serious systems, the standard ListCtrl is no longer enough. Having rummaged on the Internet you can find a considerable amount of commercial grids, but you don’t really want to part with your blood money, a great component from Yuriy Zabroda VirtualGridCtrl comes to the rescue.



This component was written in Visual C ++ 6.0, but to this day it can be successfully used in more recent versions of Visual C ++. In fact, when choosing a grid for myself, I put forward several requirements:



- multi-line grid cap (without this, it is difficult to present at least some complicated report)

- display multiline text

- the ability to replace the standard CEdit in the rows of the table with your own controls

- ability to highlight individual entries

- work speed

')

Perhaps we start with the last item. The word Virtual in the title means that the data is not stored in the grid itself, but in some kind of data structure, for example, a vector. And when displaying data on the screen from this structure, only those data that need to be displayed on the screen are requested, this ensures the independence of the speed of work on the number of elements in the list.



We will deal with other possibilities, using a small example.

Suppose we have a tabular document of the following form:



- â„– Number

- Date

- Client: Phone, Address



The lines contain plain text.



We need to get something like the following







VirtualGridCtrl includes a grid appearance constructor, it is called VirtualGridDemo.exe. There is nothing complicated in its use, on the tab, click on the “Columns and Headers constructor” button and on the “Columns” tab we delete all the columns and add as many columns as necessary, in our case 4. Then we will create the structure on the “Headers” tab hats of our grid.







The following will turn out







In the panel on the right, you can also set additional parameters for rows and columns.



Now let's figure out how to use all this now. Again open the settings window by the button “Columns and Headers constructor” and go to the tab “Code generation” and click on “Generate”.



Create a new Visual C ++ project (I use Visual Studio 2008) with the Dialog style and connect the header files to the project: VirtualGridCtrl.h, MemDC.h, TitleTip.h, GridListBox.h, GridEdit.h, GridButton.h. Add “Custom control” to the form, set its “Class” property to “CVirtualGridCtrl” and add the m_grid variable with the type “CVirtualGridCtrl”.



Now you can add grid initialization code to OnInitialDialog. We copy there the code received by us in the designer.



Immediately I will say the shortcomings of the code that we received, not all the settings that we installed in the constructor, got into this code, this is a flaw, but this code is not difficult to add yourself. So, let's look at the code we received:

// --------------- Required variables ----------------- CGridColumn *pColumn; CGridHeaderSections *pSections; CGridHeaderSection *pSection; CGridHeaderSection *pUpperSection; // ----------------- Let's add some columns -------------- m_grid.AddColumn(_T(""), 60, LVCFMT_CENTER); //  ,       m_grid.AddColumn(_T(""), 92, LVCFMT_CENTER); m_grid.AddColumn(_T(""), 81, LVCFMT_CENTER); m_grid.AddColumn(_T(""), 68, LVCFMT_CENTER); // --------------- Set additional column properties ---------------- pColumn = m_grid.GetColumn(0); pColumn->SetTabStop(FALSE); //     // --------------- Let's put the grid header into shape ------------ pSections = m_grid.GetHeader()->GetSections(); pUpperSection = pSections->GetSection(0); pUpperSection->SetCaption(_T("")); pUpperSection->SetAlignment(LVCFMT_CENTER); pUpperSection = pSections->GetSection(1); pUpperSection->SetCaption(_T("")); pUpperSection->SetAlignment(LVCFMT_CENTER); pUpperSection = pSections->GetSection(2); pUpperSection->SetCaption(_T("")); pUpperSection->SetAlignment(LVCFMT_CENTER); pUpperSection->SetWordWrap(TRUE); //     3-  pSection = pUpperSection->Add(); pSection->SetCaption(_T("")); pSection->SetAlignment(LVCFMT_CENTER); pUpperSection = pSection; pUpperSection = pSection->GetParent(); pSection = pUpperSection->Add(); pSection->SetCaption(_T("")); pSection->SetAlignment(LVCFMT_CENTER); pUpperSection = pSection; pUpperSection = pSection->GetParent(); m_grid.GetHeader()->SynchronizeSections(); // -------------- Some additional initializations... ------ //    CGridHeader *pHeader = m_grid.GetHeader(); pHeader->SetSectionHeight(25); //    pHeader->SynchronizeSections(); m_grid.SetFixedCount(1); //      m_grid.SetRowSelect(); //    m_grid.SetRowHeight(25); //    


How to set additional parameters can be seen in the example that comes with VirtualGrid.

We will understand now how to work with data. Create a structure:

 struct sKlient { int nomer; COleDateTime date; CString tel; CString adres; }; 


And we declare the m_data variable as follows:

 vector<sKlient> m_data; 


And in OnInitialDialog we initialize the structure:

 //     sKlient tmp; tmp.nomer = 1; tmp.date = COleDateTime(2012,1,1,0,0,0); tmp.tel = L"12-34-56"; tmp.adres = L" 1"; m_data.push_back(tmp); tmp.nomer = 2; tmp.date = COleDateTime(2011,2,3,0,0,0); tmp.tel = L"78-12-45"; tmp.adres = L" 2"; m_data.push_back(tmp); m_grid.SetRowCount(m_data.size()); //       


Now we will add a data output function to the grid, for this we will add a function definition to our class:

 afx_msg void OnGridGetDispInfo(NMHDR *pNMHDR, LRESULT *pResult); 


in the .cpp file in BEGIN_MESSAGE_MAP add:

 ON_NOTIFY(VGN_GETDISPINFO, IDC_CUSTOM1, OnGridGetDispInfo) 


The VGN_GETDISPINFO event handler works as follows:

 VG_DISPINFO *pDispInfo = (VG_DISPINFO *)pNMHDR; CString st; if (pDispInfo->item.mask & LVIF_TEXT) //      { switch (pDispInfo->item.nColumn) { case 0: {// â„– st.Format(L"%d", m_data[pDispInfo->item.nRow].nomer); pDispInfo->item.strText = st; } break; } } //       if (pDispInfo->item.mask & LVIF_COLOR) { if (pDispInfo->item.nColumn == 1) //      { pDispInfo->item.pDC->SetBkColor(RGB(202, 228, 255)); } } 


Similarly, you can add a function to handle double-clicking on a line:

 ON_NOTIFY(WM_LBUTTONDBLCLK, IDC_CUSTOM1, OnNMDblclkGrid) void CCVirtaGridTestDlg::OnNMDblclkGrid(NMHDR *pNMHDR, LRESULT *pResult) { int n; n = m_grid.GetRow(); if (!m_grid.GetRowCount() || (n > m_grid.GetRowCount()-1)) return; ::AfxMessageBox(m_data[n].adres); } 


Or handlers of any other events.



This grid is quite versatile and can be used in various applications to display lists in a beautiful and visual form. If necessary, it is easy to modify, because the source code has a clear and understandable structure.



PS: The application has a grid in its standard form, and an example from an article with a slightly modified grid (minor bugs were fixed, gradients were added when drawing lines and headers), so it’s better to take it from them.

Source: https://habr.com/ru/post/140388/



All Articles