<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Апи Виндовс</title>
	<atom:link href="http://www.api-windows.info/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.api-windows.info</link>
	<description>Помощь разработчику по Апи Виндовс</description>
	<lastBuildDate>Fri, 15 Jan 2010 05:12:37 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9-RC1</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Перья и кисти внутри классов</title>
		<link>http://www.api-windows.info/perya-i-kisti-vnutri-klassov/</link>
		<comments>http://www.api-windows.info/perya-i-kisti-vnutri-klassov/#comments</comments>
		<pubDate>Sat, 28 Nov 2009 13:55:28 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Перья и кисти внутри классов]]></category>
		<category><![CDATA[поток]]></category>
		<category><![CDATA[пример]]></category>
		<category><![CDATA[программа]]></category>
		<category><![CDATA[просто]]></category>
		<category><![CDATA[сервере]]></category>
		<category><![CDATA[создать]]></category>
		<category><![CDATA[способ]]></category>
		<category><![CDATA[только]]></category>

		<guid isPermaLink="false">http://www.api-windows.info/perya-i-kisti-vnutri-klassov/</guid>
		<description><![CDATA[
Рисование перьями и раскрашивание кистями
Перевод А. И. Легалова
Англоязычный оригинал находится на сервере компании Reliable Software

Подобно живописцу, Вы нуждаетесь в перьях и кистях, чтобы создать шедевр на вашем холсте. Когда Вы вызываете метод Canvas::Line или Canvas::Rectangle, Windows использует текущие установки пера, чтобы рисовать линии, и текущие установки кисти, чтобы заполнять охватываемые контуры.
Когда объект сопоставляется с Холстом, [...]]]></description>
			<content:encoded><![CDATA[<p><img src="img/ruchka.jpg" /></p>
<p>Рисование перьями и раскрашивание кистями</p>
<p>Перевод А. И. Легалова</p>
<p>Англоязычный оригинал находится на сервере компании Reliable Software</p>
<p><span id="more-10"></span></p>
<p>Подобно живописцу, Вы нуждаетесь в перьях и кистях, чтобы создать шедевр на вашем холсте. Когда Вы вызываете метод Canvas::Line или Canvas::Rectangle, Windows использует текущие установки пера, чтобы рисовать линии, и текущие установки кисти, чтобы заполнять охватываемые контуры.</p>
<p>Когда объект сопоставляется с Холстом, нельзя забывать освободить его после окончания работы. Это надо делать до тех пор, пока вы не обеспечите такой возможностью вашу программу на языке C++. Используйте только локальные объекты, чьи конструкторы присоединяют, а деструкторы (вызываемые автоматически, при выходе области действия) освобождают объекты (см. страницу «Управление ресурсами» для более детального знакомства с этой методологией). Обратите внимание, что ниже следующие объекты используют HDC (дескрипторы контекстов устройств) в качестве параметры в их конструкторах. Однако, взамен этого, Вы должны просто передать им объект Canvas. Помните, что «Холст» может автоматически приводиться к HDC.</p>
<p>class StockObject {</p>
<p>public:</p>
<p>StockObject(HDC hdc, int type) : _hdc(hdc) {</p>
<p>_hObjOld = SelectObject(_hdc, GetStockObject(type));</p>
<p>}</p>
<p>~StockObject () {</p>
<p>SelectObject(_hdc, _hObjOld);</p>
<p>}</p>
<p>private:</p>
<p>HGDIOBJ _hObjOld;</p>
<p>HDC _hdc;</p>
<p>};</p>
<p>Windows имеет набор предопределенных перьев и кистей. Если Вы хотите использовать их, то достаточно присоединить выбранные перья и кисти к вашему холсту не некоторое время.</p>
<p>class WhitePen : public StockObject {</p>
<p>public:</p>
<p>WhitePen(HDC hdc): StockObject(hdc, WHITE_PEN) {}</p>
<p>};</p>
<p>// example</p>
<p>void Controller::Paint(HWND hwnd) {</p>
<p>PaintCanvas canvas(hwnd);</p>
<p>WhitePen pen(canvas);</p>
<p>canvas.Line(0, 10, 100, 10);</p>
<p>// destructor of WhitePen</p>
<p>// destructor of PaintCanvas</p>
<p>}</p>
<p>Если ваша программа поддерживает использование несколько перьев, отсутствующих в Windows, Вы можете предварительно создать их (например, внедрив их в объект View) и использовать объект PenHolder, для временного присоединения к Холсту.</p>
<p>class Pen {</p>
<p>public:</p>
<p>Pen(COLORREF color) {</p>
<p>_hPen = CreatePen(PS_SOLID, 0, color);</p>
<p>}</p>
<p>~Pen() {</p>
<p>DeleteObject(_hpen);</p>
<p>}</p>
<p>operator HPEN() {</p>
<p>return _hPen;</p>
<p>}</p>
<p>private:</p>
<p>HPEN _hPen;</p>
<p>};</p>
<p>class PenHolder {</p>
<p>public:</p>
<p>PenHolder(HDC hdc, HPEN hPen) : _hdc (hdc) {</p>
<p>_hPenOld = (HPEN)SelectObject (_hdc, hPen);</p>
<p>}</p>
<p>~PenHolder() {</p>
<p>SelectObject(_hdc, _hPenOld);</p>
<p>}</p>
<p>private:</p>
<p>HDC _hdc;</p>
<p>HPEN _hPenOld;</p>
<p>};</p>
<p>class View {</p>
<p>public:</p>
<p>View() : _penGreen (RGB (0, 255, 128)) {}</p>
<p>void Paint(Canvas&amp; canvas) {</p>
<p>PenHolder holder(canvas, _penGreen);</p>
<p>canvas.Line(0, 10, 100, 10);</p>
<p>// destructor of PenHolder</p>
<p>}</p>
<p>private:</p>
<p>Pen _penGreen;</p>
<p>};</p>
<p>И, наконец, если ваша программа нуждается в произвольных цветных перьях, то есть, невозможно предварительно определить всех цветов, в которых вы будете нуждаться, Вы должны использовать цветные перья. Когда Вы определяете автоматический объект ColorPen, его конструктор создает и присоединяет перо. Когда, в конце области действия, вызывается деструктор, он отсоединяет перо и удаляет его.</p>
<p>class ColorPen {</p>
]]></content:encoded>
			<wfw:commentRss>http://www.api-windows.info/perya-i-kisti-vnutri-klassov/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Почему плохо использовать mfc как программировать и как не программировать</title>
		<link>http://www.api-windows.info/pochemu-ploxo-ispolzovat-mfc-kak-programmirovat-i-kak-ne-programmirovat/</link>
		<comments>http://www.api-windows.info/pochemu-ploxo-ispolzovat-mfc-kak-programmirovat-i-kak-ne-programmirovat/#comments</comments>
		<pubDate>Thu, 05 Nov 2009 05:38:41 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Почему плохо использовать mfc как программировать и как не программировать]]></category>
		<category><![CDATA[получить]]></category>
		<category><![CDATA[потому]]></category>
		<category><![CDATA[пример]]></category>
		<category><![CDATA[программа]]></category>
		<category><![CDATA[программы]]></category>
		<category><![CDATA[простой]]></category>
		<category><![CDATA[сделать]]></category>
		<category><![CDATA[сервере]]></category>
		<category><![CDATA[случае]]></category>
		<category><![CDATA[создать]]></category>
		<category><![CDATA[сообщения]]></category>
		<category><![CDATA[способ]]></category>
		<category><![CDATA[того]]></category>
		<category><![CDATA[только]]></category>
		<category><![CDATA[управления]]></category>
		<category><![CDATA[через]]></category>

		<guid isPermaLink="false">http://www.api-windows.info/pochemu-ploxo-ispolzovat-mfc-kak-programmirovat-i-kak-ne-programmirovat/</guid>
		<description><![CDATA[ Библиотека классов MFC является вредной для программиста 
 
 
 Перевод А. И. Легалова 
 
 
 Англоязычный оригинал находится на сервере компании Reliable Software 
 
 
 Программирование для Windows считается трудным. Библиотеки классов делают программирование для Windows легче. Это истина или ложь? 
 
 
 bool IsWinProgEasier (Method method) { 
 
 [...]]]></description>
			<content:encoded><![CDATA[<p> Библиотека классов MFC является вредной для программиста </p>
<p> <br/>
 </p>
<p> Перевод А. И. Легалова </p>
<p> <br/>
 </p>
<p> Англоязычный оригинал находится на сервере компании Reliable Software </p>
<p> <span id="more-2"></span><br/>
 </p>
<p> Программирование для Windows считается трудным. Библиотеки классов делают программирование для Windows легче. Это истина или ложь? </p>
<p> <br/>
 </p>
<p> bool IsWinProgEasier (Method method) { </p>
<p> <br/>
 </p>
<p> if (method == WIN_CLASS_LIBRARIES) return false; </p>
<p> <br/>
 </p>
<p> else return true; </p>
<p> <br/>
 </p>
<p> } </p>
<p> <br/>
 </p>
<p> Поговорим серьезно. Если все, чего Вы хотите &mdash; это писать программы, которые являются производными от MFC или OWL, и Вы не заботитесь о непроизводительных затратах, то использование библиотек классов и мастеров приложений &mdash; это способ, которым можно идти. Но как только Вы захотите шагнуть вне этого пути, вы окажетесь перед огромными проблемами. </p>
<p> <br/>
 </p>
<p> Позвольте привести аналогию. Представьте, что вы покупаете набор Lego блоков. Вы можете купить универсальный набор, или специализированный набор для построения пиратского судна. Если все, что Вы хотите сделать, это создать пиратское судно, то второй вариант предпочтительнее. Но если Вы вдруг попробуете попробуете сделать из него Lego автомобиль, то Вам придется преодолеть несколько проблем. В конечном счете вы придумаете нечто, похожее на автомобиль, который будет иметь забавное колесо управления, использовать якорь для торможения, а водитель будет иметь деревянную культю и черную повязку на его глазе. </p>
<p> <br/>
 </p>
<p> После работы с этим набором &quot;пиратского&quot; Лего в течении некоторого времени, Вы станете специалистом в формировании почти всего того, что могло бы быть сделано из универсального комплекта. Вы усвоите разные приемы, подобно тому, как удалить заплату с глаза пирата, как закрасить череп и кости и т.д. В конечном счете вы достигнете таких высот, когда количество знания, которое вы ассимилировали относительно Пиратского набора, будет намного больше, чем базисные принципы и техника, которые вы должны были бы узнать, чтобы использовать универсальный Lego. С той вершины вы будете выбрасывать большие деньги после первых малых затрат, вкладывая капитал во все более сложные (и сложные) Пиратские наборы. </p>
<p> <br/>
 </p>
<p> Что же Вам делать? Мой совет: накоротко урезать ваши потери, начав сейчас же изучать программирование для Windows. API Windows &ndash; не является красивой или простой вещью. Именно поэтому все эти библиотеки классов стали настолько популярными в первое время. Но если Вы хотите выращивать красивые цветы, вам необходимо будет испачкать ваши руки. Объектное программирование и Windows далеки друг от друга, но я не хочу, чтобы Вы повторно изобретали колесо. Имеются некоторые простые OO методы, которые помогут Вам инкапсулировать уродливое лицо Windows API. </p>
<p> <br/>
 </p>
<p> Побочный эффект окажется то, что вы будете способны создавать Windows программы, которые являются достаточно малыми, чтобы быть легко загружаемыми из Интернета. Малые программы загружаются очень быстро &ndash; они не нуждаются в чем-либо, имеющемся в MFC dll библиотеках. Я спорю с любым MFC энтузиастом, что он не напишет игру &quot;Морской бой&quot;, которая будет меньше по размеру, чем наша, и будет обладать теми же функциональным возможностям. </p>
<p> <br/>
 </p>
<p> Давайте же начнем наш просмотр Win32 API с самой простой возможной Windows программы &hellip; Hello Windows!. </p>
<p> <br/>
 </p>
<p> Рекомендуемая литература:[1] </p>
<p> <br/>
 </p>
<p> Brent E. Rector, Joseph M. Newcomer. Win32 Programming. Addison-Wesley </p>
<p> <br/>
 </p>
<p> Очень полное и детализированное представление Win32 API. Превосходные ссылки. </p>
<p> <br/>
 </p>
<p> И имеется письмо от одного из наших посетителей, Дейва Линенберга (Dave Linenberg). </p>
<p> <br/>
 </p>
<p> Я потратил приблизительно 20 минут, просматривая ваш сайт, и действительно наслаждался вашими взглядами на программирование &mdash; особенно относительно вздутого характера MFC. Я не мог не поделиться своими наблюдениями. </p>
<p> <br/>
 </p>
<p> Я начал писать Windows-программы, использующие API в 1991-1992 годах (обучаясь по первой книги Петцолда)&hellip; а затем, слушая все эти разговоры об объектно ориентированном программном обеспечении, я попробовал изучать MFC. Я пролистал книгу Просиса, и проработал все упражнения. Я просмотрел пару сотен страниц исходного текста MFC, и наткнулся на большое количество неописанного наполнения. Я изучил внутреннюю организацию MFC. Я был подготовлен, чтобы действительно понять MFC&hellip;., но я этого не смог сделать. Эта библиотека вызывала довольно сильное отвращение. MFC, которая делает простые вещи, является чрезвычайно сложной.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.api-windows.info/pochemu-ploxo-ispolzovat-mfc-kak-programmirovat-i-kak-ne-programmirovat/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Обертка для автоматизации</title>
		<link>http://www.api-windows.info/obertka-dlya-avtomatizacii/</link>
		<comments>http://www.api-windows.info/obertka-dlya-avtomatizacii/#comments</comments>
		<pubDate>Mon, 19 Oct 2009 21:22:07 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Обертка для автоматизации]]></category>
		<category><![CDATA[получить]]></category>
		<category><![CDATA[Пользователь]]></category>
		<category><![CDATA[потому]]></category>
		<category><![CDATA[приложение]]></category>
		<category><![CDATA[приложения]]></category>
		<category><![CDATA[пример]]></category>
		<category><![CDATA[программа]]></category>
		<category><![CDATA[программе]]></category>
		<category><![CDATA[просто]]></category>
		<category><![CDATA[простой]]></category>
		<category><![CDATA[сделать]]></category>
		<category><![CDATA[сервере]]></category>
		<category><![CDATA[случае]]></category>
		<category><![CDATA[создать]]></category>
		<category><![CDATA[способ]]></category>
		<category><![CDATA[ссылок]]></category>
		<category><![CDATA[также]]></category>
		<category><![CDATA[того]]></category>
		<category><![CDATA[только]]></category>
		<category><![CDATA[указатель]]></category>
		<category><![CDATA[через]]></category>

		<guid isPermaLink="false">http://www.api-windows.info/obertka-dlya-avtomatizacii/</guid>
		<description><![CDATA[ Автоматизация 
 
 
 Перевод А. И. Легалова 
 
 
 Англоязычный оригинал находится на сервере компании Reliable Software 
 
 
 Мне бы хотелось получить море информации из запущенной копии Microsoft Developers Studio. Это должно быть простой задачей, т.к. DevStudio, подобно многим другим приложениям MS, предоставляет его интерфейсы через OLE Автоматизацию. Не столь [...]]]></description>
			<content:encoded><![CDATA[<p> Автоматизация </p>
<p> <br/>
 </p>
<p> Перевод А. И. Легалова </p>
<p> <br/>
 </p>
<p> Англоязычный оригинал находится на сервере компании Reliable Software </p>
<p> <span id="more-16"></span><br/>
 </p>
<p> Мне бы хотелось получить море информации из запущенной копии Microsoft Developers Studio. Это должно быть простой задачей, т.к. DevStudio, подобно многим другим приложениям MS, предоставляет его интерфейсы через OLE Автоматизацию. Не столь просто! Как Вы увидите, Microsoft решил, что клиенты интерфейсов автоматизации VC ++ будет или использовать Visual Basic, или внутренних умных мастеров DevStudio. Я, с другой стороны, люблю программировать на C++ (Вам не кажется, что Microsoft Visual C++ должен быть переименован в Microsoft Visual MFC Wizard? Это принизило C++ до роли языка сценариев для MFC.) </p>
<p> <br/>
 </p>
<p> В любом случае, когда я выяснил, как надо делать, остальное оказалось не быть слишком трудным. Вы только должны выяснить, где вся необходимая информация сохраняется в реестре. В частности IID всех интерфейсов. Совет: используйте OLE-COM Object Viewer, который поставляется с VC ++, чтобы просмотреть библиотеки типов. Было бы вообще великолепно, если бы Microsoft предоставлял исходные файлы или obj файлы с определениями идентификаторов интерфейсов. В существующей же ситуации я должен копировать их из Object Viewer'а и вставлять их в нужное место. Ниже приводится пример. </p>
<p> <br/>
 </p>
<p> static const IID IID_IApplication = { </p>
<p> <br/>
 </p>
<p> 0xEC1D73A1, 0x8CC4, 0x11CF, { 0x9B, 0xE9, 0x00, 0xA0, 0xC9, 0x0A, 0x63, 0x2C } </p>
<p> <br/>
 </p>
<p> }; </p>
<p> <br/>
 </p>
<p> Итак, как получить управление выполняющейся копией DevStudio? В начале вы должны создать OLE объект. Для этого необходим идентификатор класса этого объекта. Вы можете получить идентификатор класса от системы (эта информация хранится в реестре), если знаете программный идентификатор. Программный идентификатор, устроен так чтобы читаться человеком. Конечно, каждый человек знает, что Developer Studio идет под именем &quot;MSDEV.APPLICATION&quot;. Это так просто. </p>
<p> <br/>
 </p>
<p> Имея идентификатор класса, мы можем создать наш SObject. Мы передаем значение параметра запуска как true, потому что хотим соединиться с выполняющейся копией MSDEV.APPLICATION, если это возможно. Получение интерфейса из SObject столь же просто как создание экземпляра шаблона SObjFace с соответствующими параметрами. Итак, нашей отправной точкой будет, интерфейс к приложению. </p>
<p> <br/>
 </p>
<p> CLSID idMsDev; </p>
<p> <br/>
 </p>
<p> HRESULT hr = ::CLSIDFromProgID(L&quot;MSDEV.APPLICATION&quot;, &amp;idMsDev); </p>
<p> <br/>
 </p>
<p> if (FAILED (hr)) throw HEx(hr, &quot;Couldn't convert prog id to class id&quot;); </p>
<p> <br/>
 </p>
<p> SObject obj(idMsDev, true); </p>
<p> <br/>
 </p>
<p> SObjFace&lt;IApplication, &amp;IID_IApplication&gt; app(obj); </p>
<p> <br/>
 </p>
<p> Обратите внимание, что строка, которую Вы передаете к CLSIDFromProgID, должна использовать кодировку Unicode. Помещение L перед строковым литералом обеспечивает это. </p>
<p> <br/>
 </p>
<p> Я надеюсь, что Вы можете оценить простоту этого кода. Он почти столь же прост, как и его VB эквивалент. </p>
<p> <br/>
 </p>
<p> Dim app as Application </p>
<p> <br/>
 </p>
<p> Set app = GetObject(, &quot;MSDEV.APPLICATION&quot;) </p>
<p> <br/>
 </p>
<p> if (app = NULL) </p>
<p> <br/>
 </p>
<p> Set app = CreateObject(&quot;MSDEV.APPLICATION&quot;) </p>
<p> <br/>
 </p>
<p> Теперь давайте что-нибудь сделаем с этим интерфейсом. Так случилось, что IApplication имеет член Visible, который Вы можете установить или получить. Когда Вы устанавливаете Visible в истину, окно приложения становится видимым. Ниже приводится синтаксис для &laquo;установки&raquo; члена. Обратите внимание, что в OLE Вы должны использовать обозначения с именами VARIANT_BOOL и VARIANT_TRUE вместо bool и true. Это делается ради совместимости с Basic (что делает Билла счастливым). </p>
<p> <br/>
 </p>
<p> VARIANT_BOOL b = VARIANT_TRUE; </p>
<p> <br/>
 </p>
<p> app-&gt;put_Visible(b); </p>
<p> <br/>
 </p>
<p> Как я узнал, что IApplication имеет член Visible? Хороший вопрос! Имеется подкаталог objmodel в VC ++, в каталоге include, где Вы можете отыскать такие файлы как Appauto.h, которые содержат строки, подобные одной из показанных ниже. Вы можете проводить выборочное изучение, чтобы интерпретировать эти файлы. Их критика связана с (глупым!) требованием, чтобы они включались как в C, так и в C++ код. А Microsoft не захотела поддерживать два набора заголовочных файлов, поэтому здесь мы поступаем так. </p>
<p> <br/>
 </p>
<p> STDMETHOD(get_Visible)(THIS_ VARIANT_BOOL FAR* Visible) PURE; </p>
<p> <br/>
 </p>
<p> STDMETHOD(put_Visible)(THIS_ VARIANT_BOOL Visible) PURE; </p>
<p> <br/>
 </p>
<p> Так, что же мы делаем дальше, когда приложение в наших руках? Как насчет выяснения того, какой документ является в настоящее время активным?</p>
]]></content:encoded>
			<wfw:commentRss>http://www.api-windows.info/obertka-dlya-avtomatizacii/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Обертка для контекста устройств</title>
		<link>http://www.api-windows.info/obertka-dlya-konteksta-ustrojstv/</link>
		<comments>http://www.api-windows.info/obertka-dlya-konteksta-ustrojstv/#comments</comments>
		<pubDate>Tue, 29 Sep 2009 09:09:08 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Обертка для контекста устройств]]></category>
		<category><![CDATA[пример]]></category>
		<category><![CDATA[программа]]></category>
		<category><![CDATA[программе]]></category>
		<category><![CDATA[прочим]]></category>
		<category><![CDATA[сервере]]></category>
		<category><![CDATA[создать]]></category>
		<category><![CDATA[сообщение]]></category>
		<category><![CDATA[сообщения]]></category>
		<category><![CDATA[способ]]></category>
		<category><![CDATA[того]]></category>
		<category><![CDATA[управления]]></category>

		<guid isPermaLink="false">http://www.api-windows.info/obertka-dlya-konteksta-ustrojstv/</guid>
		<description><![CDATA[ Холст или контекст устройств Windows 
 
 
 Перевод А. И. Легалова 
 
 
 Англоязычный оригинал находится на сервере компании Reliable Software 
 
 
 Чтобы раукрашивать, рисовать или печатать в окне, Вам необходим контекст устройств (device context или, кратко, DC). DC &#8212; это ресурс, который заимствуется у Windows и, как предполагается, возвращается [...]]]></description>
			<content:encoded><![CDATA[<p> Холст или контекст устройств Windows </p>
<p> <br/>
 </p>
<p> Перевод А. И. Легалова </p>
<p> <br/>
 </p>
<p> Англоязычный оригинал находится на сервере компании Reliable Software </p>
<p> <span id="more-9"></span><br/>
 </p>
<p> Чтобы раукрашивать, рисовать или печатать в окне, Вам необходим контекст устройств (device context или, кратко, DC). DC &mdash; это ресурс, который заимствуется у Windows и, как предполагается, возвращается сразу же после того, как вы сделаете свою работу. Отсюда и берет корни объект Canvas (Холст). Конструктор Холста получает DC, а деструктор освобождает его. Важно то, что Вы создаете объекты Canvas как автоматические (стековые) переменные. Это гарантирует, что, когда программа выйдет из локальной области (контекста), всегда вызовется их деструктор, в которой определены ресурсы (предлагаемый класс является примером более общей методологии Управления ресурсами). Типичное использование объекта Canvas демонстрируется следующем кодом (вы его уже видели в программе Generic): </p>
<p> <br/>
 </p>
<p> void Controller::Paint() { </p>
<p> <br/>
 </p>
<p> // prepare the canvas and let View do the rest </p>
<p> <br/>
 </p>
<p> PaintCanvas canvas(_hwnd); </p>
<p> <br/>
 </p>
<p> _view.Paint(canvas, _model); </p>
<p> <br/>
 </p>
<p> // Notice: The destructor of PaintCanvas called automatically! </p>
<p> <br/>
 </p>
<p> } </p>
<p> <br/>
 </p>
<p> Различные типы Холста совместно используют общего предка &mdash; класс Canvas. Обратите внимание, что конструктор Холста защищен. Фактически, Вы не можете сформировать объект этого класса. Однако, наследующие классы открыты, чтобы обеспечить доступ к их собственным конструкторам. Между прочим, Вы можете осуществлять добавление новых методов к Холсту, по мере возникновения такой потребности. </p>
<p> <br/>
 </p>
<p> class Canvas { </p>
<p> <br/>
 </p>
<p> public: </p>
<p> <br/>
 </p>
<p> // operator cast to HDC </p>
<p> <br/>
 </p>
<p> // (used when passing Canvas to Windows API) </p>
<p> <br/>
 </p>
<p> operator HDC() { return _hdc; } </p>
<p> <br/>
 </p>
<p> void Point(int x, int y, COLORREF color) { </p>
<p> <br/>
 </p>
<p> ::SetPixel(_hdc, x, y, color); </p>
<p> <br/>
 </p>
<p> } </p>
<p> <br/>
 </p>
<p> void MoveTo(int x, int y) { </p>
<p> <br/>
 </p>
<p> ::MoveToEx(_hdc, x, y, 0); </p>
<p> <br/>
 </p>
<p> } </p>
<p> <br/>
 </p>
<p> void Line(int x1, int y1, int x2, int y2 ) { </p>
<p> <br/>
 </p>
<p> MoveToEx(_hdc, x1, y1, 0); </p>
<p> <br/>
 </p>
<p> LineTo(_hdc, x2, y2); </p>
<p> <br/>
 </p>
<p> } </p>
<p> <br/>
 </p>
<p> void Rectangle(int left, int top, int right, int bottom) { </p>
<p> <br/>
 </p>
<p> // draw rectangle using current pen </p>
<p> <br/>
 </p>
<p> // and fill it using current brush </p>
<p> <br/>
 </p>
<p> ::Rectangle(_hdc, left, top, right, bottom); </p>
<p> <br/>
 </p>
<p> } </p>
<p> <br/>
 </p>
<p> void GetTextSize(int&amp; cxChar, int&amp; cyChar) { </p>
<p> <br/>
 </p>
<p> TEXTMETRIC tm; </p>
<p> <br/>
 </p>
<p> GetTextMetrics(_hdc, &amp;tm); </p>
<p> <br/>
 </p>
<p> cxChar = tm.tmAveCharWidth; </p>
<p> <br/>
 </p>
<p> cyChar = tm.tmHeight + tm.tmExternalLeading; </p>
<p> <br/>
 </p>
<p> } </p>
<p> <br/>
 </p>
<p> void Text(int x, int y, char const * buf, int cBuf) { </p>
<p> <br/>
 </p>
<p> ::TextOut(_hdc, x, y, buf, cbuf); </p>
<p> <br/>
 </p>
<p> } </p>
<p> <br/>
 </p>
<p> void Char(int x, int y, char c) { </p>
<p> <br/>
 </p>
<p> TextOut(_hdc, x, y, &amp;c, 1); </p>
<p> <br/>
 </p>
<p> } </p>
<p> <br/>
 </p>
<p> void SelectObject(void* pObj) { </p>
<p> <br/>
 </p>
<p> ::SelectObject(_hdc, pobj); </p>
<p> <br/>
 </p>
<p> } </p>
<p> <br/>
 </p>
<p> protected: </p>
<p> <br/>
 </p>
<p> Canvas(HDC hdc): _hdc(hdc) {} </p>
<p> <br/>
 </p>
<p> HDC _hdc; </p>
<p> <br/>
 </p>
<p> }; </p>
<p> <br/>
 </p>
<p> В ответ на сообщение WM_PAINT нужно создать объект PaintCanvas. Обратите внимание на способ получения и освобождения DC объектом PaintCanvas. </p>
<p> <br/>
 </p>
<p> class PaintCanvas: public Canvas { </p>
<p> <br/>
 </p>
<p> public: </p>
<p> <br/>
 </p>
<p> // Constructor obtains the DC </p>
<p> <br/>
 </p>
<p> PaintCanvas(HWND hwnd) : Canvas(BeginPaint(hwnd, &amp;_paint)), _hwnd(hwnd) {} </p>
<p> <br/>
 </p>
<p> // Destructor releases the DC </p>
<p> <br/>
 </p>
<p> ~PaintCanvas() { </p>
<p> <br/>
 </p>
<p> EndPaint(_hwnd, &amp;_paint); </p>
<p> <br/>
 </p>
<p> } </p>
<p> <br/>
 </p>
<p> protected: </p>
<p> <br/>
 </p>
<p> PAINTSTRUCT _paint; </p>
<p> <br/>
 </p>
<p> HWND _hwnd; </p>
<p> <br/>
 </p>
<p> }; </p>
<p> <br/>
 </p>
<p> Другой важный пример &mdash; класс UpdateCanvas, который используется для графических операций вне контекста обработки сообщения WM_PAINT. Конечно, ваша программа может всегда инициировать перерисовку, вызывая InvalidateRect, но во многих случаях это было бы массовым убийством.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.api-windows.info/obertka-dlya-konteksta-ustrojstv/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Оболочка из классов для com</title>
		<link>http://www.api-windows.info/obolochka-iz-klassov-dlya-com/</link>
		<comments>http://www.api-windows.info/obolochka-iz-klassov-dlya-com/#comments</comments>
		<pubDate>Wed, 23 Sep 2009 06:33:47 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Оболочка из классов для com]]></category>
		<category><![CDATA[получить]]></category>
		<category><![CDATA[Пользователь]]></category>
		<category><![CDATA[потому]]></category>
		<category><![CDATA[приложение]]></category>
		<category><![CDATA[приложения]]></category>
		<category><![CDATA[пример]]></category>
		<category><![CDATA[программа]]></category>
		<category><![CDATA[программе]]></category>
		<category><![CDATA[программы]]></category>
		<category><![CDATA[просто]]></category>
		<category><![CDATA[простой]]></category>
		<category><![CDATA[прочим]]></category>
		<category><![CDATA[сделать]]></category>
		<category><![CDATA[сервере]]></category>
		<category><![CDATA[создать]]></category>
		<category><![CDATA[способ]]></category>
		<category><![CDATA[ссылок]]></category>
		<category><![CDATA[также]]></category>
		<category><![CDATA[того]]></category>
		<category><![CDATA[только]]></category>
		<category><![CDATA[указатель]]></category>
		<category><![CDATA[функции]]></category>
		<category><![CDATA[через]]></category>

		<guid isPermaLink="false">http://www.api-windows.info/obolochka-iz-klassov-dlya-com/</guid>
		<description><![CDATA[ Использование оболочки Windows совместно с COM 
 
 
 Перевод А. И. Легалова 
 
 
 Англоязычный оригинал находится на сервере компании Reliable Software 
 
 
 Программировать с использованием COM настолько трудно, что Вы не должны даже пробовать это без MFC. Правильно или неправильно? Абсолютная чушь! Рекламируемые OLE и его преемник COM имеют [...]]]></description>
			<content:encoded><![CDATA[<p> Использование оболочки Windows совместно с COM </p>
<p> <br/>
 </p>
<p> Перевод А. И. Легалова </p>
<p> <br/>
 </p>
<p> Англоязычный оригинал находится на сервере компании Reliable Software </p>
<p> <span id="more-13"></span><br/>
 </p>
<p> Программировать с использованием COM настолько трудно, что Вы не должны даже пробовать это без MFC. Правильно или неправильно? Абсолютная чушь! Рекламируемые OLE и его преемник COM имеют элегантность гиппопотама, занимающегося фигурным катанием. Но размещение MFC на вершине COM подобно одеванию гиппопотама в клоунский костюм еще больших размеров. </p>
<p> <br/>
 </p>
<p> Загрузите исходник примера, TreeSizer (zip архив 12 кб, любезность Laszlo Radanyi), в котором вычисляется суммарный размер всех файлов в некотором каталоге и всех его подкаталогах. Он, для просмотра каталогов, использует окно просмотра оболочки Windows. </p>
<p> <br/>
 </p>
<p> Итак, что делать программисту, когда он столкнется с потребностью использовать возможности оболочки Windows, которые являются доступными только через интерфейсы COM? Читайте &hellip; </p>
<p> <br/>
 </p>
<p> Для начала, всякий раз, когда Вы планируете использовать COM, Вы должны сообщить системе, чтобы она инициализировала COM подсистему. Точно так же всякий раз, когда вы заканчиваете работу, Вы должны сообщить системе, чтобы она выгрузила COM. Самая простой способ это сделать заключается в определении объекта, конструктор которого инициализирует COM, а деструктор выгрожает ее. Самое лучшее место для внедрения данного механизма &mdash; это объект Controller (см. Windows программу Generic), подобный этому. </p>
<p> <br/>
 </p>
<p> class Controller { </p>
<p> <br/>
 </p>
<p> public: </p>
<p> <br/>
 </p>
<p> Controller(HWND hwnd, CREATESTRUCT * pCreate); </p>
<p> <br/>
 </p>
<p> ~Controller(); </p>
<p> <br/>
 </p>
<p> // &hellip; private: </p>
<p> <br/>
 </p>
<p> UseCom _comUser; // i'm a com user </p>
<p> <br/>
 </p>
<p> Model _model; </p>
<p> <br/>
 </p>
<p> View _view; </p>
<p> <br/>
 </p>
<p> HINSTANCE _hInst; </p>
<p> <br/>
 </p>
<p> }; </p>
<p> <br/>
 </p>
<p> Этот способ гарантируют, что COM подсистема будет проинициализирована прежде, чем к ней будут сделаны любые обращения и что она будет освобождена после того, как программа осуществит свои разрушения (то есть, после того, как &quot;Вид&quot; и &quot;Модель&quot; будут разрушены). </p>
<p> <br/>
 </p>
<p> Класс UseCom очень прост. </p>
<p> <br/>
 </p>
<p> class UseCom { </p>
<p> <br/>
 </p>
<p> public: </p>
<p> <br/>
 </p>
<p> UseCom() { </p>
<p> <br/>
 </p>
<p> HRESULT err = CoInitialize(0); </p>
<p> <br/>
 </p>
<p> if (err != S_OK) throw &quot;Couldn't initialize COM&quot;; </p>
<p> <br/>
 </p>
<p> } </p>
<p> <br/>
 </p>
<p> ~UseCom() { </p>
<p> <br/>
 </p>
<p> CoUninitialize(); </p>
<p> <br/>
 </p>
<p> } </p>
<p> <br/>
 </p>
<p> }; </p>
<p> <br/>
 </p>
<p> Пока не было слишком трудно, не так ли? Дело в том, что мы не коснулись главной мерзости COM программирования &mdash; подсчета ссылок. Вам должно быть известно, что каждый раз, когда что Вы получаете интерфейс, его счетчик ссылок увеличивается. И Вам необходимо явно уменьшать его. И это становится более чем ужастным тогда, когда Вы начинаете запрашивать интерфейсы, копировать их, передавать другим и т.д. Но ловите момент: мы знаем, как управляться с такими проблемами! Это называется управлением ресурсами. Мы никогда не должны касаться интерфейсов COM без инкапсуляции их в интеллектуальных указателях на интерфейсы. Ниже показано, как это работает. </p>
<p> <br/>
 </p>
<p> Примечание. В настоящий момент данная тема достаточно широко рассмотрена в литературе, переведенной на русский язык. В частности, можно отметить книги: </p>
<p> <br/>
 </p>
<p> Джефф Элджер. &quot;C++: библиотека программиста&quot;; </p>
<p> <br/>
 </p>
<p> Скотт Мейерс. &quot;Эффективное программирование на С++&quot;. </p>
<p> <br/>
 </p>
<p> А.Л. </p>
<p> template &lt;class T&gt; </p>
<p> <br/>
 </p>
<p> class SIfacePtr { </p>
<p> <br/>
 </p>
<p> public: </p>
<p> <br/>
 </p>
<p> ~SIfacePtr() { </p>
<p> <br/>
 </p>
<p> Free (); </p>
<p> <br/>
 </p>
<p> } </p>
<p> <br/>
 </p>
<p> T * operator-&gt;() { return _p; } </p>
<p> <br/>
 </p>
<p> T const* operator-&gt;() const { return _p; } </p>
<p> <br/>
 </p>
<p> operator T const * () const { return _p; } </p>
<p> <br/>
 </p>
<p> T const&amp; GetAccess () const { return *_p; } </p>
<p> <br/>
 </p>
<p> protected: SIfacePtr () : _p (0) {} </p>
<p> <br/>
 </p>
<p> void Free () { </p>
<p> <br/>
 </p>
<p> if (_p != 0) _p-&gt;Release(); </p>
<p> <br/>
 </p>
<p> _p = 0; </p>
<p> <br/>
 </p>
<p> } </p>
<p> <br/>
 </p>
<p> T * _p; </p>
<p> <br/>
 </p>
<p> private: </p>
<p> <br/>
 </p>
<p> SIfacePtr(SIfacePtr const&amp; p) {} </p>
<p> <br/>
 </p>
<p> void operator=(SIfacePtr const&amp; p) {} </p>
<p> <br/>
 </p>
<p> }; </p>
<p> <br/>
 </p>
<p>
]]></content:encoded>
			<wfw:commentRss>http://www.api-windows.info/obolochka-iz-klassov-dlya-com/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Краткий обзор представленных материалов</title>
		<link>http://www.api-windows.info/kratkij-obzor-predstavlennyx-materialov/</link>
		<comments>http://www.api-windows.info/kratkij-obzor-predstavlennyx-materialov/#comments</comments>
		<pubDate>Tue, 15 Sep 2009 22:58:23 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Применение windows api]]></category>
		<category><![CDATA[приложение]]></category>
		<category><![CDATA[программы]]></category>
		<category><![CDATA[процедура]]></category>
		<category><![CDATA[сообщения]]></category>

		<guid isPermaLink="false">http://www.api-windows.info/kratkij-obzor-predstavlennyx-materialov/</guid>
		<description><![CDATA[ Разработка программ зачастую напоминает священный ритуал, построенный на произнесении ряда обязательных магических заклинаний. Особенно это касается Windows приложений. Windows-заклинания позволяют вывести графическое окно, обработать поступающие сообщения. Порядок их следования предопределен священными руководствами. Часто эти руководства заменяются шпаргалкой, кратко фиксирующей основной каркас: 
 
 
 // Каркасное приложение Windows 95 
 
 
 #include &#60;windows.h&#62; [...]]]></description>
			<content:encoded><![CDATA[<p> Разработка программ зачастую напоминает священный ритуал, построенный на произнесении ряда обязательных магических заклинаний. Особенно это касается Windows приложений. Windows-заклинания позволяют вывести графическое окно, обработать поступающие сообщения. Порядок их следования предопределен священными руководствами. Часто эти руководства заменяются шпаргалкой, кратко фиксирующей основной каркас: </p>
<p> <br/>
 </p>
<p> // Каркасное приложение Windows 95 </p>
<p> <br/>
 </p>
<p> #include &lt;windows.h&gt; </p>
<p> <span id="more-1"></span><br/>
 </p>
<p> LRESULT CALLBACK WindowFunc(HWND, UINT, WPARAM, LPARAM); </p>
<p> <br/>
 </p>
<p> char szWinName[] = &quot;SimpleWin&quot;; </p>
<p> <br/>
 </p>
<p> int WINAPI WinMain (HINSTANCE hThisInst,HINSTANCE hPrevInst, LPSTR lpszArgs,int nWinMode) { </p>
<p> <br/>
 </p>
<p> HWND hwnd; </p>
<p> <br/>
 </p>
<p> MSG msg; </p>
<p> <br/>
 </p>
<p> WNDCLASS wcl; </p>
<p> <br/>
 </p>
<p> wcl.hInstance = hThisInst; </p>
<p> <br/>
 </p>
<p> wcl.lpszClassName = szWinName; </p>
<p> <br/>
 </p>
<p> wcl.lpfnWndProc = WindowFunc; </p>
<p> <br/>
 </p>
<p> wcl.style = 0; </p>
<p> <br/>
 </p>
<p> wcl.hIcon = LoadIcon(NULL,IDI_APPLICATION); </p>
<p> <br/>
 </p>
<p> wcl.hCursor = LoadCursor(NULL, IDC_ARROW); </p>
<p> <br/>
 </p>
<p> wcl.lpszMenuName = NULL; </p>
<p> <br/>
 </p>
<p> wcl.cbClsExtra = 0; </p>
<p> <br/>
 </p>
<p> wcl.cbWndExtra = 0; </p>
<p> <br/>
 </p>
<p> wcl.hbrBackground= (HBRUSH)GetStockObject (WHITE_BRUSH); </p>
<p> <br/>
 </p>
<p> if ( !RegisterClass (&amp;wcl) ) return 0; </p>
<p> <br/>
 </p>
<p> hwnd = CreateWindow(szWinName, &quot;Kаркас программы для Windows 95&quot;, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, HWND_DESKTOP, NULL, hThisInst, NULL); </p>
<p> <br/>
 </p>
<p> ShowWindow(hwnd,nWinMode); </p>
<p> <br/>
 </p>
<p> UpdateWindow(hwnd); </p>
<p> <br/>
 </p>
<p> while (GetMessage(&amp;msg, NULL,0,0) ) { </p>
<p> <br/>
 </p>
<p> TranslateMessage (&amp;msg); </p>
<p> <br/>
 </p>
<p> DispatchMessage (&amp;msg); </p>
<p> <br/>
 </p>
<p> } </p>
<p> <br/>
 </p>
<p> return msg.wParam; </p>
<p> <br/>
 </p>
<p> } </p>
<p> <br/>
 </p>
<p> <br/>
 </p>
<p> // Оконная процедура </p>
<p> <br/>
 </p>
<p> LRESULT CALLBACK WindowFunc(HWND hwnd,UINT message, WPARAM wParam,LPARAM lParam) { </p>
<p> <br/>
 </p>
<p> switch (message) { </p>
<p> <br/>
 </p>
<p> case WM_DESTROY: </p>
<p> <br/>
 </p>
<p> PostQuitMessage (0); </p>
<p> <br/>
 </p>
<p> break; </p>
<p> <br/>
 </p>
<p> default: </p>
<p> <br/>
 </p>
<p> return DefWindowProc(hwnd,message,wParam,lParam); </p>
<p> <br/>
 </p>
<p> } </p>
<p> <br/>
 </p>
<p> return 0; </p>
<p> <br/>
 </p>
<p> } </p>
<p> <br/>
 </p>
<p> Зачастую начинающие шаманы обходятся и без шпаргалок. Обратившись к волшебникам и мастерам, они получают нужный каркас и целую кучу дополнительных наворотов. Каждый из этих подходов имеет свои положительные и отрицательные стороны. И каждый из них постоянно совершенствется впитывая в себя последние достижения технологии программирования. Ряд этих подходов, как мне кажется являются достаточно интересными как для изучения, так и для практического использования.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.api-windows.info/kratkij-obzor-predstavlennyx-materialov/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Дефекты ole</title>
		<link>http://www.api-windows.info/defekty-ole/</link>
		<comments>http://www.api-windows.info/defekty-ole/#comments</comments>
		<pubDate>Tue, 08 Sep 2009 07:36:39 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Дефекты ole]]></category>
		<category><![CDATA[получить]]></category>
		<category><![CDATA[потому]]></category>
		<category><![CDATA[пример]]></category>
		<category><![CDATA[программе]]></category>
		<category><![CDATA[программы]]></category>
		<category><![CDATA[просто]]></category>
		<category><![CDATA[простой]]></category>
		<category><![CDATA[прочим]]></category>
		<category><![CDATA[сделать]]></category>
		<category><![CDATA[сервере]]></category>
		<category><![CDATA[способ]]></category>
		<category><![CDATA[ссылок]]></category>
		<category><![CDATA[также]]></category>
		<category><![CDATA[того]]></category>
		<category><![CDATA[только]]></category>
		<category><![CDATA[указатель]]></category>
		<category><![CDATA[функции]]></category>
		<category><![CDATA[через]]></category>

		<guid isPermaLink="false">http://www.api-windows.info/defekty-ole/</guid>
		<description><![CDATA[ Что является неправильным в OLE 
 
 
 Рассказ посвященного лица 
 
 
 Перевод А. И. Легалова 
 
 
 Англоязычный оригинал находится на сервере компании Reliable Software 
 
 
 Вы могли слышать или читать критические мнения относительно OLE. Программисты обычно жалуются на сложность системы подсчета ссылок и недостатосную поддержку наследования. Microsoft [...]]]></description>
			<content:encoded><![CDATA[<p> Что является неправильным в OLE </p>
<p> <br/>
 </p>
<p> Рассказ посвященного лица </p>
<p> <br/>
 </p>
<p> Перевод А. И. Легалова </p>
<p> <span id="more-14"></span><br/>
 </p>
<p> Англоязычный оригинал находится на сервере компании Reliable Software </p>
<p> <br/>
 </p>
<p> Вы могли слышать или читать критические мнения относительно OLE. Программисты обычно жалуются на сложность системы подсчета ссылок и недостатосную поддержку наследования. Microsoft обожествляет этот счетчик, говоря, что нет никакого другого способа, и что этот способ является для вас наилучшим[2]. Интерфейсы, как сказано, должно быть ссылочно подсчитаны (refcounted), и имеется мудрый, рубильник обеспечивающий соединение (агрегацию) частей (нежно называемый ухудшением (aggravation) OLE программистами), который обеспечивает те же самые функциональные возможности, что и наследование. Может быть они правы, и проблема взаимодействия с объектами, загружаемыми во время выполнения настолько сложна, что просто не имеется более лучшего способа? С другой стороны, возможно, что OLE имеет фатальный дефект, который только обостряется во всех других местах. </p>
<p> <br/>
 </p>
<p> Фатальный дефект проекта OLE &mdash; требование того, чтобы была возможность добраться от любого интерфейса до любого другого интерфейса. </p>
<p> <br/>
 </p>
<p> Технически это интерфейсное прыгание сделано за счет того, что каждый интерфейс наследует от матери всех интерфейсов IUnknown. IUnknown имеет фатальный метод QueryInterface, который, как предполагается, возвращает любой интерфейс, обеспечиваемый текущим объектом. Это единственное предположение препятствует наличию любой возможности простой реализации наследования. Позвольте мне объясняют почему. </p>
<p> <br/>
 </p>
<p> Предположим, что Вы имеете объект FooObj с интерфейсом IFoo. Эта ситуация легко моделируется в C++ при наличии абстрактного класса (все методы &mdash; чистые виртуальные) IFoo и конкретного класс FooObj, который наследуется из IFoo и реализует все его методы. </p>
<p> <br/>
 </p>
<p> Теперь Вам вдруг захотелось расширить этот объект, добавляя поддержку для другого интерфейса IBar. В C++ это тривиально, Вы только определяете класс FooBarObj, который наследует от FooObj и IBar. Этот новый класс поддерживает интерфейс IFoo вместе с его реализацией через наследование из FooObj. Он также поддерживает интерфейс IBar и обеспечивает реализацию методов IBar. </p>
<p> <br/>
 </p>
<p> <br/>
 </p>
<p> Любой, кто знает C++, может сделать это с закрытыми глазами. Так, почему же Вы не можете сделать то же самое в OLE? Здесь проявляется Изъян. Вы должны быть способны получить интерфейс IBar из интерфейса IFoo, используя его QueryInterface. Но, подождите минуту, объект FooObj, который обеспечивает реализацию всех методов IFoo, включая QueryInterface, не имеет никаких сведений относительно IBar! Невозможно было даже представить наличие IBar. Так, как же в этой ситуации обеспечить доступ к IBar? </p>
<p> <br/>
 </p>
<p> Хороший вопрос. Я не собираюсь входить в кровавые подробности агрегационной рубки, которая, как предполагается, решает эту проблему. Накладываемые ограничения и пороки начального проекта, действительно, изобретательно, рубят. Так имеется ли лучший проект? Читайте дальше&hellip; </p>
<p> <br/>
 </p>
<p> Можете ли Вы отметить случай, когда были вынуждены проводить различия между объектом, который реализует интерфейсы и интерфейсами непосредственно? Это два полностью различных понятия. Вы не можете объяснить что-нибудь в OLE без того, чтобы не говорить об объектах, иногда называемых компонентами. Интерфейсы важны, но объекты еще более важны. Когда Вы можете получить один интерфейс от другого? Когда они совместно используют один и тот же основной объект. Вы можете изменять состояние объекта, используя один интерфейс и затем исследовать это состояние через другой интерфейс. Очевидно, что это тот же самый объект! В моем примере я описал два интерфейса, IFoo и IBar, и два объекта (или класса объектов), FooObject и FooBarObject. </p>
<p> <br/>
 </p>
<p> Фактически, любой, кто реализует интерфейсы (используя C++, C, или Basic) имеет дело с объектами. Однако, эта очень важная абстракция полностью отсутствует с точки зрения клиента OLE. Все, что клиент видит &ndash; это интерфейсы. Основной объект подобен призраку. </p>
<p> <br/>
 </p>
<p> Но это не призрак. Он физически представлен в адресном пространстве вашей программы, или непосредственно, или как заглушка пересылки. Так, почему скрывают это? Действительно, разве OLE не было бы более простым с явным понятием объекта? Давайте посмотрим, как это работало бы. </p>
<p> <br/>
 </p>
<p> Клиент этого &laquo;интеллектуального OLE&raquo; вызвал бы CoCreateInstance или ClassFactory::CreateInstance, чтобы получить указатель на объект (а не на интерфейс!). Используя этот указатель, клиент вызвал бы QueryInterface, чтобы получить интерфейс.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.api-windows.info/defekty-ole/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Классовая обертка для элементов управления</title>
		<link>http://www.api-windows.info/klassovaya-obertka-dlya-elementov-upravleniya/</link>
		<comments>http://www.api-windows.info/klassovaya-obertka-dlya-elementov-upravleniya/#comments</comments>
		<pubDate>Mon, 31 Aug 2009 19:33:13 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Классовая обертка для элементов управления]]></category>
		<category><![CDATA[получить]]></category>
		<category><![CDATA[пример]]></category>
		<category><![CDATA[программы]]></category>
		<category><![CDATA[сервере]]></category>
		<category><![CDATA[случае]]></category>
		<category><![CDATA[сообщение]]></category>
		<category><![CDATA[сообщения]]></category>
		<category><![CDATA[управления]]></category>

		<guid isPermaLink="false">http://www.api-windows.info/klassovaya-obertka-dlya-elementov-upravleniya/</guid>
		<description><![CDATA[ Элементы управления Windows 
 
 
 Перевод А. И. Легалова 
 
 
 Англоязычный оригинал находится на сервере компании Reliable Software 
 
 
 Элементы управления могут быть добавлены к основному окну или к любому диалоговому окну вашей программы. Их лучше всего выбрать и позиционировать, используя графический редактор ресурсов. Такой редактор позволяет задавать символические [...]]]></description>
			<content:encoded><![CDATA[<p> Элементы управления Windows </p>
<p> <br/>
 </p>
<p> Перевод А. И. Легалова </p>
<p> <br/>
 </p>
<p> Англоязычный оригинал находится на сервере компании Reliable Software </p>
<p> <span id="more-6"></span><br/>
 </p>
<p> Элементы управления могут быть добавлены к основному окну или к любому диалоговому окну вашей программы. Их лучше всего выбрать и позиционировать, используя графический редактор ресурсов. Такой редактор позволяет задавать символические имена, которые можно использовать для идентификации элементов управления. </p>
<p> <br/>
 </p>
<p> Большинство средств управления можно инкапсулировать в объектах, которые внедрены или в соответствующий &quot;Контроллер&quot; (Вы можете иметь отдельные объекты Controller для каждого диалогового окна программы), или, для статических элементов управления, в &quot;Виде&quot;. </p>
<p> <br/>
 </p>
<p> Объекты &mdash; &quot;Контроллеры&quot; создаются при обработке сообщения WM_CREATE или, в случае диалоговых окон, сообщением WM_INITDIALOG. При этом выполняются конструкторы элементов управления, внедренных в эти &quot;Контроллеры&quot;. </p>
<p> <br/>
 </p>
<p> Базовым классом для большинства элементов управления является SimpleControl. Он получает и сохраняет дескриптор окна специфического элемента управления. Чтобы получить этот дескриптор, необходимо иметь дескриптор родительского окна и идентификатор элемента управления. </p>
<p> <br/>
 </p>
<p> class SimpleControl { </p>
<p> <br/>
 </p>
<p> public: </p>
<p> <br/>
 </p>
<p> SimpleControl(HWND hwndParent, int id) : _hWnd(GetDlgItem(hwndParent, id)) {} </p>
<p> <br/>
 </p>
<p> void SetFocus() { </p>
<p> <br/>
 </p>
<p> ::SetFocus (_hwnd); </p>
<p> <br/>
 </p>
<p> } </p>
<p> <br/>
 </p>
<p> HWND Hwnd() const { return _hWnd; } </p>
<p> <br/>
 </p>
<p> protected: </p>
<p> <br/>
 </p>
<p> HWND _hWnd; </p>
<p> <br/>
 </p>
<p> }; </p>
<p> <br/>
 </p>
<p> Ниже представлен пример элемента управления редактированием. </p>
<p> <br/>
 </p>
<p> class Edit: public SimpleControl { </p>
<p> <br/>
 </p>
<p> public: </p>
<p> <br/>
 </p>
<p> Edit(HWND hwndParent, int id) : SimpleControl (hwndParent, id) {} </p>
<p> <br/>
 </p>
<p> void SetString(char* buf) { </p>
<p> <br/>
 </p>
<p> SendMessage(Hwnd(), WM_SETTEXT, 0, (LPARAM)buf); </p>
<p> <br/>
 </p>
<p> } </p>
<p> <br/>
 </p>
<p> // code is the HIWORD (wParam) </p>
<p> <br/>
 </p>
<p> static BOOL IsChanged (int code) { </p>
<p> <br/>
 </p>
<p> return code == EN_CHANGE; </p>
<p> <br/>
 </p>
<p> } </p>
<p> <br/>
 </p>
<p> int GetLen() { </p>
<p> <br/>
 </p>
<p> return SendMessage(Hwnd(), WM_GETTEXTLENGTH, 0, 0); </p>
<p> <br/>
 </p>
<p> } </p>
<p> <br/>
 </p>
<p> void GetString(char* buf, int len) { </p>
<p> <br/>
 </p>
<p> SendMessage(Hwnd(), WM_GETTEXT, (WPARAM)len, (LPARAM)buf); </p>
<p> <br/>
 </p>
<p> } </p>
<p> <br/>
 </p>
<p> void Select() { </p>
<p> <br/>
 </p>
<p> SendMessage(Hwnd(), EM_SETSEL, 0, &ndash;1); </p>
<p> <br/>
 </p>
<p> } </p>
<p> <br/>
 </p>
<p> }; </p>
<p> <br/>
 </p>
<p> Здесь показано, как элемент управления редактированим может использоваться: </p>
<p> <br/>
 </p>
<p> class Controller { </p>
<p> <br/>
 </p>
<p> public: </p>
<p> <br/>
 </p>
<p> Controller(HWND hwnd); </p>
<p> <br/>
 </p>
<p> &hellip; </p>
<p> <br/>
 </p>
<p> private: </p>
<p> <br/>
 </p>
<p> Edit _edit; </p>
<p> <br/>
 </p>
<p> char _string[maxLen]; </p>
<p> <br/>
 </p>
<p> }; </p>
<p> <br/>
 </p>
<p> <br/>
 </p>
<p> Controller::Controller(HWND hwnd) : _edit(hwnd, IDC_EDIT) { </p>
<p> <br/>
 </p>
<p> _edit.SetFocus(); </p>
<p> <br/>
 </p>
<p> &hellip; </p>
<p> <br/>
 </p>
<p> } </p>
<p> <br/>
 </p>
<p> <br/>
 </p>
<p> void Controller::Command(HWND hwnd, WPARAM wParam, LPARAM lParam) { </p>
<p> <br/>
 </p>
<p> switch (LOWORD(wParam)) { </p>
<p> <br/>
 </p>
<p> case IDC_EDIT: </p>
<p> <br/>
 </p>
<p> if (_edit.IsChanged(HIWORD (wParam))) { </p>
<p> <br/>
 </p>
<p> _edit.GetString(_string, maxLen); </p>
<p> <br/>
 </p>
<p> } </p>
<p> <br/>
 </p>
<p> break; </p>
<p> <br/>
 </p>
<p> &hellip; </p>
<p> <br/>
 </p>
<p> } </p>
<p> <br/>
 </p>
<p> } </p>
<p> <br/>
 </p>
<p> Далее: Естественно, что наиболее вероятным местом использования элемента управления является диалоговое окно.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.api-windows.info/klassovaya-obertka-dlya-elementov-upravleniya/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Как разделить окно на части</title>
		<link>http://www.api-windows.info/kak-razdelit-okno-na-chasti/</link>
		<comments>http://www.api-windows.info/kak-razdelit-okno-na-chasti/#comments</comments>
		<pubDate>Wed, 19 Aug 2009 11:19:34 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Как разделить окно на части]]></category>
		<category><![CDATA[Пользователь]]></category>
		<category><![CDATA[посылает]]></category>
		<category><![CDATA[потому]]></category>
		<category><![CDATA[приложение]]></category>
		<category><![CDATA[приложения]]></category>
		<category><![CDATA[пример]]></category>
		<category><![CDATA[программа]]></category>
		<category><![CDATA[простой]]></category>
		<category><![CDATA[процедура]]></category>
		<category><![CDATA[процедуру]]></category>
		<category><![CDATA[расщепителя]]></category>
		<category><![CDATA[сделать]]></category>
		<category><![CDATA[сервере]]></category>
		<category><![CDATA[случае]]></category>
		<category><![CDATA[сообщение]]></category>
		<category><![CDATA[сообщений]]></category>
		<category><![CDATA[сообщения]]></category>
		<category><![CDATA[способ]]></category>
		<category><![CDATA[строку]]></category>
		<category><![CDATA[также]]></category>
		<category><![CDATA[только]]></category>
		<category><![CDATA[функции]]></category>
		<category><![CDATA[через]]></category>

		<guid isPermaLink="false">http://www.api-windows.info/kak-razdelit-okno-na-chasti/</guid>
		<description><![CDATA[ Разделительная полоска (сплиттер) 
 
 
 Перевод А. И. Легалова 
 
 
 Англоязычный оригинал находится на сервере компании Reliable Software 
 
 
 Разделительная полоска &#8212; полезный элемент, который не входит в состав элементову правления Windows. Насколько трудной его реализовать? Не столь трудно, как это кажется, если Вы знаете хотя бы основы Windows [...]]]></description>
			<content:encoded><![CDATA[<p> Разделительная полоска (сплиттер) </p>
<p> <br/>
 </p>
<p> Перевод А. И. Легалова </p>
<p> <br/>
 </p>
<p> Англоязычный оригинал находится на сервере компании Reliable Software </p>
<p> <span id="more-17"></span><br/>
 </p>
<p> Разделительная полоска &mdash; полезный элемент, который не входит в состав элементову правления Windows. Насколько трудной его реализовать? Не столь трудно, как это кажется, если Вы знаете хотя бы основы Windows API. Представленное описание может в начале показаться сложным, но вы изучите несколько очень важных методов, которые могут многократно использоваться в различных местах. Работа с дочерними окнами, сбор данных от мыши, рисование с использованием xor (исключающего или) режима &mdash; вот только некоторые из них. </p>
<p> <br/>
 </p>
<p> <br/>
 </p>
<p> Сплиттер &mdash; это окно. Точнее &mdash; это дочернее окно. Оно позиционировано между двумя другими дочерними окнами &mdash; мы назовем их левым и правым подокном, соответственно (или верхним и нижним для горизонтального расщепителя). Должно также быть основное окно, явялющееся родителем для трех дочерних. </p>
<p> <br/>
 </p>
<p> Без дальнейшей суеты приведем код WinMain, который осуществляет начальные установки. </p>
<p> <br/>
 </p>
<p> // Create top window class </p>
<p> <br/>
 </p>
<p> TopWinClassMaker topWinClass(WndProcMain, ID_MAIN, hInst, ID_MAIN); </p>
<p> <br/>
 </p>
<p> topWinClass.Register(); </p>
<p> <br/>
 </p>
<p> <br/>
 </p>
<p> // Create child pane classes </p>
<p> <br/>
 </p>
<p> WinClassMaker paneClass(WndProcPane, IDC_PANE, hInst); </p>
<p> <br/>
 </p>
<p> paneClass.SetSysCursor(IDC_IBEAM); </p>
<p> <br/>
 </p>
<p> paneClass.SetDblClicks(); </p>
<p> <br/>
 </p>
<p> paneClass.Register(); </p>
<p> <br/>
 </p>
<p> <br/>
 </p>
<p> Splitter::RegisterClass(hInst); </p>
<p> <br/>
 </p>
<p> <br/>
 </p>
<p> // Create top window </p>
<p> <br/>
 </p>
<p> ResString caption(hInst, ID_CAPTION); </p>
<p> <br/>
 </p>
<p> TopWinMaker topWin(caption, ID_MAIN, hInst); </p>
<p> <br/>
 </p>
<p> topWin.Create(); </p>
<p> <br/>
 </p>
<p> topWin.Show(cmdShow); </p>
<p> <br/>
 </p>
<p> В начале мы регистрируем классы. Верхний оконный класс связан с его оконной процедурой WndProcMain, которую мы рассмотрим через мгновение. Два дочерних подокна совместно используют тот же самый класс окна, связанный с WndProcPane. Затем регистрируется наш собственный класс сплиттера (мы скоро увидем его код). В заключение, создается и отображается верхнее окно. Дочерние окна создаются динамически во время инициализации родительского окна. </p>
<p> <br/>
 </p>
<p> Приведем оконную процедуру верхнего окна. </p>
<p> <br/>
 </p>
<p> LRESULT CALLBACK WndProcMain(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { </p>
<p> <br/>
 </p>
<p> Controller* pCtrl = GetWinLong&lt;Controller *&gt;(hwnd); </p>
<p> <br/>
 </p>
<p> switch (message) { </p>
<p> <br/>
 </p>
<p> case WM_CREATE: </p>
<p> <br/>
 </p>
<p> try { </p>
<p> <br/>
 </p>
<p> pCtrl = new Controller(hwnd, reinterpret_cast&lt;CREATESTRUCT *&gt;(lParam)); </p>
<p> <br/>
 </p>
<p> SetWinLong&lt;Controller*&gt;(hwnd, pCtrl); </p>
<p> <br/>
 </p>
<p> } catch (char const* msg) { </p>
<p> <br/>
 </p>
<p> MessageBox(hwnd, msg, &quot;Initialization&quot;, MB_ICONEXCLAMATION | MB_OK); </p>
<p> <br/>
 </p>
<p> return -1; </p>
<p> <br/>
 </p>
<p> } catch (...) { </p>
<p> <br/>
 </p>
<p> MessageBox(hwnd, &quot;Unknown Error&quot;, &quot;Initialization&quot;, MB_ICONEXCLAMATION | MB_OK); </p>
<p> <br/>
 </p>
<p> return -1; </p>
<p> <br/>
 </p>
<p> } </p>
<p> <br/>
 </p>
<p> return 0; </p>
<p> <br/>
 </p>
<p> case WM_SIZE: </p>
<p> <br/>
 </p>
<p> pCtrl-&gt;Size(LOWORD(lParam), HIWORD(lParam)); </p>
<p> <br/>
 </p>
<p> return 0; </p>
<p> <br/>
 </p>
<p> case MSG_MOVESPLITTER: </p>
<p> <br/>
 </p>
<p> pCtrl-&gt;MoveSplitter(wParam); </p>
<p> <br/>
 </p>
<p> return 0; </p>
<p> <br/>
 </p>
<p> case WM_DESTROY: </p>
<p> <br/>
 </p>
<p> SetWinLong&lt;Controller*&gt;(hwnd, 0); </p>
<p> <br/>
 </p>
<p> delete pCtrl; </p>
<p> <br/>
 </p>
<p> return 0; </p>
<p> <br/>
 </p>
<p> } </p>
<p> <br/>
 </p>
<p> return ::DefWindowProc(hwnd, message, wParam, lParam); </p>
<p> <br/>
 </p>
<p> } </p>
<p> <br/>
 </p>
<p> Имеем обычную оконную процедуру за исключением одного сообщения: MSG_MOVESPLITTER. Это &mdash; наше собственное, определяемое пользователем сообщение, которое послано сплиттером его родительскому окну. Но сначала давайте взглянем на контроллер главного окна. </p>
<p> <br/>
 </p>
<p> class Controller { </p>
<p> <br/>
 </p>
<p> public: </p>
<p> <br/>
 </p>
<p> Controller(HWND hwnd, CREATESTRUCT* pCreat); </p>
<p> <br/>
 </p>
<p> ~Controller(); </p>
<p> <br/>
 </p>
<p> void Size(int cx, int cy); </p>
<p> <br/>
 </p>
<p> void MoveSplitter(int x); </p>
<p> <br/>
 </p>
<p> private: </p>
<p> <br/>
 </p>
<p> enum { splitWidth = 8 }; // width of splitter </p>
<p> <br/>
 </p>
<p> // User Interface </p>
<p> <br/>
 </p>
]]></content:encoded>
			<wfw:commentRss>http://www.api-windows.info/kak-razdelit-okno-na-chasti/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Использование фабрики классов для окон диалога</title>
		<link>http://www.api-windows.info/ispolzovanie-fabriki-klassov-dlya-okon-dialoga/</link>
		<comments>http://www.api-windows.info/ispolzovanie-fabriki-klassov-dlya-okon-dialoga/#comments</comments>
		<pubDate>Tue, 28 Jul 2009 09:03:30 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Использование фабрики классов для окон диалога]]></category>
		<category><![CDATA[Пользователь]]></category>
		<category><![CDATA[посылает]]></category>
		<category><![CDATA[пример]]></category>
		<category><![CDATA[программе]]></category>
		<category><![CDATA[программы]]></category>
		<category><![CDATA[простой]]></category>
		<category><![CDATA[процедура]]></category>
		<category><![CDATA[процедуре]]></category>
		<category><![CDATA[процедуру]]></category>
		<category><![CDATA[сервере]]></category>
		<category><![CDATA[случае]]></category>
		<category><![CDATA[создать]]></category>
		<category><![CDATA[сообщение]]></category>
		<category><![CDATA[сообщений]]></category>
		<category><![CDATA[сообщения]]></category>
		<category><![CDATA[способ]]></category>
		<category><![CDATA[строку]]></category>
		<category><![CDATA[также]]></category>
		<category><![CDATA[того]]></category>
		<category><![CDATA[только]]></category>
		<category><![CDATA[указатель]]></category>
		<category><![CDATA[управления]]></category>
		<category><![CDATA[функции]]></category>
		<category><![CDATA[через]]></category>

		<guid isPermaLink="false">http://www.api-windows.info/ispolzovanie-fabriki-klassov-dlya-okon-dialoga/</guid>
		<description><![CDATA[ Окно диалога 
 
 
 Перевод А. И. Легалова 
 
 
 Англоязычный оригинал находится на сервере компании Reliable Software 
 
 
 Отсюда можно загрузить программу, демонстрирующую окно диалога (zip архив 14 кб) 
 
 
 Диалоговое окно для Windows программы является тем же, чем является вызов функции для программы на языке C. [...]]]></description>
			<content:encoded><![CDATA[<p> Окно диалога </p>
<p> <br/>
 </p>
<p> Перевод А. И. Легалова </p>
<p> <br/>
 </p>
<p> Англоязычный оригинал находится на сервере компании Reliable Software </p>
<p> <span id="more-8"></span><br/>
 </p>
<p> Отсюда можно загрузить программу, демонстрирующую окно диалога (zip архив 14 кб) </p>
<p> <br/>
 </p>
<p> Диалоговое окно для Windows программы является тем же, чем является вызов функции для программы на языке C. Сначала, Windows программы передают некоторые данные диалоговому окну, чтобы инициализировать его. Затем диалоговое окно обменивается информацией с пользователем. Когда пользователь решает, что любопытство программы было удовлетворено, он (или она) нажимает кнопку OK. Вновь полученные данные возвращаются обратно программе. </p>
<p> <br/>
 </p>
<p> Диалоговое окно обычно взаимодействует со всеми видами элементов управления (виджетами, устройствами, гизмозами &mdash; называйте их как хотите). Код диалогового окна взаимодействует с этими элементами, посылая и получая сообщения через свою &laquo;Процедуру диалога&raquo;. В реализациях различных диалоговых окон имеется много общего кода. Нам хотелось бы написать и отладить этот код только один раз, а затем многократно использовать его. </p>
<p> <br/>
 </p>
<p> Что изменяется от диалога к диалогу: </p>
<p> <br/>
 </p>
<p> &bull; Разновидность данных, которые передаются в диалог и возвращаются из него. </p>
<p> <br/>
 </p>
<p> &bull; Разновидность элементов внутри диалогового окна. </p>
<p> <br/>
 </p>
<p> &bull; Взаимодействие между элементами. </p>
<p> <br/>
 </p>
<p> Эта изменчивость может быть инкапсулирована в двух специальных клиентских классах: классе списка параметров и классе контроллера диалога. </p>
<p> <br/>
 </p>
<p> Класс списка параметров инкапсулирует внутри себя параметры. Он обеспечивает доступ для их восстановления и изменения. Определение и реализация этого класса находятся под полным контролем клиента (программиста, многократно использующего наш код). </p>
<p> <br/>
 </p>
<p> Класс контроллера диалога содержит объекты управления для всех элементов диалога и осуществляет взаимодействия между ними. Клиент, как предполагается, получает этот класс от абстрактного класса DlgController и реализует все его чистые виртуальные методы. </p>
<p> <br/>
 </p>
<p> Остальное &mdash; только клей. Нам необходимо параметризировать шаблон класса CtrlFactory, который используется нашей обобщенной реализацией класса ModalDialog. Фабрика контроллера создает соответствующий, определенный клиентом, контроллер и возвращает полиморфный указатель на него. Рис. 1 показывает связи между различными классами, включаемыми в реализацию диалогового окна. </p>
<p> <br/>
 </p>
<p> <br/>
 </p>
<p> Рис. 1. Классы, включаемые в образец проектирования &quot;Диалоговое окно&quot;. </p>
<p> <br/>
 </p>
<p> Давайте, начнем с клиентского кода. В нашей обобщенной программе мы нуждаемся в диалоговом окне, которое позволяет пользователю редактировать строку. Используя редактор ресурса, мы создаем шаблон диалога, который содержит средства редактирования и две кнопки, OK и CANCEL. Идентификатор ресурса (id) этого диалога &ndash; IDD_EDITDIALOG. Затем мы определяем наш собственный класс списка параметров по имени EditorData и специальный класс контроллера по имени EditorCtrl. Когда пользователь выбирает пункт меню Edit, будет выполняться следующий код: </p>
<p> <br/>
 </p>
<p> void Controller::Edit(HWND hwnd) { </p>
<p> <br/>
 </p>
<p> EditorData data(_model.GetText ()); </p>
<p> <br/>
 </p>
<p> ControllerFactory&lt;EditorCtrl, EditorData&gt; factory(&amp;data); </p>
<p> <br/>
 </p>
<p> ModalDialog dialog(_hInst, hwnd, IDD_EDITDIALOG, &amp;factory); </p>
<p> <br/>
 </p>
<p> if (dialog.IsOk()) { </p>
<p> <br/>
 </p>
<p> _model.SetText(data.GetName()); </p>
<p> <br/>
 </p>
<p> // Force repaint </p>
<p> <br/>
 </p>
<p> InvalidateRect(hwnd, 0, TRUE); </p>
<p> <br/>
 </p>
<p> } </p>
<p> <br/>
 </p>
<p> } </p>
<p> <br/>
 </p>
<p> Сначала создается и инициализируется строкой объект EditorData. Затем, формируется шаблон ControllerFactory. Мы параметризуем его двумя клиентскими классами EditorCtrl и EditorData. Объект фабрики инициализирован указателем на наши данные. Затем создается объект ModalDialog. Он получет указатель на нашу фабрику в качестве параметра. Это используется для того, чтобы создать объект контроллера и восстанавливать данные из списка параметров. После того, как проведено взаимодействие с пользователем, мы проверяем, подтверждал ли пользователь результаты, нажимая кнопку OK, и если так, то мы фиксируем результаты редактирования и используем их в нашей программе. Этот способ создания диалогового окна является наиболее типичным. </p>
<p> <br/>
 </p>
<p> Класс EditorData в нашем примере предельно прост. </p>
<p> <br/>
 </p>
<p> class EditorData { </p>
<p> <br/>
 </p>
<p> public: </p>
<p> <br/>
 </p>
<p> enum { maxLen = 128 }; </p>
<p> <br/>
 </p>
<p> EditorData(char const* name) { </p>
<p> <br/>
 </p>
<p>
]]></content:encoded>
			<wfw:commentRss>http://www.api-windows.info/ispolzovanie-fabriki-klassov-dlya-okon-dialoga/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
