Kselax.ru

Hacker Kselax — the best hacker in the world

Menu
  • Блог
  • Контакты
  • wp plugin генератор
  • Русский
    • Русский
    • English
Menu

Создание мини-сервера на базе MFC

Posted on 30 июля, 2015 by admin

Для создания мини-сервера на базе MFC особых познаний в OLE не требуется. Этот пример покажет взаимодействие компонентов и контейнеров. В данном случае мы создадим не сложный компонент. Он просто выводит в окно некоторый текст и графику. Текст хранится в документе, и для его редактирования предусмотрено диалоговое окно. Приступаем к созданию приложения компонента (мини-сервера)

1. Создание каркаса приложения мини-сервер

Запускаем Visual Studio 2010, заходим в меню «Файл» -> «Создать» -> «Проект…», в появившемся окошке «Создать проект» выбираем «Приложение MFC» и вводим имя проекта «MyMini-server»

mfc create project

нажимаем «Ок», в появившемся окошке «Мастер приложений MFC» жмем «Далее» в появившемся окошке выставляем

mfc application withord

жмем кнопку «Далее», в появившемся окошке выставляем «Мини сервер»

mfc application withart1

и жмем кнопку «Готово». У нас мастер сгенерирует приложение со следующими файлами

mfc workspace

у нас создались файлы класса вида и класса документа наследника не от CDocument,  а наследуется уже от COleServerDocEx и создалось два новых класса class CInPlaceFrame : public COleIPFrameWndEx это вороде отрисовывает окно в контейнере и class CMyMiniserverSrvrItem : public COleServerItem — а этот вроде как класс вида выступает в контейнере.

2. Создание самого приложения

Добавим в класс документа открытую переменную типа CString m_strText, а в функции члене документа CMyMiniserverDoc::OnNewDocumen задайте начальное значение этой переменной «Initial default text».

1
2
3
4
5
6
7
8
9
10
11
BOOL CMyMiniserverDoc::OnNewDocument()
{
if (!COleServerDocEx::OnNewDocument())
return FALSE;
 
// TODO: добавьте код повторной инициализации
// (Документы SDI будут повторно использовать этот документ)
m_strText="initial default text";
 
return TRUE;
}

Создадим новое диалоговое окошко, вот его вид

mfc dialog

добавим к нему класс CTextDialog, производный от CDialog. Не забудьте включить файл диалогового окна в файл MyMini-serverDoc.cpp. И добавим к диалогу переменную для поля ввода CString m_strText (добавим ее в CTextDialog), вот код файлов нашего сгенерированого диалога и с добавленной переменной

TextDialog.h »

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#pragma once
 
 
// диалоговое окно CTextDialog
 
class CTextDialog : public CDialog
{
DECLARE_DYNAMIC(CTextDialog)
 
public:
CTextDialog(CWnd* pParent = NULL);   // стандартный конструктор
virtual ~CTextDialog();
 
// Данные диалогового окна
enum { IDD = IDD_DIALOG1 };
 
protected:
virtual void DoDataExchange(CDataExchange* pDX);    // поддержка DDX/DDV
 
DECLARE_MESSAGE_MAP()
public:
CString m_strText;
};

TextDialog.cpp »

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
// TextDialog.cpp: файл реализации
//
 
#include "stdafx.h"
#include "MyMini-server.h"
#include "TextDialog.h"
#include "afxdialogex.h"
 
 
// диалоговое окно CTextDialog
 
IMPLEMENT_DYNAMIC(CTextDialog, CDialog)
 
CTextDialog::CTextDialog(CWnd* pParent /*=NULL*/)
: CDialog(CTextDialog::IDD, pParent)
, m_strText(_T(""))
{
 
}
 
CTextDialog::~CTextDialog()
{
}
 
void CTextDialog::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
DDX_Text(pDX, IDC_EDIT1, m_strText);
}
 
 
BEGIN_MESSAGE_MAP(CTextDialog, CDialog)
END_MESSAGE_MAP()
 
 
// обработчики сообщений CTextDialog

Добавим в меню для внедряемого компонента IDR_SRVR_EMBEDDED новый пункт меню под названием «IDR_SRVR_EMBEDDED» и к нему добавьте подпункт «Modify», для меню активизируемого по месту IDR_SRVR_INPLACE новый пункт меню под названием «IDR_SRVR_INPLACE» и к нему добавьте подпункт «Modify». Сделайте одинаковые идентификаторы обоих пунктов меню что в одном меню что в другом, присвойте ему название ID_MODIFY. Дальше используя «мастер классов» создайте обработчик для пунктов меню onModify в классе документа. Код обработчика onModify выглядит так

1
2
3
4
5
6
7
8
9
10
11
12
13
void CMyMiniserverDoc::OnModify()
{
// TODO: добавьте свой код обработчика команд
CTextDialog dlg;
dlg.m_strText=m_strText;
if(dlg.DoModal()==IDOK)
{
m_strText=dlg.m_strText;
UpdateAllViews(NULL);//инициирует вызов CMyMiniserverView::OnDraw
UpdateAllItems(NULL);//инициирует вызов CMyMiniserverSrvItem::OnDraw
SetModifiedFlag();//эту функцию нужно вызывать после любого изменения документа
}
}

за функцию SetModifiedFlag почитать можно тут.

Переопределим функцию OnPrepareDC

1
2
3
4
5
6
7
void CMyMiniserverView::OnPrepareDC(CDC* pDC, CPrintInfo* pInfo)
{
// TODO: добавьте специализированный код или вызов базового класса
pDC->SetMapMode(MM_HIMETRIC);
 
CView::OnPrepareDC(pDC, pInfo);
}

за функцию OnPrepareDC почитать можно тут.

Отредактируем функцию OnDraw в классе «вид». Следующий код выводит в центр клиентского прямоугольника окружность диаметром 2 см и текст (с переносом строк чтобы он умещался в окне)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
void CMyMiniserverView::OnDraw(CDC* pDC)
{
CMyMiniserverDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc)
return;
 
// TODO: добавьте здесь код отрисовки для собственных данных
CFont font;
font.CreateFontW(-500,0,0,0,400,FALSE,FALSE,0,ANSI_CHARSET,OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,DEFAULT_PITCH|FF_SWISS,L"Arial");
CFont* pFont=pDC->SelectObject(&font);
CRect rectClient;
GetClientRect(rectClient);
CSize sizeClient=rectClient.Size();
pDC->DPtoHIMETRIC(&sizeClient);
CRect rectEllipse(sizeClient.cx/2-1000,-sizeClient.cy/2+1000,
sizeClient.cx/2+1000, -sizeClient.cy/2-1000);
pDC->Ellipse(rectEllipse);
pDC->TextOutW(0,0,pDoc->m_strText);
pDC->SelectObject(pFont);
}

Дальше отредактируем функцию OnDraw серверного элемента. Следующий код пытается изобразить тоже что и функция OnDraw класса «вид»

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
BOOL CMyMiniserverSrvrItem::OnDraw(CDC* pDC, CSize& rSize)
{
if (!pDC)
return FALSE;
 
// Удалите этот код, если вы используете rSize
UNREFERENCED_PARAMETER(rSize);
 
CMyMiniserverDoc* pDoc=GetDocument();//получаем документ
 
// TODO: задайте режим отображения и величину
//  (Величина обычно совпадает с размером, возвращенным из OnGetExtent)
pDC->SetMapMode(MM_ANISOTROPIC);
pDC->SetWindowOrg(0,0);
pDC->SetWindowExt(3000, -3000);
 
// TODO: добавьте код отрисовки. Кроме того, заполните величину HIMETRIC.
//  Все рисунки производятся в контексте устройства метафайла (pDC).
CFont font;
font.CreateFont(-500, 0, 0, 0, 400, FALSE, FALSE, 0,
                ANSI_CHARSET, OUT_DEFAULT_PRECIS,
                CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
                DEFAULT_PITCH | FF_SWISS, L"Arial");
    CFont* pFont = pDC->SelectObject(&font);
    CRect rectEllipse(CRect(500, -500, 2500, -2500));
    pDC->Ellipse(rectEllipse);
    pDC->TextOut(0, 0, pDoc->m_strText);
    pDC->SelectObject(pFont);
 
return TRUE;
}

Отредактируем функцию Serialize класса документа. О загрузке и сохранении текста документа в потоке данных Contents в основном хранилище объекта заботится каркас приложений. Все что требуется от нас это написать обычный код сериализации.

1
2
3
4
5
6
7
8
9
10
11
12
13
void CMyMiniserverDoc::Serialize(CArchive& ar)
{
if (ar.IsStoring())
{
// TODO: добавьте код сохранения
ar << m_strText;
}
else
{
// TODO: добавьте код загрузки
ar >> m_strText;
}
}

Соберем и зарегистрируем приложение. Для обновление реестра нужно всего один раз запустить в автономном режиме приложение.

3. Тестируем приложение

Для того чтобы протестировать наше приложение нам понадобится программа контейнер, мы будем использовать программу excel. У меня excel 2010, запускаем excel, выбираем «Вставка» и кликаем по кнопке «вставить объект»

excel вставка

в появившемся окошке «Вставить элемент» выбираем наш элемент

excel insert object

нажимаем «ок» и у нас добавился наш элемент

mfd excel embedding

когда мы кликаем по элементу у нас запускается это от окошко. Когда мы кликаем правой клавишей по элементу у нас появляется контекстное меню

excel mini

Если мы вибераем подпункт меню Edit то у нас вроде должно загружатбся меню IDR_SRVR_INPLACE, а если выбираем Open то IDR_SRVR_EMBEDDED, но у меня загружается все время меню IDR_MAINFRAME, в общем не знаю почему так происходит если загружается IDR_SRVR_EMBEDDED, то у нас происходит внедрение, а если IDR_SRVR_INPLACE то происходит активизация по месту. Не знаю почему у меня не работает, в книге написано что должно так работать как я описал. Но мы не будем теряться добавим к меню IDR_MAINFRAME новый пункт меню под названием «IDR_MAINFRAME» и подпункт меню Modify с идентификатором ID_MODIFY. Перекомпелируем программу, кликаем два раза мышкой по нашему компоненту и у нас уже появляется новый подпункт меню

mfc application new menu

Дальше изменяем текст на «Hellow world» для этого выберем подпункт меню Modify и запустим диалоговое окно и у нас в excele меняется текст. В общем все работает.

4. Отладка

Отлаживается этот компонент как и любое другое приложение COM. Заходим в свойства проекта, указываем путь к нашему файлу и прописываем команду /Embedding, запускаем отладку и она переходит в режим ожидания. Дальше заходим в эксель и внедряем наш компонент кликаем по нему запуская программу редактор наш сервер.

Либо можно в оладчике прописать путь к excel файлу с таким же параметром /Embedding и запустить отадку, она перейдет в режим ожидания, мы запускаем excel и все что будет компонент будет выводится в отладчике. (этот способ я не уверен что будет работать, по идее должен).

5. Немножко теории

Мини-сервер — это такой компонент который сам по себе не может запускаться, а только из программки контейнера. Бывают еще полные-сервера, те могут и сами по себе запускаться. Наше приложение пример мини-сервера, она сама по себе не может работать.

Visual Editing (визуальное редактирование) — это торговая марка Microsoft, синоним активизации по месту. Активизация по месту — это когда мы внедрили компонент и кликаем по нему мушкой у нас меняется меню и панели инструментов на те которые мы можем редактировать наше приложение. А просто внедрение запускает программку которая редактирует данные элемент.

Метафайл — это общий термин для формата файлов, которые могут дополнительно хранить в себе и данные (доп. сведения) о хранимых в них (файлах) данных — сведения, которые в обычном режиме просмотра содержимого сокрыты от пользователя. В мире OLE-внедрения метафайлы создаются компонентами, а воспроизводятся контейнерами.

 

[youtube]https://www.youtube.com/watch?v=xlefiSn9Kxc[/youtube]

 

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

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Рубрики

  • C++ (293)
  • JavaScript (1)
  • linux (1)
  • MFC (39)
  • node.js (2)
  • React (3)
  • uncategorized (3)
  • vBulletin (5)
  • Visual Studio (9)
  • wordpress (18)
  • Разное (121)

Метки

Ajax bootstrap CentOS CLI expressjs FormData GDlib google Invisible reCAPTCHA JWT media MFC php react-router-dom redux repository wordpress RTTI STL vBulletin vector Visual Studio WINAPI wordpress wp-plugins XMLHttpRequest Двоичное дерево Задачи С++ Игры С++ Исключения С++ О-большое Операторы_С++ Перегрузка операторов С++ Поиск С++ Потоки Проектирование_С++ С++ Типы_С++ Типы С++ Шаблоны С++ библиотеки локализация макросы С++ сортировка С++

Свежие комментарии

  • Proffirot к записи Программка для заполнения форума на vBulletin 3.8.7
  • RA3PKJ к записи visual C++, создание диалоговых окон.
  • JasonReant к записи Создание и использование статических библиотек .lib в visual studio.
  • MyWin2020 к записи Программка для заполнения форума на vBulletin 3.8.7
  • ScottJip к записи Создание и использование статических библиотек .lib в visual studio.
©2021 Kselax.ru Theme by ThemeGiant