В проекте SilverThreads  в диалоговом окне рисуется два  элемента формы static, в каждом из которых независимо происходит рисование/стирание черного кружочка через случайный промежуток времени.

Целью данного проекта было изучение инициирования, отработки и уничтожения двух независимых вычислительных потоков одним исполняемым файлом. Для наглядной демонстрации независимости работы потоков использовалось  изменение в поведении двух независимых  графических объектов.

Программа реализована в диалоговом окне.

Инициализация диалогового окна

BOOL CSilver_ThreadsDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// Add "About..." menu item to system menu.

	// IDM_ABOUTBOX must be in the system command range.
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		CString strAboutMenu;
		strAboutMenu.LoadString(IDS_ABOUTBOX);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// Set the icon for this dialog.  The framework does this automatically
	//  when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon
	
	// TODO: Add extra initialization here

	m_static1.SubclassDlgItem(IDC_STATIC1, this);
	m_static2.SubclassDlgItem(IDC_STATIC2, this);
	
	return TRUE;  // return TRUE  unless you set the focus to a control
}

После инициализации окна, происходит обращение к функции отрисовки OnPaint()

void CSilver_ThreadsDlg::OnPaint() 
{
	if (IsIconic())
	{
		CPaintDC dc(this); // device context for painting

		SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

		// Center icon in client rectangle
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// Draw the icon
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialog::OnPaint();
	}
}

В заголовочном файле для диалогового окна SilverThreadsDlg.h  мы объявили 2 переменные для элементов управления Static. Это позволяет нам обращаться к свойствам и методам класса CStaticAll

	CStaticAll m_static1;
	CStaticAll m_static2;

Весь механизм управления отрисовкой кружочка на форме происходит здесь:

void CStaticAll::OnPaint() 
{
	CPaintDC dc(this); // device context for painting
	RECT r;


	CBrush br;
	//m_color_brush = RGB(rand()%256,rand()%256,rand()%256);
	br.CreateSolidBrush(m_color_brush);
	GetClientRect(&r);
	dc.SelectObject(&br);
	dc.FillSolidRect(&r, RGB(255,255,255));
	m_client_width = r.right - r.left + 1;
	m_client_height = r.bottom - r.top + 1;
	dc.Ellipse(m_client_width/2 + r.left - m_radius, m_client_height/2 + r.top - m_radius, 
			   m_client_width/2 + r.left + m_radius, m_client_height/2 + r.top + m_radius);

	if(m_flag)
	{
		m_flag = false;
		m_thread = AfxBeginThread(RFP, this);
	}
	
}

Рандомная  процедура определяет случайный промежуток времени:

int CStaticAll::MyRand()
{
	return(((m_holdrand = m_holdrand * 214013L + 2531011L) >> 16) & 0x7fff);
}

Рабочая функция потока

UINT RFP(LPVOID p)
{
	CStaticAll *csa = (CStaticAll *)p;
	CDC *pdc = csa -> GetDC();
	for(;;)
	{
		Sleep(csa -> m_delay + csa -> MyRand()%1000);
		if(csa -> m_color_brush == RGB(0, 0, 0))
		{
			csa -> m_color_brush = RGB(255, 255, 255);
		}
		else csa -> m_color_brush = RGB(0, 0, 0);
		csa -> Invalidate();
		// Функция Invalidate(); есть во всех классах, в основе которых CWnd.
	}
	return 0;
}