Шпора по mfc

Собственные функции MFC

 

Функции

GetModuleFileName »

Функция возвращает путь к исполняемому файлу, почитать за нее можно тут.

MAX_PATH;
wchar_t buffer[MAX_PATH];
GetModuleFileName(AfxGetInstanceHandle(),buffer,MAX_PATH);
AfxMessageBox(buffer);

#pragma comment »

//подключает библиотеки

#pragma comment(lib, "wininet.lib")

TRACE »

выводит строку со спецификаторами, работает как printf

%s – выводит строки типа char* (ANSIIZ)

%S – хз какие строки выводит, наверно широкие ANSII, UNICODE, TCHAR

BSTR sss(L"<H2 class="b-post__title b-post__title_inline "><A id=prj_name_2448718 class=b-post__link href="/projects/2448718/programmist-bitriks-pravki-po-saytu.html" name=prj2448718>Программист Битрикс, правки по сайту</A> </H2>");
TRACE("sss=%sn",_com_util::ConvertBSTRToString(sss));

AfxMessageBox »

Почитать за нее можно тут.

вот код примера

if(AfxMessageBox(L"нужно как то удалить cookie",MB_OKCANCEL)==IDOK)
{
	system("cmd.exe /C RunDll32.exe InetCpl.cpl,ClearMyTracksByProcess 255");
}

параметры которые принимает MB

MB_OK, MB_OKCANCEL, и други, а возвращает идентификаторы IDOK, IDCANCEL и другие.

CreateControl »

Используется для создания элемента управления ActiveX которые будут представлены в программе MFC в виде объекта CWnd. Почитать за нее можно тут.

CRect rectClient(10,10,500,500);
CWnd wndBrowser;//объект типа CWnd
if (!m_wndBrowser.CreateControl(__uuidof(WebBrowser), _T("Window"),
    WS_VISIBLE | WS_CHILD, rectClient, this, AFX_IDW_PANE_FIRST))
{
    DestroyWindow();
}

CWnd::GetControlUnknown »

Возвращает Указатель на IUnknown. Почитать за нее можно тут.

LPUNKNOWN pUnk=NULL;
if (pUnk = m_wndBrowser.GetControlUnknown())
{
	if(pUnk->QueryInterface(IID_IWebBrowser2,(void**)&m_pWeb2)==S_OK)
	{
		BSTR url=L"microsoft.com";
		m_pWeb2->Navigate2(COleVariant(url),NULL,NULL,NULL,NULL);
		TRACE("bifore if url=%Sn",url);
	}
}

::PostMessage »

Применяется для отправки свои собственных сообщений

::PostMessage((HWND)pParam, WM_MYMESSAGE,0,0)

,где pParam идентификатор окна, WM_MYMESSAGE наше собственное сообщение(идентификатор) которое мы посылаем

GetSafeHwnd »

Возвращает HWND окна

AfxBeginThread(ProgThread,GetSafeHwnd(),THREAD_PRIORITY_NORMAL);//запускаем поток

AfxGetInstanceHandle »

Возвращает hInstanse приложения, почитать за нее можно тут.

MAX_PATH;
wchar_t buffer[MAX_PATH];
GetModuleFileName(AfxGetInstanceHandle(),buffer,MAX_PATH);
AfxMessageBox(buffer);

GetMessage/PeekMessage »

GetMessage не возвращает false, если нету сообщения она ожидает, а PeekMessage не ожидает и вернет false, в этом их разница, и от примеры использования

while(::PeekMessage(&message,NULL,0,0,PM_REMOVE))
{
     ::TranslateMessage(&message);
     ::DispatchMessage(&message);
}
//или 
if(::GetMessage(&message,NULL,0,0))
{
     ::TranslateMessage(&message);
     ::DispatchMessage(&message);
}

SendMessage/PostMessage »

Разница между ними в том что SendMessage отправляет сообщение и будет ждать пока это сообщение будет обработано, потом пойдет код дальше. PostMessage отправило сообщение и ждать обработки его не будет, программа пойдет выполнятся дальше.

В общем если вы хотиле отлавливать посланое сообщение в какой то функции то нужно использовать PostMessage, потому что SenMessage сразу его обработает и вы не отловите его.

void Ctest_fl_ruDlg::OnCancel()
{
    // TODO: добавьте специализированный код или вызов базового класса
    //будет ждать пока обработается сообщение.    
    ::SendMessage(GetSafeHwnd(),WM_CLOSE,NULL,NULL);
    //не будет ждать обработки сообщения, сообщение добавится в очередь
    //без ожидания обработки :)
    ::PostMessage(GetSafeHwnd(),WM_CLOSE,NULL,NULL);
    CDialogEx::OnCancel();
}

Макросы MFC

Показать »

IMPLEMENT_DYNCREATE

#define IMPLEMENT_DYNCREATE(class_name, base_class_name) 
	CObject* PASCAL class_name::CreateObject() 
		{ return new class_name; } 
	IMPLEMENT_RUNTIMECLASS(class_name, base_class_name, 0xFFFF, 
		class_name::CreateObject, NULL)

Используют его так:

IMPLEMENT_DYNCREATE(CSpaceship,CCmdTarget)

Где CSpaceship – класс, а CCmdTarget – базовый класс. Подставим в сам макрос значения и посмотрим что у нас создает макрос

	CObject* PASCAL CSpaceship ::CreateObject() 
		{ return new CSpaceship ; }

В первой части как мы видим у нас создается функция CreateObject() которая динамически создает указатель на наш объект CSpaceship и возвращает его из функции. Вторая часть этого макроса это макрос:

IMPLEMENT_RUNTIMECLASS(class_name, base_class_name, 0xFFFF, 
		class_name::CreateObject, NULL)

Вызывается походу он просто как бы так давайте подставим

IMPLEMENT_RUNTIMECLASS(CSpaceship, CCmdTarget, 0xFFFF, 
		CSpaceship::CreateObject, NULL)

А теперь давайте глянем определение этого макроса

#define IMPLEMENT_RUNTIMECLASS(class_name, base_class_name, wSchema, pfnNew, class_init) 
	AFX_COMDAT const CRuntimeClass class_name::class##class_name = { 
		#class_name, sizeof(class class_name), wSchema, pfnNew, 
			RUNTIME_CLASS(base_class_name), NULL, class_init }; 
	CRuntimeClass* class_name::GetRuntimeClass() const 
		{ return RUNTIME_CLASS(class_name); }

Так как видим большое оказалось определение и еще дополнительно добавились нескольно новых макросов. Давайте снова подставим значения наши для ясности и попробуем понять что создается

#define IMPLEMENT_RUNTIMECLASS(class_name, base_class_name, wSchema, pfnNew, class_init) 
	AFX_COMDAT const CRuntimeClass CSpaceship::class##CSpaceship = { 
		#CSpaceship, sizeof(class class_name), 0хFFFF, CSpaceship::CreateObject, 
			RUNTIME_CLASS(CCmdTarget), NULL, NULL }; 
	CRuntimeClass* CSpaceship::GetRuntimeClass() const 
		{ return RUNTIME_CLASS(CSpaceship); }

Давайте дадим определения еще двум макросам AFX_COMDAT и RUNTIME_CLASS

#define AFX_COMDAT __declspec(selectany)

непонятно что это за штука такая {Сообщает компилятору, что объявленный глобальный элемент данных (переменная или объект) – это запись COMDAT (упакованная функция) режима pick-any (выбрать-любой). силь}

#define RUNTIME_CLASS(class_name) _RUNTIME_CLASS(class_name)

И найдем определение макроса _RUNTIME_CLASS

#define _RUNTIME_CLASS(class_name) ((CRuntimeClass*)(&class_name::class##class_name))

как видим все стало очень непонятно, по идее RUNTIME_CLASS это тоже самое что и _RUNTIME_CLASS, поэтому запишем что у нас выйдет после подстановки

((CRuntimeClass*)(&CSpaceship::class##CSpaceship))

получается вот такая строка, Здесь происходит преобразование в указатель CRuntimeClass* объекта типа CSpaceship. Две решетки я не знаю что означают.

И еще раз определение IMPLAMENT_RUNTIMECLASS

//#define IMPLEMENT_RUNTIMECLASS(class_name, base_class_name, wSchema, pfnNew, class_init) 
__declspec<span class="br0">(</span>selectany<span class="br0">) </span>const CRuntimeClass CSpaceship::classCSpaceship = { 
 "CSpaceship", sizeof(class CSpaceship), 0xFFFF, CSpaceship::CreateObject, 
 ((CRuntimeClass*)(&amp;CCmdTarget::classCCmdTarget)), NULL, NULL }; 
 CRuntimeClass* СSpaceship::GetRuntimeClass() const 
 { return ((CRuntimeClass*)(&amp;CSpaceship::classCSpaceship));}

Получается типо от такая непонятная фигня. Создается класс CRuntimeClass которому присваивается значение хз. какое и создается определение функции

 

DECLARE_DYNCREATE

#define DECLARE_DYNCREATE(class_name) 
	DECLARE_DYNAMIC(class_name) 
	static CObject* PASCAL CreateObject();

как видим тут новый макрос внутри DECLARE_DYNAMIC и создается определение статической функции CreateObject. Давайте разберем макрос DECLARE_DYNAMIC

#define DECLARE_DYNAMIC(class_name) 
public: 
	static const CRuntimeClass class##class_name; 
	virtual CRuntimeClass* GetRuntimeClass() const; 

Как мы видим создаются статическая константная переменная на структуру CRuntimeClass  и виртуальная функция GetRuntimeClass

В общем DECLARE_DYNCRATE создает две функции и одну статическую переменную static const CRuntimeClass class##class_name; virtual CRuntimeClass* GetRuntimeClass() cosnt; и static CObject* PASCAL CreateObject();

А IMPLAMETN_DYNCRATE инициализирует переменную и создает два определения этих функций и все в принципе.

Подключение MFC в консольное приложение

Показать »

Чтобы подключить MFC мы добавляем заголовочный файл #include <afxwin.h>

Все MFC-программы включают заголовочный файл AFXWIN.H. В нем, а также в различных вспомогательных файлах, содержатся описания классов, структур, переменных и других объектов MFC. Он автоматически подключает большинство заголовочных файлов, относящихся к MFC, в том числе и WINDOWS.H, в котором определены все функции Windows API и другие объекты, которые используются при традиционном программировании на С и “чистом” API. 

вот код:

#include <iostream>
using std::cout;
using std::endl;
#include <string>
using std::string;

#include <afxwin.h>

int main()
{
	setlocale(LC_ALL, "rus_rus.1251");
	cout <<"hellow world!rn";
	CStringA str="hellow";
	string str1;
	cout <<str<<"rn";

	return 0;
}

Этот код не будет работать, потому что нужно еще сам проект настроить, заходим в свойства проекта и выбираем как на рисунке ниже

mfc use property

Элементы управления:

Edit Control »

ССылки на посты:

  1. Пост

Рассмотрим как получить данные из этого элемента и вывести в этот элемент в диалоговом окне, и так создадим обычную форму как на рисунке ниже

mfc Edit Controlчтобы сделать расширеное поле Edit Control для многострочного ввода нужно поменять в свойствах Edit Control

  • [требует возврат] установить в true
  • [Многострочный] в true
  • [Авто HScroll] в true
  • [Прокрутка по вертикали] в true

Добавляем к первому полю переменную input типа CString, ко второму полю добавляем переменную output типа CString. Добавляем просто кликнув правой клавишей мышки по диалогу и выбираем добавить переменную, а там уже выбираем что за переменную и куда добавить, выбираем переменную элемента управления, выбираем какой элемент управления, там будет в списке 3 элемента управления так как в диалоговом окне имеется 3 элемента всего лишь, ну и выбираем в какой класс добавить. Потом для кнопки добавляем обработчик собития и от его код.

void Ctest_prog1Dlg::OnBnClickedButton1()
{
	//получаем данные из формы и выводим в форму
	UpdateData(true); //метод для считывания данных из контролов окна
	CString str;
	str.Format(_T("%s"),input);// добавляем данные из input в str
	str=_T("[")+str+_T("]");//добавляем в скобки
	str+="rnhellow world!rn";
	str+="3 strokarn";
	output=str;
	UpdateData(false);//возвращаем данные в диалоговое окно
}

Вывод при нажатии на кнопку start

mfc Edit Control1В коде выше самые главные функция это UpdateData, эта функция с параметром true получает данные из элементов управления диалогового окна и с параметром false возвращает данные в диалоговое окно, то есть мы создали две переменные для наших элементов управления Edit Control input и output, после вызова UpdateData(true) в них попадают элементы со значениями из диалога, дальше мы их меняем, можем просто очистить верхнее поле присвоив input пустую строку, но мы как бы копируем данные из input в переменную str, затем чуточку эту переменную форматируем и дальше отправляем в переменную ouput присвоив output=str, затем вызываем функцию UpdateData(false) и после этого уже данные из этих переменных передаются в диалоговое окно, как бы изменяются.

Вывод в EditControl постоянно

Приведу пример кода как непрерывно выводить в EditControl, для этого мы создаем переменную CString m_cBuffer и создаем переменную управления для CEdit m_Edit1. Добавляем таймер. вот код который в таймере

void Ctest_edit_controlDlg::OnTimer(UINT_PTR nIDEvent)
{
	// TODO: добавьте свой код обработчика сообщений или вызов стандартного
	if(nIDEvent==1)
	{
		if(m_cBuffer.GetLength()>3000)
			m_cBuffer.Delete(0,m_cBuffer.GetLength()-2000);
		
		UpdateData(TRUE);
		m_cEdit1=m_cBuffer;
		UpdateData(FALSE);
		
		CWnd* hEdit = GetDlgItem(IDC_EDIT1); // Получаем дескриптор контрола.
		int ndx = hEdit->GetWindowTextLength();
		hEdit->SendMessage(EM_SETSEL,(WPARAM)ndx, (LPARAM)ndx);
		hEdit->SendMessage ( EM_REPLACESEL, 0, (LPARAM) ((LPSTR) L"n"));
		
		MSG message;
		//обработка сообщений
        while(::PeekMessage(&message,NULL,0,0,PM_REMOVE))
        {
            ::TranslateMessage(&message);
            ::DispatchMessage(&message);
        }
		if(!m_bTimer){KillTimer(1);}
	}
	

	CDialogEx::OnTimer(nIDEvent);
}

И кнопка

void Ctest_edit_controlDlg::OnBnClickedButton1()
{
	// TODO: добавьте свой код обработчика уведомлений
	SetTimer(1,2000,NULL);
	m_bTimer=TRUE;
	MSG message;
	for(int i=0;i<10000;i++)
	{
		CProgressCtrl* pBar = (CProgressCtrl*) GetDlgItem(IDC_PROGRESS1);
        TRACE("i=%dn",i);
        pBar->SetPos((i+1)*100/10000);
		CString s; s.Format(L" %d ",i);
		m_cBuffer.Append(s);
         
        //обработка сообщений
        if(::PeekMessage(&message,NULL,0,0,PM_REMOVE))
        {
            ::TranslateMessage(&message);
            ::DispatchMessage(&message);
        }	
	}
	m_bTimer=FALSE;
}

Вывод:

test

 

Combo Box »

Почитать можно тут.

Progress Control »

Разберем диалоговое приложение

Это полоса прогресса. Вот скрин с ней.

MFC Progress ControlОбработчик кнопки старт вот его код

void Ctest_progressDlg::OnBnClickedButton1()
{
	// TODO: добавьте свой код обработчика уведомлений
	MSG message;
	
	for(int i=0;i<10000;i++)
	{
		CProgressCtrl* pBar = (CProgressCtrl*) GetDlgItem(IDC_PROGRESS1);
		TRACE("i=%dn",i);
		pBar->SetPos((i+1)*100/10000);
		
		//обработка сообщений
		if(::PeekMessage(&message,NULL,0,0,PM_REMOVE))
		{
			::TranslateMessage(&message);
			::DispatchMessage(&message);
		}
	}
}

нас интересуют вот эти функции

CProgressCtrl* pBar = (CProgressCtrl*) GetDlgItem(IDC_PROGRESS1);
pBar->SetPos((i+1)*100/10000);

Мы получаем доступ к диалоговому элементу IDC_PROGRESS1, а дальше функцией SetPos устанавливаем как он будет отображаться, эта функция принимает значение от 0 до 100, 100 это полностью загружена полоса прогресса, а 0 это ничего не загружено. Посмотреть примеры с использованием Progress Control можно тут и тут.

Элемент управления MFC link »

Добавляет ссылку на диалог.

MFC link

Radio Button »

Почитать за него можно тут.

 

Использование таймера в MFC сообщение WM_TIMER

Показать »

 

Для того чтобы создать таймер нужно:

1. Создаем идентификатор таймера

#define ID_TIMER_1 100

2. В объявлении класса окна диалога добавляем функцию – реакцию на таймер

afx_msg void OnTimer(UINT);// функция реакции на таймер

3. В карте сообщений добавляем реакцию на таймер

ON_WM_TIMER() // реагировать на таймер

4. Реализация функции ответа на таймер

void Ctest_timerDlg::OnTimer( UINT uTime)
{
//	AfxMessageBox(L"Timer !");
	UpdateData(true);//получаем данные
	stringstream stream;
	stream <<m_count;
	m_output=stream.str().c_str();
	UpdateData(false);//возвращаем данные в диалог
	m_count++;//увеличиваем счетчик
	if(m_count>=100)
		KillTimer(ID_TIMER_1);
}

5. Реализация функции при нажатии на кнопку

void Ctest_timerDlg::OnBnClickedButton1()
{
	if (!Test)// если таймер не установлен
	{
		Test=true;// установить его (логически)
		SetTimer(ID_TIMER_1,500,NULL);// а теперь физически
	}
	else// а иначе (установлен)
	{
		Test=false;// убить логически
		KillTimer(ID_TIMER_1);// физически	
	}
}

Таймер запускается с помощью функции SetTimer(ID_TIMER_1, 500, NULL); , где ID_TIMER_1 – это идентификатор таймера, 500 это время в миллисекундах ( 1 секунда – 1000 миллисекунд). Третий параметр это указатель на callback-функцию.

 Как послать и принять свое собственное сообщение ON_MESSAGE

Показать »

  1. http://www.firststeps.ru/mfc/steps/r.php?285
  2. https://msdn.microsoft.com/ru-ru/library/k35k2bfs.aspx
  3. http://www.firststeps.ru/mfc/steps/r.php?284

В MFC судествуют пользовательские сообщения – это такие сообщения которые создает сам пользователь.

Чтобы создать сообщение нужно:

1. Определить идентификатор сообщения

//собственный идентификатор
#define WM_MYMESSAGE (WM_USER + 101)

2. Создаем функцию которая будет вызываться на наше сообщение

//собственная функция, которая вызывается на свое сообщение
afx_msg LRESULT OnMyMessage(WPARAM wParam, LPARAM lParam);//собственная функция

3. Создаем определение собственной функции

LRESULT Ctest_timerDlg::OnMyMessage(WPARAM wParam, LPARAM lParam)
{
   UNREFERENCED_PARAMETER(wParam);
   UNREFERENCED_PARAMETER(lParam);

   // Handle message here. 
   AfxMessageBox(L"hellow world!");


   return 0;
}

4.  Добавляем в карту сообщений реакцию на собственное сообщение

ON_MESSAGE(WM_MYMESSAGE, OnMyMessage)//собственная функция

5. И теперь просто посылаем наше сообщение в очередь сообщений в обработчике нашей кнопки

void Ctest_timerDlg::OnBnClickedButton2()
{
	for(int i=0;i<10;i++)
	{
		Sleep(1000);
		PostMessage(WM_MYMESSAGE,0,0);//посылаем собвственное сообщение в диалоговое окно
	}
}

выше в функции цикл захватывает весь процесс и у нас получается что программка как бы виснет, а все это происходит потому что цикл блокирует программой получение сообщений.

 

MFC создание потока и передача данных в диалог с помощью передачи своего собственного сообщения ON_MESSAGE

Показать »

  1. http://www.sources.ru/cpp/faqs/41.htm

У нас есть в диалоге поле редактирование Edit Controll и нам нужно допустим вывести в него цикл. Ну то есть постепенно обновлять это поле и следить на каком этапе находится программа. В общем создаем два файла в которых у нас будет наша функция потока. Как оказалось в классе диалога функцию потока создать нельзя, потому что ошибка появляется, поэтому мы в отдельном файле создаем.

function.h

#pragma once

#include "stdafx.h"

//флаг который говорит что поток запущен или нет
extern bool bThreadstop;
extern int data;//счетчик, может быть что угодно

//Потоковая функция обычная вне класса
UINT ThreadProc(LPVOID param);
//останавливает поток
void stopThread();

function.cpp

#pragma once
#include "stdafx.h"

#include "function.h"

bool bThreadstop=false;
int data=0;
//идентификатор сообщения которое будет посылатся когда
//останавливается поток
const int WM_THREADENDED = WM_USER+1;
//идентификатор сообщения которое будет посылатся в цикле из потока
const int WM_MYMESSAGE = WM_USER + 101;

//Потоковая функция обычная вне класса
UINT ThreadProc(LPVOID param)  //Создание потоковой функции 
{
    ::MessageBox((HWND)param, L"Thread activated",L"Message from thread",MB_OK);
    while(!bThreadstop)
    {
		//Выполнение опреаций
		data++;
		Sleep(4000);
		//посылаем сообщение в диалог, то есть мы обновляем диалог
		::PostMessage((HWND)param,WM_MYMESSAGE,(WPARAM)param,0); //Сообщение
   
    }

	//посылаем сообщение указывающее на то что диалог завершился
	::PostMessage((HWND)param,WM_THREADENDED,(WPARAM)param,0); //Сообщение
    ::MessageBox((HWND)param, L"Thread ended",L"Message from thread",MB_OK);
    return 0;
}

//останавливает поток
void stopThread()
{
	bThreadstop=true;
}

И в самом диалоге создаем поле редактирования и две кнопки, по нажатию на первую будет запускаться наш поток, по нажатию на вторую будет выход из потока.

Да идентификаторы сообщения должны быть и в классе нашего диалога

dialogтак же добавим в карту сообщений две строчки

test_timerDlg.cpp

ON_MESSAGE(WM_MYMESSAGE, OnMyMessage)//собственная функция

ON_MESSAGE(WM_THREADENDED,OnThreadEnded)

сами функции которые будут вызываться по нашим сообщениям объявим в заголовочном файле

test_timerDlg.h

//собственная функция, которая вызывается на свое сообщение
afx_msg LRESULT OnMyMessage(WPARAM wParam, LPARAM lParam);//собственная функция
//функция обработчик своего сообщения
afx_msg LONG OnThreadEnded(WPARAM wParam,LPARAM lParam);

И определение в cpp файле

test_timerDlg.cpp

//функция которая вызывается при остановке потока
LONG Ctest_timerDlg::OnThreadEnded(WPARAM wParam, LPARAM lParam)
{
    ::MessageBox((HWND)wParam,L"Thread Ended",L"Message from thread", MB_OK);
	return 0;
}

//функция которая вызывается на сообщения из бесконечного цикла потока
LRESULT Ctest_timerDlg::OnMyMessage(WPARAM wParam, LPARAM lParam)
{
   UNREFERENCED_PARAMETER(wParam);
   UNREFERENCED_PARAMETER(lParam);

//	AfxMessageBox(L"mu tyt");
	UpdateData(true);//получаем данные
	stringstream stream;
	stream <<data;
//переменная поля редактирования
	m_output=stream.str().c_str();
	UpdateData(false);//возвращаем данные в диалог
	
   return 0;
}

и добавим функции обработчики кнопок

//запускает поток
void Ctest_timerDlg::OnBnClickedButton3()
{
	bThreadstop=false;
	//создаем поток
	AfxBeginThread(ThreadProc,GetSafeHwnd()); //Запуск потока
}
//останавливает поток
void Ctest_timerDlg::OnBnClickedButton4()
{
	//выключаем поток
	stopThread();
}

Запускаем программу и мы можем запускать и останавливать поток.

Обозначения переменных в MFC

Показать »

  1. http://www.firststeps.ru/mfc/steps/r.php?297
Префикс Тип Пример
С Класс или структура CPoint, CPrintInfo
m_ переменная член класса m_pDoc

Ктирические секции в потоках

Показать »

Разберем пример блокировки потоков с помощью критический секций. В MFC есть класс CCriticalSection для этого.

Создаем обычное диалоговое приложение MFC, дальше добавляем определение процедуры потока

int g_nCount=0;
CCriticalSection g_cs;//создаем критическую секцию
UINT ProgThread(LPVOID pParam)
{
	for(g_nCount=0;g_nCount<100000000;)
	{
		TRACE("g_nCount=%dn",g_nCount);
		g_cs.Lock();//блокируем поток
		g_nCount++;
		g_cs.Unlock();//разблокирует поток
	}

	return 0;
}

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

Добавляем кнопку “start”

void Ctest_CCriticalDlg::OnBnClickedStart()
{
	// TODO: добавьте свой код обработчика уведомлений
	AfxBeginThread(ProgThread,GetSafeHwnd());//запускаем поток
	GetDlgItem(IDC_START)->EnableWindow(FALSE);
}

и переопределяем кнопку “Отмена”

void Ctest_CCriticalDlg::OnBnClickedCancel()
{
	// TODO: добавьте свой код обработчика уведомлений
	if(g_nCount!=0)
	{
		g_nCount=100000000;
	}
	GetDlgItem(IDC_START)->EnableWindow(TRUE);

//	CDialogEx::OnCancel();
}

При нажатии на start у нас запускается поток, и блокируется кнопка, при нажатии на “Отмена” поток завершается и с данными будет порядок.

Скрыть кнопку и изменить текст

Показать »

GetDlgItem(IDC_START)->EnableWindow(FALSE);
GetDlgItem(IDC_START)->SetWindowTextW(L"Login...");

IDC_START-идентификатор кнопки

Ключевое слово volatile

Показать »

это слово запрещает компилятору оптимизировать код

например код

volatile int nTemp;
for(int i=0;i<10;i++)
{
	for(nTemp=0;nTemp<100;nTemp++)
	{}//просто занимаем процесорное время
	TRACE("hellow world!n");
}

в данном примере внутренний цикл бесполезный и если будет без volatile то компилятор просто проигнорирует этот код, а так он заставит этот бесполезный код выполнится.

CComQIPtr умные указатели

Показать »

CComQIPtr<IHTMLDocument3,&IID_IHTMLDocument3> pADocument3;
IDispatch* pdispTmpVal3;
 
pIWeb->get_Document(&pdispTmpVal3);//получаем документ
pADocument3 = pdispTmpVal3;

Запуск команды из командной стоки system

Показать »

Данный код удаляет журнал IE, запускается cmd.exe с параметром 🙂

system("cmd.exe /C RunDll32.exe InetCpl.cpl,ClearMyTracksByProcess 255");

Завершение MFC программы на основе диалогового окна

Показать »

По нажатию на крестик, должна завершится программа, нам нужно перегрузить функцию OnCancel и добавить в нее код

void Ctest_fl_ruDlg::OnCancel()
{
	// TODO: добавьте специализированный код или вызов базового класса
	::SendMessage(GetSafeHwnd(),WM_CLOSE,NULL,NULL);
	//::PostMessage(GetSafeHwnd(),WM_CLOSE,NULL,NULL);
	CDialogEx::OnCancel();
}

Получить изображение из буфера и сохранить его в формате png

Показать »

код копирует из буфера изображение и дальше сохраняем его

// 11. читаем из буфера битмеп
if ( !OpenClipboard() )//открываем буфер
{AfxMessageBox( _T("Cannot open the Clipboard") );return;}
HGLOBAL hGlob=NULL;
hGlob=::GetClipboardData(CF_BITMAP);
if(hGlob==NULL)AfxMessageBox(L"hGlob==NULL");
CloseClipboard();//закрываем буфер
//------------------------------

// 12. сохраняем изображение из буфера в виде png файла
CBitmap* m_pBitmap=(CBitmap*)hGlob;
CImage img;
img.Attach(HBITMAP(m_pBitmap));
img.Save(L"img.png");
//------------------------------

Код удаляет из буфера данные

// Remove the current Clipboard contents
   if( !EmptyClipboard() )
   {
      AfxMessageBox( _T("Cannot empty the Clipboard") );
      return;
   }

MFC работа с реестром, добавление значений CRegKey и работа с интернетом, установка прокси и удаление

Показать »

Почитать за то как добавить в реестр можно тут.  Там третий подпункт, про то как изменять прокси.

тут будет пример который добавляет прокси вот часть кода

CRegKey key;
if(key.Open(HKEY_CURRENT_USER, L"Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings")!=ERROR_SUCCESS)
{AfxMessageBox(L"don't open reg key");return;}
if(key.SetDWORDValue(L"MigrateProxy",1)!=ERROR_SUCCESS){AfxMessageBox(L"don't open MigrateProxy");return;}
if(key.SetDWORDValue(L"ProxyEnable",1)!=ERROR_SUCCESS){AfxMessageBox(L"don't open ProxyEnable");return;}
if(key.SetDWORDValue(L"ProxyHttp1.1",0)!=ERROR_SUCCESS){AfxMessageBox(L"don't open ProxyHttp1.1");return;}
if(key.SetStringValue(L"ProxyServer",url)!=ERROR_SUCCESS){AfxMessageBox(L"don't open ProxyServer");return;}
if(key.SetStringValue(L"ProxyOverride",L"<local>")!=ERROR_SUCCESS){AfxMessageBox(L"don't open ProxyOverride");return;}      
key.Close();
InternetSetOption(NULL, INTERNET_OPTION_SETTINGS_CHANGED, NULL, 0);
InternetSetOption(NULL, INTERNET_OPTION_REFRESH , NULL, 0);

а тут код который возвращает данные обратно

CRegKey key;
if(key.Open(HKEY_CURRENT_USER, L"Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings")!=ERROR_SUCCESS)
{AfxMessageBox(L"don't open reg key");return;}
if(key.SetDWORDValue(L"ProxyEnable",0)!=ERROR_SUCCESS){AfxMessageBox(L"don't open ProxyEnable");return;}
if(key.SetDWORDValue(L"ProxyHttp1.1",1)!=ERROR_SUCCESS){AfxMessageBox(L"don't open ProxyHttp1.1");return;}
key.Close();
InternetSetOption(NULL, INTERNET_OPTION_SETTINGS_CHANGED, NULL, 0);
InternetSetOption(NULL, INTERNET_OPTION_REFRESH , NULL, 0);

MFC создание процесса CreateProcess и получение информации из процесса через пайп

Показать »

Почитать за функцию CreateProcess можно на мсдн тут  и еще тут и тут. Так же есть пример где описано как создавать пайп для stdout и stdin полный пример за него можно почитать тут, и у меня ниже он будет приведен. Вот мой пример без берегрузки stdIn

Почитать можно темы на форумах

  1. http://www.cyberforum.ru/cpp-beginners/thread1501793-page2.html
  2. http://programmersforum.ru/showthread.php?t=281781

Синтаксис вызовод, часто просто не получается создать процесс, поэтому я добавлю как получается вызывать

Так командная строка вызыывается

TCHAR szCmdline[]=L"recognition.exe img.png";
//создаем дочерний процесс
if (!CreateProcess(NULL,szCmdline,NULL,NULL,TRUE,HIGH_PRIORITY_CLASS,
                     NULL,NULL,&si,&pi))

и просто с указанием программы

TCHAR szCmdline[]=L"recognition.exe img.png";
//создаем дочерний процесс
if (!CreateProcess(L"recognition.exe",szCmdline,NULL,NULL,TRUE,HIGH_PRIORITY_CLASS,
                     NULL,NULL,&si,&pi))

Второй параметр должен быть доступен для записи вроде, поэтому мы так делаем.

 

Удаляем процесс

//завершаем процесс	
::TerminateProcess(pi.hProcess,1);
::WaitForSingleObject(pi.hProcess, INFINITE); // ждем завершения

 

 

void Cgov_plDlg::OnBnClickedCreateprocess()
{
	// TODO: добавьте свой код обработчика уведомлений
	char buf[1024];           //буфер ввода/вывода



  STARTUPINFO si;
  SECURITY_ATTRIBUTES sa;
  PROCESS_INFORMATION pi;

  HANDLE newstdout,read_stdout;  //дескрипторы
                                                      // пайпов

  sa.lpSecurityDescriptor = NULL;

  sa.nLength = sizeof(SECURITY_ATTRIBUTES);
  sa.bInheritHandle = true;       //разрешаем наследование дескрипторов

  if (!CreatePipe(&read_stdout,&newstdout,&sa,0)) //создаем пайп
                                                  // для stdout
  {
    AfxMessageBox(L"CreatePipe");
    return;
  }



  GetStartupInfo(&si);      //создаем startupinfo для
                            // дочернего процесса

  /*

  Параметр dwFlags сообщает функции CreateProcess
  как именно надо создать процесс.

  STARTF_USESTDHANDLES управляет полями hStd*.
  STARTF_USESHOWWINDOW управляет полем wShowWindow.

  */

  si.dwFlags = STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW;
  si.wShowWindow = SW_HIDE;
  si.hStdOutput = newstdout;
  si.hStdError = newstdout;   //подменяем дескрипторы для

 // char app_spawn[] = L"d:\winnt\system32\cmd.exe"; //это просто
                                                     // пример,
                                                     //замените на то,
                                                     // что вам нужно



  //создаем дочерний процесс
  if (!CreateProcess(L"recognition.exe",L"recognition.exe img.png",NULL,NULL,TRUE,HIGH_PRIORITY_CLASS,
                     NULL,NULL,&si,&pi))
  {
    AfxMessageBox(L"CreateProcess");
    CloseHandle(newstdout);
    CloseHandle(read_stdout);
    return;
  }



  unsigned long exit=0;  //код завершения процесса
  unsigned long bread;   //кол-во прочитанных байт
  unsigned long avail;   //кол-во доступных байт



  std::fill(buf,buf+1024,0);

  for(;;)      //основной цикл программы
  {
    GetExitCodeProcess(pi.hProcess,&exit); //пока дочерний процесс
                                           // не закрыт
    if (exit != STILL_ACTIVE)
      break;

    PeekNamedPipe(read_stdout,buf,1023,&bread,&avail,NULL);

    //Проверяем, есть ли данные для чтения в stdout

    if (bread != 0)
    {
      std::fill(buf,buf+1024,0);
      if (avail > 1023)
      {
        while (bread >= 1023)
        {
          ReadFile(read_stdout,buf,1023,&bread,NULL);  //читаем из
                                                       // пайпа stdout
		  CString str;str.Format(L"%S",buf);
		  AfxMessageBox(str);
          std::fill(buf,buf+1024,0);
        }
      }

      else {
        ReadFile(read_stdout,buf,1023,&bread,NULL);
        CString str;str.Format(L"%S",buf);
		AfxMessageBox(str);
      }
	}
  }

  CloseHandle(pi.hThread);
  CloseHandle(pi.hProcess);           //небольшая уборка за собой
  CloseHandle(newstdout);
  CloseHandle(read_stdout);
  AfxMessageBox(L"exit");
}

и от полностью пример с перегрузкой этих stdout и stdin

//------------Пример использования CreateProcess и Anonymous Pipes------

// childspawn.cpp
// Приложение запускает shell и перехватывает его ввод/вывод

//---------------------use freely---------------------------------------

#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include <string.h>
#pragma hdrstop
#include <condefs.h>



#define bzero(a) memset(a,0,sizeof(a)) //для сокращения писанины



bool IsWinNT()  //проверка запуска под NT
{
  OSVERSIONINFO osv;
  osv.dwOSVersionInfoSize = sizeof(osv);
  GetVersionEx(&osv);
  return (osv.dwPlatformId == VER_PLATFORM_WIN32_NT);
}



void ErrorMessage(char *str)  //вывод подробной информации об ошибке
{

  LPVOID msg;

  FormatMessage(
    FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
    NULL,
    GetLastError(),
    MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // язык по умолчанию
    (LPTSTR) &msg,
    0,
    NULL
  );

  printf("%s: %sn",str,msg);
  LocalFree(msg);

}



//----------------------------------------------------------------------

void main()

{

  char buf[1024];           //буфер ввода/вывода



  STARTUPINFO si;
  SECURITY_ATTRIBUTES sa;
  SECURITY_DESCRIPTOR sd;        //структура security для пайпов
  PROCESS_INFORMATION pi;

  HANDLE newstdin,newstdout,read_stdout,write_stdin;  //дескрипторы
                                                      // пайпов


  if (IsWinNT())        //инициализация security для Windows NT
  {
    InitializeSecurityDescriptor(&sd,SECURITY_DESCRIPTOR_REVISION);
    SetSecurityDescriptorDacl(&sd, true, NULL, false);
    sa.lpSecurityDescriptor = &sd;
  }

  else sa.lpSecurityDescriptor = NULL;

  sa.nLength = sizeof(SECURITY_ATTRIBUTES);
  sa.bInheritHandle = true;       //разрешаем наследование дескрипторов


  if (!CreatePipe(&newstdin,&write_stdin,&sa,0))   //создаем пайп
                                                   // для stdin
  {
    ErrorMessage("CreatePipe");
    getch();
    return;
  }

  if (!CreatePipe(&read_stdout,&newstdout,&sa,0)) //создаем пайп
                                                  // для stdout
  {
    ErrorMessage("CreatePipe");
    getch();
    CloseHandle(newstdin);
    CloseHandle(write_stdin);
    return;
  }



  GetStartupInfo(&si);      //создаем startupinfo для
                            // дочернего процесса

  /*

  Параметр dwFlags сообщает функции CreateProcess
  как именно надо создать процесс.

  STARTF_USESTDHANDLES управляет полями hStd*.
  STARTF_USESHOWWINDOW управляет полем wShowWindow.

  */

  si.dwFlags = STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW;
  si.wShowWindow = SW_HIDE;
  si.hStdOutput = newstdout;
  si.hStdError = newstdout;   //подменяем дескрипторы для
  si.hStdInput = newstdin;    // дочернего процесса

  char app_spawn[] = "d:\winnt\system32\cmd.exe"; //это просто
                                                     // пример,
                                                     //замените на то,
                                                     // что вам нужно



  //создаем дочерний процесс

  if (!CreateProcess(app_spawn,NULL,NULL,NULL,TRUE,CREATE_NEW_CONSOLE,
                     NULL,NULL,&si,&pi))
  {
    ErrorMessage("CreateProcess");
    getch();
    CloseHandle(newstdin);
    CloseHandle(newstdout);
    CloseHandle(read_stdout);
    CloseHandle(write_stdin);
    return;
  }



  unsigned long exit=0;  //код завершения процесса
  unsigned long bread;   //кол-во прочитанных байт
  unsigned long avail;   //кол-во доступных байт



  bzero(buf);

  for(;;)      //основной цикл программы
  {
    GetExitCodeProcess(pi.hProcess,&exit); //пока дочерний процесс
                                           // не закрыт
    if (exit != STILL_ACTIVE)
      break;

    PeekNamedPipe(read_stdout,buf,1023,&bread,&avail,NULL);

    //Проверяем, есть ли данные для чтения в stdout

    if (bread != 0)
    {
      bzero(buf);
      if (avail > 1023)
      {
        while (bread >= 1023)
        {
          ReadFile(read_stdout,buf,1023,&bread,NULL);  //читаем из
                                                       // пайпа stdout
          printf("%s",buf);
          bzero(buf);
        }
      }

      else {
        ReadFile(read_stdout,buf,1023,&bread,NULL);
        printf("%s",buf);
      }
    }

    if (kbhit())      //проверяем, введено ли что-нибудь с клавиатуры
    {
      bzero(buf);
      *buf = (char)getche();

      //printf("%c",*buf);

      WriteFile(write_stdin,buf,1,&bread,NULL); //отправляем это
                                                // в stdin

      if (*buf == 'r') {
        *buf = 'n';
        printf("%c",*buf);
        WriteFile(write_stdin,buf,1,&bread,NULL); //формирум конец
                                                  //строки, если нужно

      }
    }
  }

  CloseHandle(pi.hThread);
  CloseHandle(pi.hProcess);
  CloseHandle(newstdin);            //небольшая уборка за собой
  CloseHandle(newstdout);
  CloseHandle(read_stdout);
  CloseHandle(write_stdin);
}

//----------------------------EOF-----------------------------------

MFC преобразование из CStringW в char

Показать »

Почитать за преобразования различных типов можно тут. Функция которая преобразует CStringW в char

//преобразовывает CStringW в Char
char* CStringW_to_char(CStringW str)
{
    const size_t newsizew = (str.GetLength() + 1)*2;
    char *nstringw = new char[newsizew];
    size_t convertedCharsw = 0;
    wcstombs_s(&convertedCharsw, nstringw, newsizew, str, _TRUNCATE );
    return nstringw;
}

 CStdioFio запись в файл и чтение из файла

Показать »

//чтение и запись в файл
	CStdioFile file;
	if(!file.Open(L"proxy.txt",CFile::modeRead))
	{AfxMessageBox(L"don't open file proxy.txt");return;}
	CString str;
	CString temp;
	while(file.ReadString(temp))str+=temp+L"n";
	AfxMessageBox(str);
	file.Close();
	
	//запись в файл
	CFileStatus status;
	if(CFile::GetStatus( L"proxy1.txt", status))
	{
		if(!file.Open(L"proxy1.txt",CFile::modeReadWrite))
		{AfxMessageBox(L"don't open file proxy1.txt"); return;}
	}
	else
	{
		if(!file.Open(L"proxy1.txt",CFile::modeReadWrite|CFile::modeCreate))
		{AfxMessageBox(L"don't open file proxy1.txt"); return;}
	}
	file.Seek(0,CFile::end);
	file.WriteString(str);

Диалоговое окошко выбора файла CFileDialog

Показать »

CFileDialog fileDialog(TRUE,NULL,L"*.txt");	//объект класса выбора файла
int result = fileDialog.DoModal();	//запустить диалоговое окно
if (result==IDOK)	//если файл выбран
{
	m_cEditPath=fileDialog.GetPathName();
	UpdateData(FALSE);//обновляем данные
//	AfxMessageBox(fileDialog.GetPathName()); // показать полный путь
}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

и кнопка которая запускает

Комментарии:


Оставить комментарий

Your email address will not be published. Required fields are marked *