This example assumes there is a form that has a TableLayoutPanel with a vertical and horizontal scroll bar.
The form can be resized and when it is the TableLayoutPanel is re-created to only include what is visible.
This means that only the controls that can be seen are created and makes creating and updating it as fast as possible.

(IBEX library has ready made form with this)

For the TableLayoutPanel

Name			Table1
Anchor			Top, Bottom, Left, Right
AutoScroll		False
AutoSize		False
For the horizontal scroll bar

Name			TableHozScrollBar1
Anchor			Bottom, Left, Right
For the vertical scroll bar

Name			TableVertScrollBar1
Anchor			Top, Bottom, Right
Create these in the class

	//GLOBAL VARAIBLES
	private: int TotalNumOfColumns;
	private: int TotalNumOfRows;
	private: int NumOfColumnsShown;
	private: int NumOfRowsShown;
	private: int ShowingStartColumnIndex;
	private: int ShowingStartRowIndex;
	private: array<System::Windows::Forms::TextBox^, 2>  ^txtGridBoxes;
In the form load event

	//CREATE THE TABLE GRID
	TotalNumOfColumns = 150;
	TotalNumOfRows = 150;
	ShownStartColumnIndex = 0;
	ShownStartRowIndex = 0;

	EventArgs ^MyArgs = gcnew EventArgs();
	frmGroupSetup_ResizeEnd(this, MyArgs);		//Trigger the rezize event
These are the functions


//*********************************
//*********************************
//********** FORM RESIZE **********
//*********************************
//*********************************
private: System::Void frmGroupSetup_Resize(System::Object^  sender, System::EventArgs^  e)
{
	const int ColumnsWidth = 100;	//Set required columns width
	const int RowsHeight = 20;		//Set required columns height
	int Count;
	int Column;
	int Row;

	//---------------------------------------------------------------------------
	//----- CALCULATE HOW MANY ROWS AND COLUMNS WE CAN FIT INTO WINDOW SIZE -----
	//---------------------------------------------------------------------------
	NumOfColumnsShown = (this->Width - 20) / ColumnsWidth;		//Subtract width of other items on form.
	NumOfColumnsShown++;										//We need 1 extra colum to act as the variable size column on the right
	NumOfRowsShown = (this->Height - 80) / RowsHeight;			//Subtract height of other items on form.
	NumOfRowsShown++;										//We need 1 extra row to act as the variable size column on the bottom

	//Stop re-drawing while we update contents
	this->SuspendLayout();
	Table1->SuspendLayout();

	//--------------------------------------------
	//----- REMOVE THE EXISTING CONTROLS ---------
	//--------------------------------------------
	while (Table1->Controls->Count)
		Table1->Controls->RemoveAt(0);

	//-----------------------------
	//----- RE-SIZE THE TABLE -----
	//-----------------------------
	//Remove existing styles so we can re-create
	while (Table1->ColumnStyles->Count)
		Table1->ColumnStyles->RemoveAt(0);
	while (Table1->RowStyles->Count)
		Table1->RowStyles->RemoveAt(0);

	Table1->ColumnCount = NumOfColumnsShown;
	Table1->RowCount = NumOfRowsShown;

	for (Count = 0; Count < NumOfColumnsShown; Count++)
		Table1->ColumnStyles->Add(gcnew System::Windows::Forms::ColumnStyle(System::Windows::Forms::SizeType::Absolute, ColumnsWidth));

	for (Count = 0; Count < NumOfRowsShown; Count++)
		Table1->RowStyles->Add(gcnew System::Windows::Forms::RowStyle(System::Windows::Forms::SizeType::Absolute, RowsHeight));

	//----------------------------
	//----- ADD THE CONTROLS -----
	//----------------------------
	this->txtGridBoxes = gcnew array<System::Windows::Forms::TextBox^, 2>(NumOfColumnsShown, NumOfRowsShown);

	for (Column = 0; Column < NumOfColumnsShown; Column++)
	{
		for (Row = 0; Row < NumOfRowsShown; Row++)
		{
			this->txtGridBoxes[Column, Row] = (gcnew System::Windows::Forms::TextBox());
			this->txtGridBoxes[Column, Row]->Margin = System::Windows::Forms::Padding(0, 0, 0, 0);
			this->txtGridBoxes[Column, Row]->BorderStyle = System::Windows::Forms::BorderStyle::FixedSingle;
			this->txtGridBoxes[Column, Row]->Dock = System::Windows::Forms::DockStyle::Fill;
			this->txtGridBoxes[Column, Row]->ReadOnly = true;

			Table1->Controls->Add(this->txtGridBoxes[Column, Row], Column, Row);
		}
	}

	//----------------------------------
	//----- UPDATE THE SCROLL BARS -----
	//----------------------------------

	//----- HORIZONTAL -----
	TableHozScrollBar1->Minimum = 0;

	if (ShowingStartColumnIndex > (TotalNumOfColumns - NumOfColumnsShown))
	{
		ShowingStartColumnIndex = (TotalNumOfColumns - NumOfColumnsShown) + 1;
		if (ShowingStartColumnIndex < 0)
			ShowingStartColumnIndex = 0;
		if (ShowingStartColumnIndex >= TotalNumOfColumns)
			ShowingStartColumnIndex = TotalNumOfColumns - 1;
		TableHozScrollBar1->Value = ShowingStartColumnIndex;
	}
	if ((NumOfColumnsShown > 1) && (TotalNumOfColumns > NumOfColumnsShown))
		TableHozScrollBar1->LargeChange = NumOfColumnsShown - 2;
	else
		TableHozScrollBar1->LargeChange = 1;

	if (TotalNumOfColumns > NumOfColumnsShown)
		TableHozScrollBar1->Maximum = (TotalNumOfColumns - NumOfColumnsShown) + TableHozScrollBar1->LargeChange;
	else
		TableHozScrollBar1->Maximum = 0;

	//----- VERTICAL -----
	TableVertScrollBar1->Minimum = 0;

	if (ShowingStartRowIndex > (TotalNumOfRows - NumOfRowsShown))
	{
		ShowingStartRowIndex = (TotalNumOfRows - NumOfRowsShown) + 1;
		if (ShowingStartRowIndex < 0)
			ShowingStartRowIndex = 0;
		if (ShowingStartRowIndex >= TotalNumOfColumns)
			ShowingStartRowIndex = TotalNumOfColumns - 1;
		TableVertScrollBar1->Value = ShowingStartRowIndex;
	}
	if ((NumOfRowsShown > 1) && (TotalNumOfRows > NumOfRowsShown))
		TableVertScrollBar1->LargeChange = NumOfRowsShown - 2;
	else
		TableVertScrollBar1->LargeChange = 1;

	if (TotalNumOfRows > NumOfRowsShown)
		TableVertScrollBar1->Maximum = (TotalNumOfRows - NumOfRowsShown) + TableVertScrollBar1->LargeChange;
	else
		TableVertScrollBar1->Maximum = 0;

	//-------------------------------------
	//----- UPDATE THE DISPLAYED DATA -----
	//-------------------------------------
	UpdateTableGridData();

	Table1->ResumeLayout();
	this->ResumeLayout();
 }

//********************************************************
//********************************************************
//********** GRID HORIZONTAL SCROLL BAR CHANGED **********
//********************************************************
//********************************************************
private: System::Void TableHozScrollBar1_ValueChanged(System::Object^  sender, System::EventArgs^  e)
{
	if (TableHozScrollBar1->Value < TotalNumOfColumns)
		ShowingStartColumnIndex = TableHozScrollBar1->Value;
	else
		ShowingStartColumnIndex = TotalNumOfColumns - 1;

	UpdateTableGridData();
}

//******************************************************
//******************************************************
//********** GRID VERTICAL SCROLL BAR CHANGED **********
//******************************************************
//******************************************************
private: System::Void TableVertScrollBar1_ValueChanged(System::Object^  sender, System::EventArgs^  e)
{
	if (TableVertScrollBar1->Value < TotalNumOfRows)
		ShowingStartRowIndex = TableVertScrollBar1->Value;
	else
		ShowingStartRowIndex = TotalNumOfRows - 1;

	UpdateTableGridData();
}

//***********************************************
//***********************************************
//********** UPDATE DATA IN TABLE GRID **********
//***********************************************
//***********************************************
private: void UpdateTableGridData(void)
{
	int Column;
	int Row;
	String ^NewText;

	Table1->SuspendLayout();

	for (Column = 0; Column < NumOfColumnsShown; Column++)
	{
		for (Row = 0; Row < NumOfRowsShown; Row++)
		{
			if (
			((Column + ShowingStartColumnIndex) < TotalNumOfColumns) &&
			((Row + ShowingStartRowIndex) < TotalNumOfRows)
			)
			{
				//SET CELL CONTENTS
				NewText = Convert::ToString(Column + ShowingStartColumnIndex) + "," + Convert::ToString(Row + ShowingStartRowIndex);
				if (this->txtGridBoxes[Column, Row]->Text != NewText)
					this->txtGridBoxes[Column, Row]->Text = NewText;

				this->txtGridBoxes[Column, Row]->BackColor = System::Drawing::SystemColors::Control;
			}
			else
			{
				//UNUSED CELL
				NewText = "";	//Unused end of column or end of row text box  - blank
				if (this->txtGridBoxes[Column, Row]->Text != NewText)
					this->txtGridBoxes[Column, Row]->Text = NewText;

				this->txtGridBoxes[Column, Row]->BackColor = System::Drawing::SystemColors::Control;
			}
		}
	}

	Table1->ResumeLayout();
}
USEFUL?
We benefit hugely from resources on the web so we decided we should try and give back some of our knowledge and resources to the community by opening up many of our company’s internal notes and libraries through mini sites like this. We hope you find the site helpful.
Please feel free to comment if you can add help to this page or point out issues and solutions you have found, but please note that we do not provide support on this site. If you need help with a problem please use one of the many online forums.