no message
parent
6798243ceb
commit
aafe88ac8b
|
@ -8,6 +8,16 @@
|
||||||
#include <qsysinfo.h>
|
#include <qsysinfo.h>
|
||||||
#include <qt_windows.h>
|
#include <qt_windows.h>
|
||||||
#include "media/screen_capture.h"
|
#include "media/screen_capture.h"
|
||||||
|
#include "media/DXGICapture.h"
|
||||||
|
#include <QVector>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <tchar.h>
|
||||||
|
#include <shlobj.h>
|
||||||
|
#include <D3D9.h>
|
||||||
|
|
||||||
|
#if _MSC_VER >= 1600
|
||||||
|
#pragma execution_character_set("utf-8")
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __MINGW32__
|
#ifdef __MINGW32__
|
||||||
#include <Tlhelp32.h>
|
#include <Tlhelp32.h>
|
||||||
|
@ -18,15 +28,239 @@ int RegiesterOwnType(){
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IDirect3DDevice9* g_pd3dDevice = nullptr;
|
||||||
|
|
||||||
|
// 全???======================================================
|
||||||
|
|
||||||
|
// 建立D3DDevice
|
||||||
|
|
||||||
|
LPDIRECT3D9 g_pD3D = nullptr; // Used to create the D3DDevice
|
||||||
|
|
||||||
|
// (我?的?)render?置,用??生最後影像的?置
|
||||||
|
|
||||||
|
|
||||||
|
// =============================================================
|
||||||
|
HRESULT ScreenGrab(LPDIRECT3DDEVICE9 pDev)
|
||||||
|
|
||||||
|
{
|
||||||
|
HRESULT hr;
|
||||||
|
D3DDISPLAYMODE mode;
|
||||||
|
if (FAILED(hr=pDev->GetDisplayMode(0, &mode))) //第一???是Swap Chain,跟?重???有防止破碎
|
||||||
|
return hr;
|
||||||
|
|
||||||
|
IDirect3DSurface9* pSurface;
|
||||||
|
|
||||||
|
if (FAILED(hr=pDev->CreateOffscreenPlainSurface(mode.Width,mode.Height,
|
||||||
|
D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &pSurface, NULL)))
|
||||||
|
return hr;
|
||||||
|
|
||||||
|
|
||||||
|
if (FAILED(hr=pDev->GetFrontBufferData(0,pSurface))) {
|
||||||
|
pSurface->Release();
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
D3DLOCKED_RECT lockedRect;
|
||||||
|
if(FAILED(pSurface->LockRect(&lockedRect,NULL,D3DLOCK_NO_DIRTY_UPDATE|D3DLOCK_NOSYSLOCK|D3DLOCK_READONLY)))
|
||||||
|
{
|
||||||
|
printf("Unable to Lock Front Buffer Surface");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
BYTE* pBits = new BYTE[2960*1440*3];
|
||||||
|
for(int i=0;i<mode.Height;i++)
|
||||||
|
{
|
||||||
|
memcpy((BYTE*)pBits+(mode.Height-i-1)*mode.Width*3/8,(BYTE*)lockedRect.pBits+i*lockedRect.Pitch,
|
||||||
|
mode.Width*3/8);//g_d3dpp.BackBufferHeight*g_d3dpp.BackBufferWidth*4);
|
||||||
|
|
||||||
|
}
|
||||||
|
pSurface->UnlockRect();
|
||||||
|
|
||||||
|
SetCursor(LoadCursor(NULL,IDC_ARROW));
|
||||||
|
|
||||||
|
// release the image surface
|
||||||
|
|
||||||
|
// ?放影像表面
|
||||||
|
|
||||||
|
pSurface->Release();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// return status of save operation to caller
|
||||||
|
|
||||||
|
// 回?Handler
|
||||||
|
|
||||||
|
return hr;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
QVector<tagDublicatorMonitorInfo> GetMonitors()
|
||||||
|
{
|
||||||
|
QVector<tagDublicatorMonitorInfo> ret;
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
CDXGICapture dxgiCapture;
|
||||||
|
hr = dxgiCapture.Initialize();
|
||||||
|
if (FAILED(hr)) {
|
||||||
|
printf("Error[0x%08X]: CDXGICapture::Initialize failed.\n", hr);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int nMonitorCount = dxgiCapture.GetDublicatorMonitorInfoCount();
|
||||||
|
printf("{\n");
|
||||||
|
if (nMonitorCount > 0) {
|
||||||
|
printf(" \"count\" : %u,\n", nMonitorCount);
|
||||||
|
printf(" \"monitors\" : [\n");
|
||||||
|
for (int i = 0; i < nMonitorCount; ++i) {
|
||||||
|
const tagDublicatorMonitorInfo *pInfo = dxgiCapture.GetDublicatorMonitorInfo(i);
|
||||||
|
if (nullptr != pInfo) {
|
||||||
|
printf(" {\n");
|
||||||
|
printf(" \"idx\" : %u,\n", pInfo->Idx);
|
||||||
|
printf(" \"name\" : \"%S\",\n", pInfo->DisplayName);
|
||||||
|
printf(" \"x\" : %d,\n", pInfo->Bounds.X);
|
||||||
|
printf(" \"y\" : %d,\n", pInfo->Bounds.Y);
|
||||||
|
printf(" \"width\" : %d,\n", pInfo->Bounds.Width);
|
||||||
|
printf(" \"height\" : %d,\n", pInfo->Bounds.Height);
|
||||||
|
printf(" \"rotation\" : %d\n", pInfo->RotationDegrees);
|
||||||
|
if (i < (nMonitorCount - 1)) {
|
||||||
|
printf(" },\n");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
printf(" }\n");
|
||||||
|
}
|
||||||
|
ret.push_back(*pInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf(" ]\n");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
printf(" \"count\" : %u\n", nMonitorCount);
|
||||||
|
}
|
||||||
|
printf("}\n");
|
||||||
|
|
||||||
|
dxgiCapture.Terminate();
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT InitD3D( HWND hWnd )
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
// Create the D3D object, which is needed to create the D3DDevice.
|
||||||
|
|
||||||
|
// D3DDevice所需要的D3D物件,Direct3DCreate9回?D3DDevice,?入值?使用者安?DirectX的版本
|
||||||
|
|
||||||
|
if( NULL == ( g_pD3D = Direct3DCreate9( D3D_SDK_VERSION ) ) )
|
||||||
|
|
||||||
|
return E_FAIL;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Set up the structure used to create the D3DDevice. Most parameters are
|
||||||
|
|
||||||
|
// zeroed out. We set Windowed to TRUE, since we want to do D3D in a
|
||||||
|
|
||||||
|
// window, and then set the SwapEffect to "discard", which is the most
|
||||||
|
|
||||||
|
// efficient method of presenting the back buffer to the display. And
|
||||||
|
|
||||||
|
// we request a back buffer format that matches the current desktop display
|
||||||
|
|
||||||
|
// format.
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
用?建立D3DDevice的??。大多????0。
|
||||||
|
|
||||||
|
?定是否?"?窗化"?真,就是?示??窗化。
|
||||||
|
|
||||||
|
如果?D3D於?窗?行,?SwapEffect定"discard",??在後端??呈???最有效率。
|
||||||
|
|
||||||
|
?且我?要求後端??的?示格式??在的?面相符。
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
D3DPRESENT_PARAMETERS d3dpp;
|
||||||
|
|
||||||
|
ZeroMemory( &d3dpp, sizeof( d3dpp ) ); //初始化d3d的??
|
||||||
|
|
||||||
|
d3dpp.Windowed = TRUE; //?定?窗化
|
||||||
|
|
||||||
|
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; //提高效率
|
||||||
|
|
||||||
|
d3dpp.BackBufferFormat = D3DFMT_UNKNOWN; //??有呈??面相符格式(竟然是?定未知= =)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Create the Direct3D device. Here we are using the default adapter (most
|
||||||
|
|
||||||
|
// systems only have one, unless they have multiple graphics hardware cards
|
||||||
|
|
||||||
|
// installed) and requesting the HAL (which is saying we want the hardware
|
||||||
|
|
||||||
|
// device rather than a software one). Software vertex processing is
|
||||||
|
|
||||||
|
// specified since we know it will work on all cards. On cards that support
|
||||||
|
|
||||||
|
// hardware vertex processing, though, we would see a big performance gain
|
||||||
|
|
||||||
|
// by specifying hardware vertex processing.
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
建立Direct3D?置。我?使用??的adapter(?似?置的意思= =)。
|
||||||
|
|
||||||
|
?大多?的使用者??只有一??置(?示卡),除非他?有其多的?示卡。
|
||||||
|
|
||||||
|
?且要求HAL,也就是?先用?示卡?示,而不是用???理。
|
||||||
|
|
||||||
|
既然我?知道????(角)?理的?理方式被定?所有?示卡。
|
||||||
|
|
||||||
|
於支援硬????理的?示卡上,我??看到?佳的?行效率。
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
if( FAILED( g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, //??adapter
|
||||||
|
|
||||||
|
D3DDEVTYPE_HAL, //硬?加速
|
||||||
|
|
||||||
|
hWnd, //Handler名?
|
||||||
|
|
||||||
|
//D3DCREATE_SOFTWARE_VERTEXPROCESSING, //最後竟然用???
|
||||||
|
|
||||||
|
D3DCREATE_HARDWARE_VERTEXPROCESSING, //改用硬?加速吧
|
||||||
|
|
||||||
|
&d3dpp, //D3D??
|
||||||
|
|
||||||
|
&g_pd3dDevice //D3D最後?示?置??
|
||||||
|
|
||||||
|
) ) )
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
return E_FAIL;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Device state would normally be set here
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
ScreenCapture g;
|
setbuf(stdout, NULL);//让printf立即输出
|
||||||
g.EnumScreen();
|
|
||||||
|
|
||||||
QssEventFilter filter;
|
QssEventFilter filter;
|
||||||
QApplication app(argc, argv);
|
QApplication app(argc, argv);
|
||||||
|
|
||||||
|
|
||||||
MainWindow main;
|
MainWindow main;
|
||||||
|
InitD3D((HWND)main.winId());
|
||||||
|
ScreenGrab( g_pd3dDevice);
|
||||||
main.setWindowTitle("직첵竟꿎桿묏야");
|
main.setWindowTitle("직첵竟꿎桿묏야");
|
||||||
main.setFixedSize(1920,1080);
|
main.setFixedSize(1920,1080);
|
||||||
main.show();
|
main.show();
|
||||||
|
|
|
@ -657,7 +657,8 @@ HRESULT CDXGICapture::CaptureToFile(_In_ LPCWSTR lpcwOutputFileName, _Out_opt_ B
|
||||||
m_ipD2D1RenderTarget->BeginDraw();
|
m_ipD2D1RenderTarget->BeginDraw();
|
||||||
// clear background color
|
// clear background color
|
||||||
m_ipD2D1RenderTarget->Clear(D2D1::ColorF(D2D1::ColorF::Black, 1.0f));
|
m_ipD2D1RenderTarget->Clear(D2D1::ColorF(D2D1::ColorF::Black, 1.0f));
|
||||||
m_ipD2D1RenderTarget->DrawBitmap(ipD2D1SourceBitmap, rcTarget, 1.0f, D2D1_BITMAP_INTERPOLATION_MODE_LINEAR, rcSource);
|
m_ipD2D1RenderTarget->DrawBitmap(ipD2D1SourceBitmap, rcTarget, 1.0f,
|
||||||
|
D2D1_BITMAP_INTERPOLATION_MODE_LINEAR, rcSource);
|
||||||
// Reset transform
|
// Reset transform
|
||||||
//m_ipD2D1RenderTarget->SetTransform(D2D1::Matrix3x2F::Identity());
|
//m_ipD2D1RenderTarget->SetTransform(D2D1::Matrix3x2F::Identity());
|
||||||
// Logo draw sample
|
// Logo draw sample
|
||||||
|
@ -671,8 +672,8 @@ HRESULT CDXGICapture::CaptureToFile(_In_ LPCWSTR lpcwOutputFileName, _Out_opt_ B
|
||||||
if (nullptr != pRetRenderDuration) {
|
if (nullptr != pRetRenderDuration) {
|
||||||
*pRetRenderDuration = (UINT)((std::chrono::system_clock::now() - startTick).count() / 10000);
|
*pRetRenderDuration = (UINT)((std::chrono::system_clock::now() - startTick).count() / 10000);
|
||||||
}
|
}
|
||||||
|
hr = DXGICaptureHelper::SaveImageToFile(m_ipWICImageFactory,
|
||||||
hr = DXGICaptureHelper::SaveImageToFile(m_ipWICImageFactory, m_ipWICOutputBitmap, lpcwOutputFileName);
|
m_ipWICOutputBitmap, lpcwOutputFileName);
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,128 @@
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
|
||||||
|
#define WIDEN2(x) L ## x
|
||||||
|
#define WIDEN(x) WIDEN2(x)
|
||||||
|
#define __WFILE__ WIDEN(__FILE__)
|
||||||
|
#define HRCHECK(__expr) {hr=(__expr);if(FAILED(hr)){wprintf(L"FAILURE 0x%08X (%i)\n\tline: %u file: '%s'\n\texpr: '" WIDEN(#__expr) L"'\n",hr, hr, __LINE__,__WFILE__);goto cleanup;}}
|
||||||
|
#define RELEASE(__p) {if(__p!=nullptr){__p->Release();__p=nullptr;}}
|
||||||
|
|
||||||
|
// ȱenum·½·¨
|
||||||
|
// https://www.gamedev.net/forums/topic/132636-enum-displaymode--dx9--false/
|
||||||
|
|
||||||
|
HRESULT SavePixelsToFile32bppPBGRA(UINT width, UINT height, UINT stride, LPBYTE pixels, LPWSTR filePath, const GUID &format)
|
||||||
|
{
|
||||||
|
if (!filePath || !pixels)
|
||||||
|
return E_INVALIDARG;
|
||||||
|
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
IWICImagingFactory *factory = nullptr;
|
||||||
|
IWICBitmapEncoder *encoder = nullptr;
|
||||||
|
IWICBitmapFrameEncode *frame = nullptr;
|
||||||
|
IWICStream *stream = nullptr;
|
||||||
|
GUID pf = GUID_WICPixelFormat32bppPBGRA;
|
||||||
|
BOOL coInit = CoInitialize(nullptr);
|
||||||
|
|
||||||
|
HRCHECK(CoCreateInstance(CLSID_WICImagingFactory, nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&factory)));
|
||||||
|
HRCHECK(factory->CreateStream(&stream));
|
||||||
|
HRCHECK(stream->InitializeFromFilename(filePath, GENERIC_WRITE));
|
||||||
|
HRCHECK(factory->CreateEncoder(format, nullptr, &encoder));
|
||||||
|
HRCHECK(encoder->Initialize(stream, WICBitmapEncoderNoCache));
|
||||||
|
HRCHECK(encoder->CreateNewFrame(&frame, nullptr)); // we don't use options here
|
||||||
|
HRCHECK(frame->Initialize(nullptr)); // we dont' use any options here
|
||||||
|
HRCHECK(frame->SetSize(width, height));
|
||||||
|
HRCHECK(frame->SetPixelFormat(&pf));
|
||||||
|
HRCHECK(frame->WritePixels(height, stride, stride * height, pixels));
|
||||||
|
HRCHECK(frame->Commit());
|
||||||
|
HRCHECK(encoder->Commit());
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
RELEASE(stream);
|
||||||
|
RELEASE(frame);
|
||||||
|
RELEASE(encoder);
|
||||||
|
RELEASE(factory);
|
||||||
|
if (coInit) CoUninitialize();
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT Direct3D9TakeScreenshots(UINT adapter, UINT count)
|
||||||
|
{
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
IDirect3D9 *d3d = nullptr;
|
||||||
|
IDirect3DDevice9 *device = nullptr;
|
||||||
|
IDirect3DSurface9 *surface = nullptr;
|
||||||
|
D3DPRESENT_PARAMETERS parameters = { 0 };
|
||||||
|
D3DDISPLAYMODE mode;
|
||||||
|
D3DLOCKED_RECT rc;
|
||||||
|
UINT pitch;
|
||||||
|
SYSTEMTIME st;
|
||||||
|
LPBYTE *shots = nullptr;
|
||||||
|
|
||||||
|
// init D3D and get screen size
|
||||||
|
d3d = Direct3DCreate9(D3D_SDK_VERSION);
|
||||||
|
HRCHECK(d3d->GetAdapterDisplayMode(adapter, &mode));
|
||||||
|
|
||||||
|
parameters.Windowed = TRUE;
|
||||||
|
parameters.BackBufferCount = 1;
|
||||||
|
parameters.BackBufferHeight = mode.Height;
|
||||||
|
parameters.BackBufferWidth = mode.Width;
|
||||||
|
parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
|
||||||
|
parameters.hDeviceWindow = NULL;
|
||||||
|
|
||||||
|
// create device & capture surface
|
||||||
|
HRCHECK(d3d->CreateDevice(adapter, D3DDEVTYPE_HAL, NULL, D3DCREATE_SOFTWARE_VERTEXPROCESSING, ¶meters, &device));
|
||||||
|
HRCHECK(device->CreateOffscreenPlainSurface(mode.Width, mode.Height, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &surface, nullptr));
|
||||||
|
|
||||||
|
// compute the required buffer size
|
||||||
|
HRCHECK(surface->LockRect(&rc, NULL, 0));
|
||||||
|
pitch = rc.Pitch;
|
||||||
|
HRCHECK(surface->UnlockRect());
|
||||||
|
|
||||||
|
// allocate screenshots buffers
|
||||||
|
shots = new LPBYTE[count];
|
||||||
|
for (UINT i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
shots[i] = new BYTE[pitch * mode.Height];
|
||||||
|
}
|
||||||
|
|
||||||
|
GetSystemTime(&st); // measure the time we spend doing <count> captures
|
||||||
|
wprintf(L"%i:%i:%i.%i\n", st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
|
||||||
|
for (UINT i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
// get the data
|
||||||
|
HRCHECK(device->GetFrontBufferData(0, surface));
|
||||||
|
|
||||||
|
// copy it into our buffers
|
||||||
|
HRCHECK(surface->LockRect(&rc, NULL, 0));
|
||||||
|
CopyMemory(shots[i], rc.pBits, rc.Pitch * mode.Height);
|
||||||
|
HRCHECK(surface->UnlockRect());
|
||||||
|
}
|
||||||
|
GetSystemTime(&st);
|
||||||
|
wprintf(L"%i:%i:%i.%i\n", st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
|
||||||
|
|
||||||
|
// save all screenshots
|
||||||
|
for (UINT i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
WCHAR file[100];
|
||||||
|
wsprintf(file, L"cap%i.png", i);
|
||||||
|
HRCHECK(SavePixelsToFile32bppPBGRA(mode.Width, mode.Height, pitch, shots[i], file, GUID_ContainerFormatPng));
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
if (shots != nullptr)
|
||||||
|
{
|
||||||
|
for (UINT i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
delete shots[i];
|
||||||
|
}
|
||||||
|
delete[] shots;
|
||||||
|
}
|
||||||
|
RELEASE(surface);
|
||||||
|
RELEASE(device);
|
||||||
|
RELEASE(d3d);
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
ScreenCapture::ScreenCapture()
|
ScreenCapture::ScreenCapture()
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
#define SCREEN_CAPTURE
|
#define SCREEN_CAPTURE
|
||||||
|
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
|
#include <Wincodec.h> // we use WIC for saving images
|
||||||
|
#include <d3d9.h> // DirectX 9 header
|
||||||
|
|
||||||
class ScreenCapture
|
class ScreenCapture
|
||||||
{
|
{
|
||||||
|
|
|
@ -99,7 +99,7 @@ contains(DEFINES, __MINGW32__){
|
||||||
libavformat.a libavutil.a \
|
libavformat.a libavutil.a \
|
||||||
libswresample.a libswscale.a fdk-aac.lib ws2_32.lib libeay32.lib ssleay32.lib \
|
libswresample.a libswscale.a fdk-aac.lib ws2_32.lib libeay32.lib ssleay32.lib \
|
||||||
shell32.lib gdi32.lib crypt32.lib User32.lib GDI32.lib Advapi32.lib zlibstaticd.lib Secur32.lib \
|
shell32.lib gdi32.lib crypt32.lib User32.lib GDI32.lib Advapi32.lib zlibstaticd.lib Secur32.lib \
|
||||||
Bcrypt.lib Kernel32.lib portaudio_x86.lib ole32.lib oleaut32.lib strmiids.lib libx264.lib
|
Bcrypt.lib Kernel32.lib portaudio_x86.lib ole32.lib oleaut32.lib strmiids.lib libx264.lib d3d9.lib
|
||||||
|
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<!DOCTYPE QtCreatorProject>
|
<!DOCTYPE QtCreatorProject>
|
||||||
<!-- Written by QtCreator 4.11.0, 2021-10-04T20:14:49. -->
|
<!-- Written by QtCreator 4.11.0, 2021-10-05T02:07:58. -->
|
||||||
<qtcreator>
|
<qtcreator>
|
||||||
<data>
|
<data>
|
||||||
<variable>EnvironmentId</variable>
|
<variable>EnvironmentId</variable>
|
||||||
|
|
Loading…
Reference in New Issue