Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
A témakör elolvasása előtt szüksége lesz a A C++/CX-ről a C++/WinRT-re való áttérés című témakörben található információkra. Ez a témakör két fő stratégiai lehetőséget mutat be a C++/CX projekt C+++/WinRT-be történő átviteléhez.
- Portolja a teljes projektet egyetlen lépésben. Egy nem túl nagy projekt legegyszerűbb lehetősége. Ha Windows-futtatókörnyezet összetevőprojektje van, akkor ez a stratégia az egyetlen lehetőség.
- A projektet fokozatosan portolhatja (a kódbázis mérete vagy összetettsége ezt szükségessé teheti). Ez a stratégia azonban arra kéri, hogy kövessen egy portálási folyamatot, amelyben egy ideig a C++/CX és a C++/WinRT kód egymás mellett létezik ugyanabban a projektben. XAML-projekt esetén egy adott időpontban a XAML-oldaltípusoknak vagy mind C++/WinRT-, vagy mind C++/CX-típusúnak kell lenniük.
Ez az interoperabilitási témakör ehhez a második stratégiához kapcsolódik – azokban az esetekben, amikor fokozatosan kell átültetnie a projektjét. Ez a témakör a C++/CX objektumok (és más típusok) C++/WinRT objektummá alakításához használható segédfüggvények különböző formáit mutatja be (és fordítva).
Ezek a segédfüggvények nagyon hasznosak lesznek, mivel a kódot fokozatosan portozza C++/CX-ről C++/WinRT-be. Vagy dönthet úgy is, hogy ugyanabban a projektben a C++/WinRT és a C++/CX nyelvi projekciót is használja, akár éppen portol, akár nem, és ezekkel a segédfüggvényekkel interoperabilitást biztosít a kettő között.
A témakör elolvasása után további információ- és kódpéldákat találhat, amelyek bemutatják, hogyan támogathatja a PPL-feladatokat és a coroutine-okat egymás mellett ugyanabban a projektben (például a coroutinest a tevékenységláncokból hívhatja meg), tekintse meg a fejlettebb Aszinkron témakört, valamint a C++/WinRT és a C+++/CX közötti együttműködéseket.
A from_cx és to_cx függvények
Íme egy interop_helpers.h nevű fejlécfájl forráskódlistája, amely különféle konverziós segédfüggvényeket tartalmaz. Ahogy fokozatosan portozza a projektet, a C++/CX- és a C++/WinRT-be portolt részek is megmaradnak. Ezeket a segédfüggvényeket arra használhatja, hogy objektumokat (és más típusokat) oda-vissza konvertáljon a projektben a C++/CX és a C++/WinRT között, e két rész közötti illesztési pontokon.
A kódlistát követő szakaszok ismertetik a segédfüggvényeket, valamint a projekt fejlécfájljának létrehozását és használatát.
// interop_helpers.h
#pragma once
template <typename T>
T from_cx(Platform::Object^ from)
{
T to{ nullptr };
if (from != nullptr)
{
winrt::check_hresult(reinterpret_cast<::IUnknown*>(from)
->QueryInterface(winrt::guid_of<T>(), winrt::put_abi(to)));
}
return to;
}
template <typename T>
T^ to_cx(winrt::Windows::Foundation::IUnknown const& from)
{
return safe_cast<T^>(reinterpret_cast<Platform::Object^>(winrt::get_abi(from)));
}
inline winrt::hstring from_cx(Platform::String^ const& from)
{
return reinterpret_cast<winrt::hstring&>(const_cast<Platform::String^&>(from));
}
inline Platform::String^ to_cx(winrt::hstring const& from)
{
return reinterpret_cast<Platform::String^&>(const_cast<winrt::hstring&>(from));
}
inline winrt::guid from_cx(Platform::Guid const& from)
{
return reinterpret_cast<winrt::guid&>(const_cast<Platform::Guid&>(from));
}
inline Platform::Guid to_cx(winrt::guid const& from)
{
return reinterpret_cast<Platform::Guid&>(const_cast<winrt::guid&>(from));
}
A from_cx függvény
A from_cx segédfüggvény C++/CX objektumot konvertál egyenértékű C++/WinRT objektummá. A függvény egy C++/CX objektumot vet a mögöttes IUnknown felület mutatójára. Ezután meghívja a QueryInterface-t arra a mutatóra, hogy lekérdezhesse a C++/WinRT objektum alapértelmezett felületét. A QueryInterface a C++/CX safe_cast kiterjesztés Windows-futtatókörnyezet alkalmazásbináris felületi (ABI) megfelelője. A winrt::p ut_abi függvény pedig lekéri egy C++/WinRT-objektum mögöttes IUnknown felületi mutatójának címét, hogy az másik értékre legyen állítva.
A to_cx függvény
A to_cx segédfüggvény egy C++/WinRT objektumot egyenértékű C++/CX objektummá konvertál. A winrt::get_abi függvény egy C++/WinRT-objektum mögöttes IUnknown felületére mutató mutatót kér le. A függvény először C++/CX objektummá alakítja a mutatót, majd a C++/CX safe_cast kiterjesztés használatával lekérdezi a kért C++/CX típust.
A interop_helpers.h fejlécfájl
A projekt segédfüggvényeinek használatához kövesse az alábbi lépéseket.
- Adjon hozzá egy új fejlécfájlt (.h) a projekthez, és nevezze el.
interop_helpers.h - Cserélje le a(z)
interop_helpers.htartalmát a fenti kódlistában szereplő kódra. - Adja hozzá ezeket a bővítményeket a következőhöz
pch.h:
// pch.h
...
#include <unknwn.h>
// Include C++/WinRT projected Windows API headers here.
...
#include <interop_helpers.h>
C++/CX projekt készítése és C++/WinRT-támogatás hozzáadása
Ez a szakasz azt ismerteti, hogy mi a teendő, ha úgy döntött, hogy a meglévő C++/CX projektet használja, hozzáadja a C++/WinRT-támogatást, és ott végzi a portolást. Lásd még Visual Studio C++/WinRT támogatását.
A C++/CX és a C++/WinRT C++/CX projektben való kombinálásához – beleértve a projekt from_cx és to_cx segédfüggvényeinek használatát is – manuálisan kell hozzáadnia a C++/WinRT-támogatást a projekthez.
Először nyissa meg a C++/CX projektet a Visual Studio, és győződjön meg arról, hogy a Project Property General>Target Platform Version értéke 10.0.17134.0 (Windows 10, 1803-es verzió) vagy újabb.
A C++/WinRT NuGet csomag telepítése
A Microsoft.Windows. A CppWinRT NuGet-csomag C++/WinRT buildtámogatást biztosít (MSBuild tulajdonságok és célok). A telepítéshez kattintson a Project>Manage NuGet Packages...>Browse menüpontra, írja be vagy illessze be a(z) Microsoft.Windows.CppWinRT nevet a keresőmezőbe, válassza ki az elemet a keresési eredmények közül, majd kattintson a Install gombra a csomag adott projekthez való telepítéséhez.
Fontos
A C++/WinRT NuGet csomag telepítése miatt a C++/CX támogatása ki van kapcsolva a projektben. Ha egy menetben szeretné elvégezni a portolást, akkor érdemes kikapcsolva hagyni ezt a támogatást, hogy az összeállítási üzenetek segítsenek megtalálni (és átportolni) a C++/CX-re támaszkodó összes függőséget (így a korábban tisztán C++/CX-projekt végül tisztán C++/WinRT-projektté válik). A visszakapcsolásról a következő szakaszban olvashat.
A C++/CX támogatás visszakapcsolása
Ha egyetlen lépésben portolsz, akkor ezt nem kell megtenned. Ha azonban fokozatosan kell portolnia, akkor ezen a ponton újra be kell kapcsolnia a C++/CX támogatást a projektben. A projekt tulajdonságainál a C/C++>Általános>Windows-futtatókörnyezet-bővítmény használata>Igen (/ZW)).
Másik lehetőségként (vagy XAML-projekt esetén) C++/CX-támogatást is hozzáadhat a C++/WinRT projekttulajdonságok lapján a Visual Studio. A projekt tulajdonságainál, Általános tulajdonságok>C++/WinRT>Projekt nyelve>C++/CX. Ezzel hozzáadja a következő tulajdonságot a .vcxproj fájlhoz.
<PropertyGroup Label="Globals">
<CppWinRTProjectLanguage>C++/CX</CppWinRTProjectLanguage>
</PropertyGroup>
Fontos
Amikor a Midl-fájl (.idl) tartalmát csonkfájlokká való feldolgozáshoz fordítania kell, vissza kell állítania a Projekt nyelve beállítást C++/WinRT értékre. Miután a fordítás létrehozta ezeket a stubokat, módosítsa a Projekt nyelve beállítást vissza C++/CX értékre.
A cppwinrt.exe eszköz működését finomhangoló hasonló testreszabási lehetőségek listáját lásd a Microsoft.Windows.CppWinRT NuGet-csomag readme fájljában.
C++/WinRT-fejlécfájlok belefoglalása
Legalább annyit tegyen meg, hogy a precompiled header fájlba (általában pch.h) felveszi a winrt/base.h elemet, az alábbiak szerint.
// pch.h
...
#include <winrt/base.h>
...
De szinte biztosan szüksége lesz a winrt::Windows::Foundation névtér típusára. És lehet, hogy már tud más névterekről, amelyekre szüksége lesz. Tehát a következőképpen foglalja bele az ezeknek a névtereknek megfelelő, a C++/WinRT által leképezett Windows API-fejléceket (a winrt/base.h elemet most már nem kell külön belefoglalnia, mert a rendszer automatikusan belefoglalja).
// pch.h
...
#include <winrt/Windows.Foundation.h>
// Include any other C++/WinRT projected Windows API headers here.
...
Lásd még a következő szakaszban található kódpéldát (Egy C++/WinRT-projekt átalakítása és a C++/CX támogatás hozzáadása), amely a namespace cx és namespace winrt névtéraliasokat használó technikát mutat be. Ez a technika lehetővé teszi a C++/WinRT-vetítés és a C++/CX-vetítés közötti esetleges névtérütközések kezelését.
Adja hozzá interop_helpers.h a projekthez
Mostantól hozzáadhatja a from_cx és to_cx függvényeket a C++/CX projekthez. Ehhez útmutatást a fenti from_cx és to_cx függvények szakaszában talál.
C++/WinRT-projekt készítése és C++/CX-támogatás hozzáadása
Ez a szakasz azt ismerteti, hogy mi a teendő, ha úgy döntött, hogy létrehoz egy új C++/WinRT-projektet, és ott végzi a portolást.
A C++/WinRT és a C++/CX egy C++/WinRT-projektben való kombinálásához – beleértve a projekt from_cx és to_cx segédfüggvényeinek használatát is – manuálisan kell hozzáadnia a C++/CX támogatást a projekthez.
- Hozzon létre egy új C++/WinRT-projektet Visual Studio a C++/WinRT projektsablonok egyikével (lásd Visual Studio C++/WinRT támogatásával).
- A C++/CX projekttámogatásának bekapcsolása. A projekt tulajdonságainál a C/C++>Általános>Windows-futtatókörnyezet bővítmény használata>Igen (/ZW).
Példa C++/WinRT projektre, amely a két használt segédfüggvényt mutatja be
Ebben a szakaszban létrehozhat egy C++/WinRT-projektet, amely bemutatja, hogyan használható from_cx és to_cx. Azt is bemutatja, hogyan használhat névtér-aliasokat a kód különböző szigeteihez, hogy kezelni tudja a C++/WinRT-vetítés és a C++/CX-előrejelzés közötti esetleges névtér-ütközéseket.
- Hozzon létre egy Visual C++>Windows Universal>Core App (C++/WinRT) projektet.
- A projekt tulajdonságainál: C/C++>General>Consume Windows-futtatókörnyezet Extension>Yes (/ZW).
- Adja hozzá a(z)
interop_helpers.helemet a projekthez. Ehhez útmutatást a fenti from_cx és to_cx függvények szakaszában talál. - Cserélje le a
App.cpptartalmát az alábbi kódra. - Építés és futtatás.
WINRT_ASSERT egy makródefiníció, és _ASSERTE elemre bővül.
// App.cpp
#include "pch.h"
#include <sstream>
namespace cx
{
using namespace Windows::Foundation;
}
namespace winrt
{
using namespace Windows;
using namespace Windows::ApplicationModel::Core;
using namespace Windows::Foundation;
using namespace Windows::Foundation::Numerics;
using namespace Windows::UI;
using namespace Windows::UI::Core;
using namespace Windows::UI::Composition;
}
struct App : winrt::implements<App, winrt::IFrameworkViewSource, winrt::IFrameworkView>
{
winrt::CompositionTarget m_target{ nullptr };
winrt::VisualCollection m_visuals{ nullptr };
winrt::Visual m_selected{ nullptr };
winrt::float2 m_offset{};
winrt::IFrameworkView CreateView()
{
return *this;
}
void Initialize(winrt::CoreApplicationView const &)
{
}
void Load(winrt::hstring const&)
{
}
void Uninitialize()
{
}
void Run()
{
winrt::CoreWindow window = winrt::CoreWindow::GetForCurrentThread();
window.Activate();
winrt::CoreDispatcher dispatcher = window.Dispatcher();
dispatcher.ProcessEvents(winrt::CoreProcessEventsOption::ProcessUntilQuit);
}
void SetWindow(winrt::CoreWindow const & window)
{
winrt::Compositor compositor;
winrt::ContainerVisual root = compositor.CreateContainerVisual();
m_target = compositor.CreateTargetForCurrentView();
m_target.Root(root);
m_visuals = root.Children();
window.PointerPressed({ this, &App::OnPointerPressed });
window.PointerMoved({ this, &App::OnPointerMoved });
window.PointerReleased([&](auto && ...)
{
m_selected = nullptr;
});
}
void OnPointerPressed(IInspectable const &, winrt::PointerEventArgs const & args)
{
winrt::float2 const point = args.CurrentPoint().Position();
for (winrt::Visual visual : m_visuals)
{
winrt::float3 const offset = visual.Offset();
winrt::float2 const size = visual.Size();
if (point.x >= offset.x &&
point.x < offset.x + size.x &&
point.y >= offset.y &&
point.y < offset.y + size.y)
{
m_selected = visual;
m_offset.x = offset.x - point.x;
m_offset.y = offset.y - point.y;
}
}
if (m_selected)
{
m_visuals.Remove(m_selected);
m_visuals.InsertAtTop(m_selected);
}
else
{
AddVisual(point);
}
}
void OnPointerMoved(IInspectable const &, winrt::PointerEventArgs const & args)
{
if (m_selected)
{
winrt::float2 const point = args.CurrentPoint().Position();
m_selected.Offset(
{
point.x + m_offset.x,
point.y + m_offset.y,
0.0f
});
}
}
void AddVisual(winrt::float2 const point)
{
winrt::Compositor compositor = m_visuals.Compositor();
winrt::SpriteVisual visual = compositor.CreateSpriteVisual();
static winrt::Color colors[] =
{
{ 0xDC, 0x5B, 0x9B, 0xD5 },
{ 0xDC, 0xED, 0x7D, 0x31 },
{ 0xDC, 0x70, 0xAD, 0x47 },
{ 0xDC, 0xFF, 0xC0, 0x00 }
};
static unsigned last = 0;
unsigned const next = ++last % _countof(colors);
visual.Brush(compositor.CreateColorBrush(colors[next]));
float const BlockSize = 100.0f;
visual.Size(
{
BlockSize,
BlockSize
});
visual.Offset(
{
point.x - BlockSize / 2.0f,
point.y - BlockSize / 2.0f,
0.0f,
});
m_visuals.InsertAtTop(visual);
m_selected = visual;
m_offset.x = -BlockSize / 2.0f;
m_offset.y = -BlockSize / 2.0f;
}
};
int __stdcall wWinMain(HINSTANCE, HINSTANCE, PWSTR, int)
{
winrt::init_apartment();
winrt::Uri uri(L"http://aka.ms/cppwinrt");
std::wstringstream wstringstream;
wstringstream << L"C++/WinRT: " << uri.Domain().c_str() << std::endl;
// Convert from a C++/WinRT type to a C++/CX type.
cx::Uri^ cx = to_cx<cx::Uri>(uri);
wstringstream << L"C++/CX: " << cx->Domain->Data() << std::endl;
::OutputDebugString(wstringstream.str().c_str());
// Convert from a C++/CX type to a C++/WinRT type.
winrt::Uri uri_from_cx = from_cx<winrt::Uri>(cx);
WINRT_ASSERT(uri.Domain() == uri_from_cx.Domain());
WINRT_ASSERT(uri == uri_from_cx);
winrt::CoreApplication::Run(winrt::make<App>());
}
Fontos API-k
Kapcsolódó témakörök
Windows developer