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 konuda, Windows Çalışma Zamanı C++ Template Library (WRL) kodunun C++/WinRT içindeki eşdeğerine nasıl taşınacağı gösterilmektedir.
C++/WinRT'ye taşımanın ilk adımı, projenize el ile C++/WinRT desteği eklemektir (bkz. C++/WinRT için Visual Studio destek). Bunu yapmak için Microsoft.Windows.CppWinRT NuGet paketini projenize yükleyin. Projeyi Visual Studio’da açın, Project>NuGet Paketlerini Yönet...>Gözat seçeneğine 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 paketi o proje için yüklemek üzere Yükle düğmesine tıklayın. Bu değişikliğin bir etkisi, projede C++/CX desteğinin kapatılmasıdır. Projede C++/CX kullanıyorsanız, desteği kapalı bırakabilir ve C++/CX kodunuzu da C++/WinRT olarak güncelleştirebilirsiniz (bkz. C++/CX'ten C++/WinRT'ye taşıma). Ya da desteği yeniden etkinleştirebilir (proje özelliklerinde C/C++>Genel>Windows Çalışma Zamanı Uzantısını Kullan>Evet (/ZW)) ve önce WRL kodunuzu geçirmeye odaklanabilirsiniz. C++/CX ve C++/WinRT kodu, XAML derleyici desteği ve Windows Çalışma Zamanı bileşenleri dışında aynı projede birlikte bulunabilir (bkz. C++/CX'ten C++/WinRT'ye taşıma).
GenelHedef Platform Sürümü> 10.0.17134.0 (Windows 10, sürüm 1803) veya üzeri olarak ayarlayın.
Önceden derlenmiş üst bilgi dosyanıza (genellikle pch.h) ekleyin winrt/base.h.
#include <winrt/base.h>
C++/WinRT tarafından projekte edilen herhangi bir Windows API üst bilgisini (örneğin winrt/Windows.Foundation.h) eklerseniz, winrt/base.h üst bilgisini şu şekilde açıkça eklemeniz gerekmez; çünkü sizin için otomatik olarak eklenir.
WRL COM akıllı işaretçilerini taşıma (Microsoft::WRL::ComPtr)
Microsoft::WRL::ComPtr<T> kullanan tüm kodları, winrt::com_ptr<T> kullanacak şekilde taşıyın. İşte bir öncesi ve sonrası kod örneği. after sürümünde, com_ptr::put üye işlevi, ayarlanabilmesi için temeldeki ham işaretçiyi elde eder.
ComPtr<IDXGIAdapter1> previousDefaultAdapter;
DX::ThrowIfFailed(m_dxgiFactory->EnumAdapters1(0, &previousDefaultAdapter));
winrt::com_ptr<IDXGIAdapter1> previousDefaultAdapter;
winrt::check_hresult(m_dxgiFactory->EnumAdapters1(0, previousDefaultAdapter.put()));
Önemli
Önceden oturmuş bir winrt::com_ptr varsa (iç ham işaretçisinin zaten bir hedefi var) ve bunu farklı bir nesneye işaret etmek için yeniden oturtmak istiyorsanız, önce aşağıdaki kod örneğinde gösterildiği gibi bu nesneye atamanız nullptr gerekir. Bunu yapmazsanız, daha önce atanmış bir com_ptr, iç işaretçisinin null olmadığını doğrulayarak sorunu dikkatinize çeker (com_ptr::put veya com_ptr::put_void çağrısı yaptığınızda).
winrt::com_ptr<IDXGISwapChain1> m_pDXGISwapChain1;
...
// We execute the code below each time the window size changes.
m_pDXGISwapChain1 = nullptr; // Important because we're about to re-seat
winrt::check_hresult(
m_pDxgiFactory->CreateSwapChainForHwnd(
m_pCommandQueue.get(), // For Direct3D 12, this is a pointer to a direct command queue, and not to the device.
m_hWnd,
&swapChainDesc,
nullptr,
nullptr,
m_pDXGISwapChain1.put())
);
Bu sonraki örnekte (after sürümünde), com_ptr::put_void üye işlevi, altta yatan ham işaretçiyi void işaretçisine işaret eden bir işaretçi olarak elde eder.
ComPtr<ID3D12Debug> debugController;
if (SUCCEEDED(D3D12GetDebugInterface(IID_PPV_ARGS(&debugController))))
{
debugController->EnableDebugLayer();
}
winrt::com_ptr<ID3D12Debug> debugController;
if (SUCCEEDED(D3D12GetDebugInterface(__uuidof(debugController), debugController.put_void())))
{
debugController->EnableDebugLayer();
}
ComPtr::Get öğesini com_ptr::get ile değiştirin.
m_d3dDevice->CreateDepthStencilView(m_depthStencil.Get(), &dsvDesc, m_dsvHeap->GetCPUDescriptorHandleForHeapStart());
m_d3dDevice->CreateDepthStencilView(m_depthStencil.get(), &dsvDesc, m_dsvHeap->GetCPUDescriptorHandleForHeapStart());
Altta yatan ham işaretçiyi IUnknown işaretçisi bekleyen bir işleve iletmek istediğinizde, aşağıdaki örnekte gösterildiği gibi winrt::get_unknown serbest işlevini kullanın.
ComPtr<IDXGISwapChain1> swapChain;
DX::ThrowIfFailed(
m_dxgiFactory->CreateSwapChainForCoreWindow(
m_commandQueue.Get(),
reinterpret_cast<IUnknown*>(m_window.Get()),
&swapChainDesc,
nullptr,
&swapChain
)
);
// Note: In a WinUI 3 desktop app, use CreateSwapChainForHwnd instead of
// CreateSwapChainForCoreWindow, since WinUI 3 doesn't use CoreWindow.
winrt::agile_ref<winrt::Windows::UI::Core::CoreWindow> m_window;
winrt::com_ptr<IDXGISwapChain1> swapChain;
winrt::check_hresult(
m_dxgiFactory->CreateSwapChainForCoreWindow(
m_commandQueue.get(),
winrt::get_unknown(m_window.get()),
&swapChainDesc,
nullptr,
swapChain.put()
)
);
WRL modülünü taşıma (Microsoft::WRL::Module)
Bu bölüm, Microsoft::WRL::Module türünü kullanan taşıma koduyla ilgilidir.
Bir bileşeni uygulamak için WRL kullanan mevcut bir projeye aşamalı olarak C++/WinRT kodu ekleyebilirsiniz ve mevcut WRL sınıflarınız desteklenmeye devam eder. Bu bölümde nasıl olduğu gösterilmektedir.
Visual Studio’da yeni bir Windows Çalışma Zamanı Bileşeni (C++/WinRT) proje türü oluşturur ve projeyi derlerseniz, Generated Files\module.g.cpp dosyası sizin için oluşturulur. Bu dosya, projenize kopyalayıp ekleyebileceğiniz iki yararlı C++/WinRT işlevinin (aşağıda listelenmiştir) tanımlarını içerir. Bu işlevler WINRT_CanUnloadNow ve WINRT_GetActivationFactory ve gördüğünüz gibi, hangi aşamada olursa olsun taşıma aşamasında sizi desteklemek için koşullu olarak WRL çağrısı yaparlar.
HRESULT WINRT_CALL WINRT_CanUnloadNow()
{
#ifdef _WRL_MODULE_H_
if (!::Microsoft::WRL::Module<::Microsoft::WRL::InProc>::GetModule().Terminate())
{
return S_FALSE;
}
#endif
if (winrt::get_module_lock())
{
return S_FALSE;
}
winrt::clear_factory_cache();
return S_OK;
}
HRESULT WINRT_CALL WINRT_GetActivationFactory(HSTRING classId, void** factory)
{
try
{
*factory = nullptr;
wchar_t const* const name = WINRT_WindowsGetStringRawBuffer(classId, nullptr);
if (0 == wcscmp(name, L"MoveFromWRLTest.Class"))
{
*factory = winrt::detach_abi(winrt::make<winrt::MoveFromWRLTest::factory_implementation::Class>());
return S_OK;
}
#ifdef _WRL_MODULE_H_
return ::Microsoft::WRL::Module<::Microsoft::WRL::InProc>::GetModule().GetActivationFactory(classId, reinterpret_cast<::IActivationFactory**>(factory));
#else
return winrt::hresult_class_not_available().to_abi();
#endif
}
catch (...) { return winrt::to_hresult(); }
}
Projenizde bu işlevlere sahip olduktan sonra Module ::GetActivationFactory'yi doğrudan çağırmak yerine WINRT_GetActivationFactory çağırın (wrl işlevini dahili olarak çağırır). İşte bir öncesi ve sonrası kod örneği.
HRESULT WINAPI DllGetActivationFactory(_In_ HSTRING activatableClassId, _Out_ ::IActivationFactory **factory)
{
auto & module = Microsoft::WRL::Module<Microsoft::WRL::InProc>::GetModule();
return module.GetActivationFactory(activatableClassId, factory);
}
HRESULT __stdcall WINRT_GetActivationFactory(HSTRING activatableClassId, void** factory);
HRESULT WINAPI DllGetActivationFactory(_In_ HSTRING activatableClassId, _Out_ ::IActivationFactory **factory)
{
return WINRT_GetActivationFactory(activatableClassId, reinterpret_cast<void**>(factory));
}
Module::Terminate öğesini doğrudan çağırmak yerine WINRT_CanUnloadNow (WRL işlevini dahili olarak çağırır) çağırın. İşte bir öncesi ve sonrası kod örneği.
HRESULT __stdcall DllCanUnloadNow(void)
{
auto &module = Microsoft::WRL::Module<Microsoft::WRL::InProc>::GetModule();
HRESULT hr = (module.Terminate() ? S_OK : S_FALSE);
if (hr == S_OK)
{
hr = ...
}
return hr;
}
HRESULT __stdcall WINRT_CanUnloadNow();
HRESULT __stdcall DllCanUnloadNow(void)
{
HRESULT hr = WINRT_CanUnloadNow();
if (hr == S_OK)
{
hr = ...
}
return hr;
}
Microsoft::WRL::Wrappers sarmalayıcılarının taşınması
Bu bölüm, Microsoft::WRL::Wrappers sarmalayıcılarını kullanan taşıma koduyla ilgilidir.
Aşağıdaki tabloda görebileceğiniz gibi, iş parçacığı yardımcılarını değiştirmek için Standart C++ iş parçacığı destek kitaplığını kullanmanızı öneririz. Seçiminiz gereksinimlerinize bağlı olduğundan WRL sarmalayıcılarından bire bir eşleme yanıltıcı olabilir. Ayrıca, belirgin eşlemeler gibi görünebilecek bazı türler C++20 standardına yeni eklenmiştir, bu nedenle henüz yükseltmediyseniz bunlar pratik olmayacaktır.
| Type | Notları taşıma |
|---|---|
| CriticalSection sınıfı | İş parçacığı destek kitaplığını kullanma |
| Olay sınıfı (WRL) | winrt::event yapısı şablonunu kullanma |
| HandleT sınıfı | winrt::handle yapısını veya winrt::file_handle yapısını kullanın |
| HString sınıfı | winrt::hstring yapısını kullanma |
| HStringReference sınıfı | Yerine başka bir şey kullanmaya gerek yok; çünkü C++/WinRT bunu, HStringReference kadar verimli olacak şekilde dahili olarak ele alır ve bunun avantajı, sizin bunu düşünmek zorunda olmamanızdır. |
| Mutex sınıfı | İş parçacığı destek kitaplığını kullanma |
| RoInitializeWrapper sınıfı | winrt::init_apartment ve winrt::uninit_apartment kullanın; ya da CoInitializeEx ve CoUninitialize için kendi basit sarmalayıcınızı yazın. |
| Semaphore sınıfı | İş parçacığı destek kitaplığını kullanma |
| SRWLock sınıfı | İş parçacığı destek kitaplığını kullanma |
Önemli API'ler
İlgili konular
Windows developer