Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
Bu konuyu okumadan önce C++/CX'ten C++/WinRT'ye taşı başlığındaki bilgilere ihtiyacınız olacaktır. Bu konu başlığında C++/CX projenizi C++/WinRT'ye taşımaya yönelik iki ana strateji seçeneği tanıtılmaktadır.
- Projenin tamamını tek geçişte taşıma. Çok büyük olmayan bir proje için en basit seçenek. Windows Çalışma Zamanı bileşen projeniz varsa tek seçeneğiniz bu stratejidir.
- Projeyi aşamalı olarak taşıma (kod tabanınızın boyutu veya karmaşıklığı bunu gerekli hale getirebilir). Ancak bu strateji, bir süre için C++/CX ve C++/WinRT kodunun aynı projede yan yana bulunduğu bir taşıma işlemini izlemenizi gerektirir. Bir XAML projesi için, herhangi bir zamanda XAML sayfa türlerinizin tümü C ++/WinRT veya tüm C++/CX olmalıdır.
Bu birlikte çalışabilirlik konusu, projenizi aşamalı olarak taşımanız gereken durumlarda ikinci strateji için geçerlidir. Bu konu başlığında, bir C++/CX nesnesini (ve diğer türleri) aynı proje içindeki bir C++/WinRT nesnesine (ve tersi) dönüştürmek için kullanabileceğiniz çeşitli yardımcı işlev çiftleri gösterilmektedir.
Kodunuzu C++/CX'ten C++/WinRT'ye aşamalı olarak taşımanız nedeniyle bu yardımcı işlevler çok yararlı olacaktır. Ya da aynı projede hem C++/WinRT hem de C++/CX dil projeksiyonlarını (taşıma veya taşımama) kullanmayı seçebilir ve ikisi arasında birlikte çalışma için bu yardımcı işlevleri kullanabilirsiniz.
Bu konuyu okuduktan sonra, aynı projede (örneğin, görev zincirlerinden eş yordamları çağırma) PPL görevlerini ve eş yordamları yan yana desteklemeyi gösteren bilgi ve kod örnekleri için daha gelişmiş Zaman Uyumsuzluk konusuna ve C++/WinRT ile C++/CX arasında birlikte çalışma konusuna bakın.
from_cx ve to_cx işlevleri
Aşağıda, çeşitli dönüştürme yardımcı işlevlerini içeren adlı interop_helpers.hüst bilgi dosyasının kaynak kod listesi verilmiştir. Projenizi aşamalı olarak taşımaya devam ettikçe C++/CX içinde kalan bölümler ve C++/WinRT'ye aktardığınız bölümler olacaktır. Projenizde nesneleri (ve diğer türleri), bu iki bölüm arasındaki sınır noktalarında C++/CX ile C++/WinRT arasında dönüştürmek için bu yardımcı işlevleri kullanabilirsiniz.
Kod listesini izleyen bölümler yardımcı işlevleri ve projenizde üst bilgi dosyasının nasıl oluşturulup kullanılacağını açıklar.
// 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));
}
from_cx işlevi
from_cx yardımcı işlevi, bir C++/CX nesnesini eşdeğer bir C++/WinRT nesnesine dönüştürür. İşlev, bir C++/CX nesnesini temel aldığı IUnknown arabirim işaretçisine dönüştürür. Ardından, C++/WinRT nesnesinin varsayılan arabirimini sorgulamak için bu işaretçide QueryInterface'i çağırır.
QueryInterface, C++/CX safe_cast uzantısının Windows Çalışma Zamanı uygulama ikili arabirimi (ABI) eşdeğeridir. Ve, winrt::put_abi işlevi, bir C++/WinRT nesnesinin temelindeki IUnknown arabirim işaretçisinin adresini, başka bir değere ayarlanabilmesi için alır.
to_cx işlevi
to_cx yardımcı işlevi bir C++/WinRT nesnesini eşdeğer bir C++/CX nesnesine dönüştürür.
winrt::get_abi işlevi, bir C++/WinRT nesnesinin temelindeki IUnknown arabirimine yönelik bir işaretçi döndürür. İşlev, istenen C++/CX türünü sorgulamak için C++/CX safe_cast uzantısını kullanmadan önce bu işaretçiyi bir C++/CX nesnesine dönüştürür.
interop_helpers.h başlık dosyası
Projenizdeki yardımcı işlevleri kullanmak için aşağıdaki adımları izleyin.
- Projenize yeni bir Üst Bilgi Dosyası (.h) öğesi ekleyin ve adını verin
interop_helpers.h. - öğesinin içeriğini
interop_helpers.hyukarıdaki kod listesiyle değiştirin. - Bu include'ları
pch.höğesine ekleyin.
// pch.h
...
#include <unknwn.h>
// Include C++/WinRT projected Windows API headers here.
...
#include <interop_helpers.h>
Bir C++/CX projesini alıp buna C++/WinRT desteği ekleme
Bu bölümde, mevcut C++/CX projenizi almaya, C++/WinRT desteği eklemeye ve taşıma işinizi orada yapmaya karar verirseniz ne yapmanız gerekir açıklanmaktadır. Ayrıca bkz. C++/WinRT için Visual Studio desteği.
C++/CX projesinde C++/CX ve C++/WinRT'yi (projedeki from_cx ve to_cx yardımcı işlevlerini kullanma dahil) birlikte kullanmak için projeye el ile C++/WinRT desteği eklemeniz gerekir.
İlk olarak, C++/CX projenizi Visual Studio açın ve Genel>Hedef Platform Sürümü proje özelliğinin 10.0.17134.0 (Windows 10, sürüm 1803) veya üzeri olarak ayarlandığını onaylayın.
C++/WinRT NuGet paketini yükleme
Microsoft.Windows. CppWinRT NuGet paketi C++/WinRT derleme desteği (MSBuild özellikleri ve hedefleri) sağlar. Yüklemek için Project>Manage NuGet Packages...>Gözat menü öğesine tıklayın, arama kutusuna Microsoft.Windows.CppWinRT yazın veya yapıştırın, arama sonuçlarında öğeyi seçin ve ardından o proje için paketi yüklemek üzere Yükle'ye tıklayın.
Önemli
C++/WinRT NuGet paketinin yüklenmesi, projede C++/CX desteğinin kapatılmasına neden olur. Eğer taşımayı tek seferde yapacaksanız, derleme iletilerinin C++/CX’e olan tüm bağımlılıklarınızı bulmanıza (ve taşımanıza) yardımcı olması için bu desteği kapalı bırakmak iyi bir fikirdir (böylece başlangıçta tamamen C++/CX olan bir projeyi zamanla tamamen C++/WinRT projesine dönüştürmüş olursunuz). Ancak yeniden açma hakkında bilgi için sonraki bölüme bakın.
C++/CX desteğini yeniden açın
Eğer tek seferde taşıma yapıyorsanız, bunu yapmanıza gerek yoktur. Ancak aşamalı olarak taşımanız gerekiyorsa, bu noktada projenizde C++/CX desteğini yeniden açmanız gerekir. Proje özelliklerinde C/C++>Genel>Windows Çalışma Zamanı Uzantısı Kullan>Evet (/ZW)).
Alternatif olarak (veya bir XAML projesi için ek olarak), Visual Studio C++/WinRT proje özellik sayfasını kullanarak C++/CX desteği ekleyebilirsiniz. project özelliklerinde Ortak Özellikler>C++/WinRT>Project Dili>C++/CX. Bunu yaptığınızda dosyanıza .vcxproj aşağıdaki özellik eklenir.
<PropertyGroup Label="Globals">
<CppWinRTProjectLanguage>C++/CX</CppWinRTProjectLanguage>
</PropertyGroup>
Önemli
Midl File (.idl) içeriğini saplama dosyalarına işlemek üzere derleme yapmanız gerektiğinde, Project Language ayarını yeniden C++/WinRT olarak değiştirmeniz gerekir. Derleme bu taslakları oluşturduktan sonra Proje Dili seçeneğini yeniden C++/CX olarak değiştirin.
Benzer özelleştirme seçeneklerinin (cppwinrt.exe aracının davranışına ince ayar yapan seçenekler) listesi için Microsoft.Windows.CppWinRT NuGet paketinin readme dosyasına bakın.
C++/WinRT üst bilgi dosyalarını ekle
Yapmanız gereken en az şey, önceden derlenmiş başlık dosyanıza (genellikle pch.h) aşağıda gösterildiği gibi winrt/base.h eklemektir.
// pch.h
...
#include <winrt/base.h>
...
Ancak winrt::Windows::Foundation ad alanında türlerine neredeyse kesinlikle ihtiyacınız olacaktır. Ayrıca ihtiyacınız olacak diğer ad alanlarını zaten biliyor olabilirsiniz. Bu yüzden, bu ad alanlarına karşılık gelen C++/WinRT tarafından projekte edilen Windows API başlıklarını şu şekilde ekleyin (artık winrt/base.h öğesini açıkça dahil etmeniz gerekmez; sizin için otomatik olarak dahil edilir).
// pch.h
...
#include <winrt/Windows.Foundation.h>
// Include any other C++/WinRT projected Windows API headers here.
...
Ayrıca, namespace cx ve namespace winrt ad alanı takma adlarını kullanan bir teknik için aşağıdaki bölümdeki kod örneğine de bakın (Bir C++/WinRT projesini alıp C++/CX desteği ekleme). Bu teknik, C++/WinRT projeksiyonu ile C++/CX projeksiyonu arasındaki olası ad alanı çakışmalarıyla başa çıkmanızı sağlar.
Projeye ekle interop_helpers.h
Artık C++/CX projenize from_cx ve to_cx işlevlerini ekleyebilirsiniz. Bunu yapma yönergeleri için yukarıdaki from_cx ve to_cx işlevleri bölümüne bakın.
Bir C++/WinRT projesine C++/CX desteği ekleme
Bu bölümde, yeni bir C++/WinRT projesi oluşturmaya karar verirseniz ve taşıma işinizi orada yapmaya karar verdiyseniz ne yapmanız gerekir açıklanmaktadır.
C++/WinRT projesinde C++/WinRT ve C++/CX'i (projedeki from_cx ve to_cx yardımcı işlevlerini kullanma dahil) birlikte kullanmak için projeye C++/CX desteğini el ile eklemeniz gerekir.
- C++/WinRT proje şablonlarından birini kullanarak Visual Studio'de yeni bir C++/WinRT projesi oluşturun (bkz. C++/WinRT için Visual Studio destek).
- C++/CX için proje desteğini açın. Proje özelliklerinde C/C++>Genel>Windows Çalışma Zamanı Uzantısını Kullan>Evet (/ZW).
Kullanımda olan iki yardımcı işlevi gösteren örnek C++/WinRT projesi
Bu bölümde, from_cx veto_cx kullanmayı gösteren örnek bir C++/WinRT projesi oluşturabilirsiniz. Ayrıca, C++/WinRT projeksiyonu ile C++/CX projeksiyonu arasında aksi takdirde ortaya çıkabilecek ad alanı çakışmalarını ele almak için, ayrı kod adalarında ad alanı takma adlarını nasıl kullanabileceğinizi de gösterir.
- Visual C++>Windows Universal>Core Uygulaması (C++/WinRT) projesi oluşturun.
- Proje özelliklerinde C/C++>General>Windows Çalışma Zamanı Uzantılarını Kullan>Evet (/ZW).
- Projeye ekleyin
interop_helpers.h. Bunu yapma yönergeleri için yukarıdaki from_cx ve to_cx işlevleri bölümüne bakın. -
App.cppiçeriğini aşağıdaki kod listesiyle değiştirin. - Derle ve çalıştır.
WINRT_ASSERT bir makro tanımıdır ve _ASSERTE genişletilir.
// 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>());
}
Önemli API'ler
İlgili konular
Windows developer