/* winDesktopApp.cpp : Defines the entry point for the application. */ #include "framework.h" #include "winDesktopApp.h" #pragma once /* folder - DirectX_Tutorial */ #define DX11 // using directx 11 /* define the screen resolution */ #define SCREEN_WIDTH 800 #define SCREEN_HEIGHT 400 #include #pragma comment(lib, "User32.lib") #include #ifndef UNICODE #define UNICODE #define SetWindowText SetWindowTextW #define _tcslen wcslen #else #define SetWindowText SetWindowTextA #define _tcslen strlen #endif #include #include #include //#include #include #include #pragma comment (lib, "d3d11.lib") #include #pragma comment (lib, "d3d10_1.lib") #pragma region D3DX Notes /* The D3DX (D3DX 9, D3DX 10, and D3DX 11) utility library is deprecated for Windows 8, and is not supported for Microsoft Store apps For Direct3D 11 users, the recommendation is to switch from D3DX11 to one of many open-source replacements to remove the need for this legacy NuGet package. For more information, see Living without D3DX Use Package Manager NuGet\Install-Package Microsoft.DXSDK.D3DX -Version 9.29.952.8 */ #pragma endregion /* includes extensions to Direct3D */ //#include /* include the Direct3D Library file */ //#pragma comment (lib, "d3dx11.lib") #include #pragma comment (lib, "D2d1") #include #include #include //#include #include #pragma comment(lib, "dcomp.lib") #include #pragma comment(lib, "d3dcompiler.lib") using namespace std; using namespace D2D1; ID3D10Device* m_pD3D10Device = nullptr; ID2D1BitmapBrush* m_pBitmapBrush; //ID2D1DeviceContext* d2dDC; //ID3D11Device* m_pD3D11Device; D3D_FEATURE_LEVEL featureLevelSupported; IDXGIDevice* pDXGIDevice = nullptr; IDCompositionDevice* m_pDCompDevice; IDCompositionTarget* m_pDCompTarget; IDCompositionVisual* pVisual = nullptr; IDCompositionSurface* pSurface = nullptr; HBITMAP m_hBitmap; ID2D1Factory1* m_pD2DFactory1 = nullptr; ID3D11Device* m_pD3D11Device = nullptr; ID3D11DeviceContext* m_pD3D11DeviceContext = NULL; IDXGIDevice1* m_pDXGIDevice = nullptr; ID2D1Device* m_pD2DDevice = nullptr; ID2D1DeviceContext3* m_pD2DDeviceContext3 = NULL; IDXGISwapChain1* m_pDXGISwapChain1 = nullptr; ID2D1Bitmap1* m_pD2DTargetBitmap = nullptr; ID2D1SolidColorBrush* m_pD2DBrushBlack = nullptr; ID2D1SolidColorBrush* m_pD2DBrushWhite = nullptr; ID2D1SolidColorBrush* m_pD2DBrushBlue = nullptr; ID2D1SolidColorBrush* m_pD2DBrushGreen = nullptr; IDCompositionDevice* m_pDCompositionDevice = nullptr; IDCompositionTarget* m_pDCompositionTarget = nullptr; HWND winHandle, activeHandle; HINSTANCE hInst; // current instance HRESULT hr, hr1, hr2, hr3, hr4, hr5, hr6; UINT nPlanes = 1, nBitCount = 1; int nWidth = SCREEN_WIDTH, nHeight = SCREEN_HEIGHT, bmp = 0; int nX = (GetSystemMetrics(SM_CXSCREEN) - nWidth) / 2, nY = (GetSystemMetrics(SM_CYSCREEN) - nHeight) / 2; /* rectangle edge */ int rectL, rectR, rectT, rectB; int bitmapSize = 0; int deviceFlag[22] = { DRIVERVERSION, HORZSIZE, VERTSIZE, HORZRES, VERTRES, BITSPIXEL, PLANES, NUMBRUSHES, NUMPENS, NUMFONTS, NUMCOLORS, CLIPCAPS, SIZEPALETTE, COLORRES, VREFRESH, SHADEBLENDCAPS, RASTERCAPS, CURVECAPS, LINECAPS, POLYGONALCAPS, TEXTCAPS, COLORMGMTCAPS }; int numFlags = sizeof(deviceFlag) / sizeof(int); /* HPEN */ int penStyle[] = { PS_SOLID, PS_DASH, PS_DOT, PS_DASHDOT, PS_DASHDOTDOT, PS_NULL, PS_INSIDEFRAME }; HGDIOBJ originalPen = nullptr; HPEN hPen; HBRUSH hBrush; HRGN hRegion; /* if nWidth is zero, the pen is a single pixel wide */ int pointSize = 0, colR, colG, colB; COLORREF paintCol; bool fail, fileOpened, imgCapture, usingDx10, dcdCreate = false; FLOAT dpiX, dpiY; ID2D1ColorContext* colContext; D2D1_BITMAP_PROPERTIES bmpProps; ID2D1HwndRenderTarget* m_pRenderTarget; D2D1_PIXEL_FORMAT pixelFormat; D2D1_SIZE_U d2dSize; float xOffset = 20; // horizonal position of visual float yOffset = 20; // vertical position of visual string deviceInfoStr[22]{ "The device driver version", "Width, in millimeters, of the physical screen", "Height, in millimeters, of the physical screen", "Width, in pixels, of the screen; or for printers", "Height, in raster lines, of the screen; or for printers", "Number of adjacent color bits for each pixel", "Number of color planes", "Number of device-specific brushes", "Number of device-specific pens", "Number of device-specific fonts", "Number of entries in the device's color table", "clipping capabilities of the device", "Number of entries in the system palette", "color resolution of the device, in bits per pixel", "current vertical refresh rate of device, in cycles per second", "shading and blending capabilities of the device", "raster capabilities of the device", "curve capabilities of the device", "line capabilities of the device", "polygon capabilities of the device", "text capabilities of the device", "color management capabilities of the device" }; string pathParts[6] = { "E:", "GameDevelopment", "GameProjects-Workshop", "VS_Projects", "OpenGL", "2023" }; string logFile, writeStr; fstream writefile; time_t secs; PCTSTR ptext, pcaption; UINT utype; RECT windRect = { nX, nY, nWidth, nHeight }, DesktopRect, defaultRect; RECT rcClient; // client area LONG initialWidth = windRect.right - windRect.left; LONG initialHeight = windRect.bottom - windRect.top; BITMAP bm; HBITMAP hbmOld, hbmMask, hbmColour; HDC hDc, screen, hdcMem, hdcMem1; HGDIOBJ gdiObj; UINT bmpBrushBits[8]; // bitmap bits ID2D1SolidColorBrush* m_pLightSlateGrayBrush; ID2D1SolidColorBrush* m_pYellowGreenBrush; ID2D1SolidColorBrush* m_pBlackBrush; D2D1_RECT_F rectWin; LONG gridB, gridL, gridR, gridT; POINT pnt; #pragma once #include "Prerequisites.h" void CleanDeviceResources(); void Clean(); template void SafeRelease(T** ppT) { if (*ppT) { (*ppT)->Release(); *ppT = NULL; } } static void exitStatus(const bool& fail) { /* The program failed (1)*/ if (fail) { exit(EXIT_FAILURE); } /* The program was successful (0)*/ else { exit(EXIT_SUCCESS); } } static void msgBox( HWND hWnd, PCTSTR pText, PCTSTR pCaption, UINT uType) { MessageBox(hWnd, pText, pCaption, uType); } /* capture an image of the entire desktop scale it down to the current window size save it to a file displaying in the client area */ int CaptureAnImage(HWND hWnd) { HDC hdcScreen, hdcWindow, hdcMemDC = NULL; HBITMAP hbmScreen = NULL; BITMAP bmpScreen; DWORD dwBytesWritten = 0, dwSizeofDIB = 0, dwBmpSize = 0; HANDLE hFile = NULL; char* lpbitmap = NULL; HANDLE hDIB = NULL; /* Retrieve the handle to a display device context for the client area of the window */ hdcScreen = GetDC(NULL); hdcWindow = GetDC(hWnd); /* Create a compatible DC, which is used in a BitBlt from the window DC */ hdcMemDC = CreateCompatibleDC(hdcWindow); if (!hdcMemDC) { ptext = L"CreateCompatibleDC has failed"; msgBox(hWnd, ptext, pcaption, utype); DeleteObject(hbmScreen); DeleteObject(hdcMemDC); ReleaseDC(NULL, hdcScreen); ReleaseDC(hWnd, hdcWindow); fail = true; exitStatus(fail); } /* Get the client area for size calculation */ GetClientRect(hWnd, &rcClient); /* sets bitmap stretching mode in specified device context */ SetStretchBltMode(hdcWindow, HALFTONE); // best stretch mode #pragma region NOTE! /* HALFTONE - Maps pixels from the source rectangle into blocks of pixels in the destination rectangle. The average color over the destination block of pixels approximates the color of the source pixels. After setting the HALFTONE stretching mode, an application must call the SetBrushOrgEx function to set the brush origin. If it fails to do so, brush misalignment occurs. The HALFTONE mode is slower and requires more processing of the source image than the other three modes; but produces higher quality images. The brush origin is a pair of coordinates specifying the location of one pixel in the bitmap. The default brush origin coordinates are (0,0). For horizontal coordinates, the value 0 corresponds to the leftmost column of pixels; the width corresponds to the rightmost column. For vertical coordinates, the value 0 corresponds to the uppermost row of pixels; the height corresponds to the lowermost row. The system automatically tracks the origin of all window- managed device contexts and adjusts their brushes as necessary to maintain an alignment of patterns on the surface. The brush origin that is set with this call is relative to the upper-left corner of the client area. An application should call SetBrushOrgEx after setting the bitmap stretching mode to HALFTONE by using SetStretchBltMode. This must be done to avoid brush misalignment. The stretching mode defines how the system combines rows or columns of a bitmap with existing pixels on a display device when an application calls the StretchBlt function */ #pragma endregion if (!SetBrushOrgEx(hdcWindow, 0, 0, nullptr)) { ptext = L"Set brush origin failed"; msgBox(hWnd, ptext, pcaption, utype); } /* the source DC is the entire screen, and the destination DC is the current window(HWND) */ #pragma region NOTE /* The StretchBlt function copies a bitmap from a source rectangle into a destination rectangle, stretching or compressing the bitmap to fit the dimensions of the destination rectangle, if necessary. The system stretches or compresses the bitmap according to the stretching mode currently set in the destination device context */ #pragma endregion if (!StretchBlt( /* handle to the destination device context */ hdcWindow, /* xy-coordinates, in logical units, of the upper-left corner of the destination rectangle */ 0, 0, /* width & height, in logical units, of the destination rectangle */ rcClient.right, rcClient.bottom, /* handle to the source device context */ hdcScreen, /* xy-coordinates, in logical units, of the upper-left corner of the source rectangle */ 0, 0, /* width, in logical units, of the source rectangle */ GetSystemMetrics(SM_CXSCREEN), /* height, in logical units, of the source rectangle */ GetSystemMetrics(SM_CYSCREEN), /* raster operation to be performed. Raster operation codes define how the system combines colors in output operations that involve a brush, a source bitmap, and a destination bitmap */ SRCCOPY )) { ptext = L"StretchBlt has failed"; msgBox(hWnd, ptext, pcaption, utype); DeleteObject(hbmScreen); DeleteObject(hdcMemDC); ReleaseDC(NULL, hdcScreen); ReleaseDC(hWnd, hdcWindow); fail = true; exitStatus(fail); } /* Create a compatible bitmap from the Window DC */ hbmScreen = CreateCompatibleBitmap( hdcWindow, rcClient.right - rcClient.left, rcClient.bottom - rcClient.top ); if (!hbmScreen) { ptext = L"CreateCompatibleBitmap Failed"; msgBox(hWnd, ptext, pcaption, utype); imgCapture = false; fail = true; exitStatus(fail); } else { imgCapture = true; } /* Select the compatible bitmap into the compatible memory DC */ SelectObject(hdcMemDC, hbmScreen); /* Bit block transfer into our compatible memory DC */ if (!BitBlt( /* handle to the destination device context */ hdcMemDC, /* xy-coordinates, in logical units, of the upper-left corner of the destination rectangle */ 0, 0, /* width, in logical units, of the source and destination rectangles */ rcClient.right - rcClient.left, /* height, in logical units, of the source and destination rectangles */ rcClient.bottom - rcClient.top, /* handle to the source device context */ hdcWindow, /* xy-coordinates, in logical units, of the upper-left corner of the source rectangle */ 0, 0, /* A raster-operation code. These codes define how the color data for the source rectangle is to be combined with the color data for the destination rectangle to achieve the final color */ SRCCOPY )) { ptext = L"BitBlt has failed"; msgBox(hWnd, ptext, pcaption, utype); imgCapture = false; fail = true; exitStatus(fail); } else { imgCapture = true; } /* Get the BITMAP from the HBITMAP */ bitmapSize = GetObject(hbmScreen, sizeof(BITMAP), &bmpScreen); bitmapSize = GetObject(hbmScreen, sizeof(BITMAP), &bm); /* The BITMAPFILEHEADER structure contains information about the type, size, and layout of a file that contains a DIB */ BITMAPFILEHEADER bmpFh; /* The BITMAPINFOHEADER structure contains information about the dimensions and color format of a device-independent bitmap (DIB) */ BITMAPINFOHEADER bmpIh; bmpIh.biSize = sizeof(BITMAPINFOHEADER); bmpIh.biWidth = bmpScreen.bmWidth; bmpIh.biHeight = bmpScreen.bmHeight; bmpIh.biPlanes = 1; bmpIh.biBitCount = 32; bmpIh.biCompression = BI_RGB; bmpIh.biSizeImage = 0; bmpIh.biXPelsPerMeter = 0; bmpIh.biYPelsPerMeter = 0; bmpIh.biClrUsed = 0; bmpIh.biClrImportant = 0; dwBmpSize = ( (bmpScreen.bmWidth * bmpIh.biBitCount + 31) / 32 ) * 4 * bmpScreen.bmHeight; /* Starting with 32-bit Windows, GlobalAlloc and LocalAlloc are implemented as wrapper functions that call HeapAlloc using a handle to the process's default heap. Therefore, GlobalAlloc and LocalAlloc have greater overhead than HeapAlloc. */ hDIB = GlobalAlloc(GHND, dwBmpSize); lpbitmap = (char*)GlobalLock(hDIB); /* Gets the "bits" from the bitmap, and copies them into a buffer that's pointed to by lpbitmap */ #pragma region NOTE /* BitBlt returns an error if the source and destination device contexts represent different devices. To transfer data between DCs for different devices, convert the memory bitmap to a DIB by calling GetDIBits */ #pragma endregion GetDIBits( /* handle to the device context */ hdcWindow, /* handle to bitmap; must be a compatible bitmap (DDB) */ hbmScreen, /* first scan line to retrieve */ 0, /* number of scan lines to retrieve */ (UINT)bmpScreen.bmHeight, /* pointer to a buffer to receive the bitmap data */ lpbitmap, /* pointer to a BITMAPINFO structure which specifies the desired format for the DIB data */ (BITMAPINFO*)&bmpIh, /* format of bmiColors member of BITMAPINFO structure */ DIB_RGB_COLORS // color table consist of (RGB) values ); /* A file is created, this is where we will save the screen capture */ hFile = CreateFile( /* name of the file or device to be created or opened. uses either forward slashes (/) or backslashes (\) */ L"captureqwsx.bmp", /* requested access to the file or device, which can be summarized as read, write, both or 0 indicating neither most commonly used values - GENERIC_READ, GENERIC_WRITE, or both (GENERIC_READ | GENERIC_WRITE) */ GENERIC_WRITE, /* requested sharing mode of the file or device, which can be read, write, both, delete, all of these, or none If this parameter is zero and CreateFile succeeds, the file or device cannot be shared and cannot be opened again until the handle to the file or device is closed */ 0, /* pointer to a SECURITY_ATTRIBUTES structure */ NULL, /* an action to take on a file or device that exists or does not exist */ CREATE_ALWAYS, // Creates a new file, always /* file or device attributes and flags */ FILE_ATTRIBUTE_NORMAL, /* valid handle to a template file with the GENERIC_READ access right */ NULL ); /* Add the size of the headers to the size of the bitmap to get the total file size */ dwSizeofDIB = dwBmpSize + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER); /* Offset to where the actual bitmap bits start */ bmpFh.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + (DWORD)sizeof(BITMAPINFOHEADER); /* Size of the file */ bmpFh.bfSize = dwSizeofDIB; /* bfType must always be BM for Bitmaps */ bmpFh.bfType = 0x4D42; // BM. /* Writes data to specified file or input/output (I/O) device */ WriteFile( hFile, (PSTR)&bmpFh, //LPSTR sizeof(BITMAPFILEHEADER), &dwBytesWritten, NULL ); WriteFile( hFile, (PSTR)&bmpIh, //LPSTR sizeof(BITMAPINFOHEADER), &dwBytesWritten, NULL ); WriteFile( hFile, (PSTR)lpbitmap, //LPSTR dwBmpSize, &dwBytesWritten, NULL ); /* Unlock and Free the DIB from the heap */ GlobalUnlock(hDIB); GlobalFree(hDIB); /* Close the handle for the file that was created */ CloseHandle(hFile); return 0; } static void drawSomething(PAINTSTRUCT ps, HDC hdc) { /* rectangle dimensions */ rectB = defaultRect.bottom; rectL = defaultRect.left; rectR = defaultRect.right; rectT = defaultRect.top; /* store original pen color */ originalPen = SelectObject( ps.hdc, GetStockObject(DC_PEN)); /* choose a color */ colG = 200; paintCol = RGB(colR, colG, colB); /* Create a pen */ hPen = CreatePen(penStyle[0], pointSize, paintCol); /* Select the pen */ SelectObject(ps.hdc, hPen); /* Draw a rectangle */ Rectangle(ps.hdc, rectL + 100, rectT + 100, rectR - 100, rectB - 100); /* Delete object */ DeleteObject(hPen); /* Restore the original object */ SelectObject(ps.hdc, originalPen); } /*==========================================================*/ /* D2D Drawing */ /*==========================================================*/ static void d2dDrawingSetup() { /* Create an ID2D1Device and an ID2D1DeviceContext */ /* Obtain the underlying DXGI device of the Direct3D11 device */ hr = m_pD3D11Device->QueryInterface( (IDXGIDevice1**)&m_pDXGIDevice); if (SUCCEEDED(hr)) { /* Obtain the Direct2D device for 2-D rendering. */ hr = m_pD2DFactory1->CreateDevice( m_pDXGIDevice, &m_pD2DDevice); if (SUCCEEDED(hr)) { /* Get Direct2D device's corresponding device context object */ ID2D1DeviceContext* pD2DDeviceContext = NULL; /* Create device context from Direct2D device */ hr = m_pD2DDevice->CreateDeviceContext( D2D1_DEVICE_CONTEXT_OPTIONS_NONE, &pD2DDeviceContext); if (SUCCEEDED(hr)) { hr = pD2DDeviceContext->QueryInterface( (ID2D1DeviceContext3**)&m_pD2DDeviceContext3); /* A device context is a device that can perform drawing operations and create device-dependent drawing resources such as brushes. You also use the device context to link a ID2D1Bitmap to a DXGI surface to use as a render target. The device context can render to different types of targets */ } SafeRelease(&pD2DDeviceContext); } } } HRESULT Rendering() { HRESULT hr = S_OK; /* gray brush */ hr = m_pRenderTarget->CreateSolidColorBrush( D2D1::ColorF(D2D1::ColorF::LightSlateGray), &m_pLightSlateGrayBrush ); /* black brush */ hr = m_pRenderTarget->CreateSolidColorBrush( D2D1::ColorF(D2D1::ColorF::Black, 1.0f), &m_pBlackBrush ); /* solid color brush with its rgb value 0x9ACD32 */ hr = m_pRenderTarget->CreateSolidColorBrush( D2D1::ColorF(D2D1::ColorF(0x9ACD32, 1.0f)), &m_pYellowGreenBrush ); /* get size of render target in dots per inch (DPIs)*/ D2D1_SIZE_F rtSize = m_pRenderTarget->GetSize(); float sz = 0.0f; /* start drawing */ m_pRenderTarget->BeginDraw(); /* Draw a grid background */ int width = static_cast(rtSize.width); int height = static_cast(rtSize.height); for (int x = 0; x < width; x += 10) { m_pRenderTarget->DrawLine( D2D1::Point2F(static_cast(x), 0.0f), D2D1::Point2F( static_cast(x), rtSize.height), m_pLightSlateGrayBrush, 0.5f ); } for (int y = 0; y < height; y += 10) { m_pRenderTarget->DrawLine( D2D1::Point2F(0.0f, static_cast(y)), D2D1::Point2F( rtSize.width, static_cast(y)), m_pLightSlateGrayBrush, 0.5f ); } for (int i = 0; i < 2; i++) { if (i == 0) { sz = 50.0f; } else { sz = 100.0f; } rectWin = D2D1::RectF( rcClient.right / 2 - sz, rcClient.bottom / 2 - sz, rcClient.right / 2 + sz, rcClient.bottom / 2 + sz ); if (i == 0) { m_pRenderTarget->FillRectangle( &rectWin, m_pYellowGreenBrush); } else { m_pRenderTarget->DrawRectangle( &rectWin, m_pBlackBrush, 1, NULL); } } hr = m_pRenderTarget->EndDraw(); CleanDeviceResources(); return hr; } /*==========================================================*/ /* Direct Composition */ /*==========================================================*/ HRESULT createARenderTarget(const HWND& hwnd) { HRESULT hr = S_OK; /* Render Target */ D2D1_RENDER_TARGET_PROPERTIES props = D2D1::RenderTargetProperties(); props.pixelFormat = pixelFormat; /* Create a Direct2D render target */ hr = m_pD2DFactory1->CreateHwndRenderTarget( props, D2D1::HwndRenderTargetProperties(hwnd, d2dSize), &m_pRenderTarget ); return hr; } static void createPixelFormat(const HWND& hwnd) { GetClientRect(hwnd, &rcClient); d2dSize = D2D1::SizeU( rcClient.right - rcClient.left, rcClient.bottom - rcClient.top ); /* Create a pixel format and initial its format and alphaMode fields */ pixelFormat = D2D1::PixelFormat( DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_IGNORE ); /* */ D2D1_BITMAP_PROPERTIES bmpProps = D2D1::BitmapProperties(pixelFormat, 0, 0); } HRESULT CreateD2D1Factory(const HWND& hwnd) { HRESULT hr = S_OK; /* allows additional parameters for factory creation */ D2D1_FACTORY_OPTIONS options; ZeroMemory(&options, sizeof(D2D1_FACTORY_OPTIONS)); /* requests a certain level of debugging information from the debug layer */ options.debugLevel = D2D1_DEBUG_LEVEL::D2D1_DEBUG_LEVEL_INFORMATION; hr = D2D1CreateFactory( /* The threading model of the factory and the resources it creates */ D2D1_FACTORY_TYPE_SINGLE_THREADED, /* A reference to the IID of ID2D1Factory obtained by using __uuidof(ID2D1Factory) */ __uuidof(ID2D1Factory1), /* The level of detail provided to the debugging layer */ &options, /* When this method returns, contains the address to a pointer to the new factory */ (void**)&m_pD2DFactory1); if (SUCCEEDED(hr)) { /* create pixel format */ createPixelFormat(hwnd); /* create render target */ createARenderTarget(hwnd); d2dDrawingSetup(); } return hr; } HRESULT bindSurfaceToVisual(const HWND& hwnd) { /* set the bitmap content for the visual, and the horizontal and vertical position of the visual relative to upper-left corner of its container. Because it is the root visual, the container for this visual is the composition target window */ // Set the bitmap content of the visual. hr = pVisual->SetContent(pSurface); if (SUCCEEDED(hr)) { /* Set the horizontal and vertical position of the visual relative to the upper-left corner of the composition target window */ hr = pVisual->SetOffsetX(xOffset); if (SUCCEEDED(hr)) { hr = pVisual->SetOffsetY(yOffset); if (SUCCEEDED(hr)) { /* Step 8 */ /* Set visual to be the root of the visual tree */ hr = m_pDCompTarget->SetRoot(pVisual); if (SUCCEEDED(hr)) { /* Step 9 */ /* Commit the visual to be composed and displayed */ hr = m_pDCompDevice->Commit(); } } } } /* Step 10 */ /* Free the visual */ SafeRelease(&pVisual); /* Step 1 - D2D drawing initialization */ /* create d2d factory */ CreateD2D1Factory(hwnd); return hr; } /* Creates a DirectComposition surface and copies the bitmap to the surface Parameters: hBitmap - a GDI bitmap ppSurface - the composition surface object */ HRESULT createGDIRendDCompSurface( const HWND& hwnd, HBITMAP hBitmap, IDCompositionSurface** ppSurface) { HRESULT hr = S_OK; int bitmapWidth = 0; int bitmapHeight = 0; int bmpSize = 0; BITMAP bmp = { }; HBITMAP hBitmapOld = NULL; HDC hSurfaceDC = NULL; HDC hBitmapDC = NULL; IDXGISurface1* pDXGISurface = nullptr; IDCompositionSurface* pDCSurface = nullptr; POINT pointOffset = { }; if (ppSurface == nullptr) { return E_INVALIDARG; } hr = bitmapSize ? S_OK : E_FAIL; if (SUCCEEDED(hr)) { bmp = bm; // Save the bitmap dimensions. bitmapWidth = bmp.bmWidth; bitmapHeight = bmp.bmHeight; /* Create a DirectComposition-compatible surface that is the same size as the bitmap. The DXGI_FORMAT_B8G8R8A8_UNORM flag is required for rendering on the surface using GDI via GetDC */ hr = m_pDCompDevice->CreateSurface( bitmapWidth, bitmapHeight, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_ALPHA_MODE_IGNORE, &pDCSurface); if (SUCCEEDED(hr)) { // Begin rendering to the surface. hr = pDCSurface->BeginDraw( NULL, __uuidof(IDXGISurface1), reinterpret_cast(&pDXGISurface), &pointOffset); if (SUCCEEDED(hr)) { // Get the device context (DC) for the surface. hr = pDXGISurface->GetDC(FALSE, &hSurfaceDC); if (SUCCEEDED(hr)) { /* Create a compatible DC and select the surface into the DC */ hBitmapDC = CreateCompatibleDC(hSurfaceDC); if (hBitmapDC != NULL) { hBitmapOld = (HBITMAP)SelectObject( hBitmapDC, hBitmap); BitBlt( hSurfaceDC, pointOffset.x, pointOffset.y, bitmapWidth, bitmapHeight, hBitmapDC, 0, 0, SRCCOPY); if (hBitmapOld) { SelectObject( hBitmapDC, hBitmapOld); } DeleteDC(hBitmapDC); } pDXGISurface->ReleaseDC(NULL); } } // End the rendering. pDCSurface->EndDraw(); *ppSurface = pDCSurface; /* Call an application-defined macro to free the surface pointer */ //SafeRelease(&pDXGISurface); pDXGISurface->Release(); } } /* Step 7 - Bind surface to visual */ bindSurfaceToVisual(hwnd); return hr; } static void createDeviceObject(const HWND& hwnd) { /* Step 1 */ /* Create the D3D device object. The D3D11_CREATE_DEVICE_BGRA_SUPPORT flag enables rendering on surfaces using Direct2D. */ hr = D3D11CreateDevice( nullptr, D3D_DRIVER_TYPE_HARDWARE, NULL, D3D11_CREATE_DEVICE_BGRA_SUPPORT, NULL, 0, D3D11_SDK_VERSION, &m_pD3D11Device, &featureLevelSupported, nullptr); /* Check the result of calling D3D11CreateDriver */ if (SUCCEEDED(hr)) { /* Step 2 */ /* Create a DXGI device used to create bitmap surfaces */ hr = m_pD3D11Device->QueryInterface(&pDXGIDevice); if (SUCCEEDED(hr)) { /* Step 3 */ /* Create the DirectComposition device object */ hr = DCompositionCreateDevice(pDXGIDevice, __uuidof(IDCompositionDevice), reinterpret_cast(&m_pDCompDevice)); if (SUCCEEDED(hr)) { /* Step 4 */ /* Create the composition target object based on the specified application window */ hr = m_pDCompDevice->CreateTargetForHwnd( hwnd, TRUE, &m_pDCompTarget); if (SUCCEEDED(hr)) { /* Step 5 */ /* Create a visual object */ hr = m_pDCompDevice->CreateVisual(&pVisual); if (SUCCEEDED(hr)) { /* Step 6 */ /* Create a composition surface and render a GDI bitmap to the surface */ hr = createGDIRendDCompSurface( hwnd, m_hBitmap, &pSurface); } } } } } activeHandle = hwnd; } /*==========================================================*/ static void CleanDeviceResources() { SafeRelease(&m_pD2DBrushBlack); SafeRelease(&m_pD2DBrushWhite); SafeRelease(&m_pD2DBrushBlue); SafeRelease(&m_pD2DBrushGreen); SafeRelease(&m_pBlackBrush); SafeRelease(&m_pYellowGreenBrush); SafeRelease(&m_pLightSlateGrayBrush); } static void Clean() { DeleteObject(m_hBitmap); SafeRelease(&m_pRenderTarget); /* free the DXGI object, the device object, and composition target object before application exits */ SafeRelease(&pSurface); SafeRelease(&pDXGIDevice); SafeRelease(&m_pDCompDevice); SafeRelease(&m_pDCompTarget); //SafeRelease(&m_pD3D11Device); SafeRelease(&m_pD2DDevice); SafeRelease(&m_pD2DDeviceContext3); SafeRelease(&m_pD2DTargetBitmap); CleanDeviceResources(); SafeRelease(&m_pDXGISwapChain1); SafeRelease(&m_pDXGIDevice); SafeRelease(&m_pD3D11Device); SafeRelease(&m_pD3D11DeviceContext); SafeRelease(&m_pD2DFactory1); SafeRelease(&m_pDCompositionDevice); SafeRelease(&m_pDCompositionTarget); writefile.close(); } static void setup() { fail = fileOpened = imgCapture = false; screen = GetDC(0); dpiX = static_cast(GetDeviceCaps(screen, LOGPIXELSX)); dpiY = static_cast(GetDeviceCaps(screen, LOGPIXELSY)); ReleaseDC(0, screen); ptext = L"empty"; pcaption = L"Failed"; utype = MB_OK | MB_ICONEXCLAMATION; gridB = gridL = gridR = gridT = 0; usingDx10 = false; } #define MAX_LOADSTRING 100 // Global Variables: WCHAR szTitle[MAX_LOADSTRING]; // The title bar text WCHAR szWindowClass[MAX_LOADSTRING]; // main window class name // Forward declarations of functions included in this code module ATOM MyRegisterClass(HINSTANCE hInstance); BOOL InitInstance(HINSTANCE, int); LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM); int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPWSTR lpCmdLine, _In_ int nCmdShow) { UNREFERENCED_PARAMETER(hPrevInstance); UNREFERENCED_PARAMETER(lpCmdLine); // TODO: Place code here. setup(); // Initialize global strings LoadStringW( hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING); LoadStringW( hInstance, IDC_WINDESKTOPAPP, szWindowClass, MAX_LOADSTRING); MyRegisterClass(hInstance); // Perform application initialization: if (!InitInstance (hInstance, nCmdShow)) { return FALSE; } HACCEL hAccelTable = LoadAccelerators( hInstance, MAKEINTRESOURCE(IDC_WINDESKTOPAPP)); MSG msg; // Main message loop: while (GetMessage(&msg, nullptr, 0, 0)) { if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } } return (int) msg.wParam; } /* FUNCTION: MyRegisterClass() PURPOSE: Registers the window class. */ ATOM MyRegisterClass(HINSTANCE hInstance) { WNDCLASSEXW wcex; wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = WndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; wcex.hIcon = LoadIcon( hInstance, MAKEINTRESOURCE(IDI_WINDESKTOPAPP)); wcex.hCursor = LoadCursor(nullptr, IDC_ARROW); wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wcex.lpszMenuName = MAKEINTRESOURCEW(IDC_WINDESKTOPAPP); wcex.lpszClassName = szWindowClass; wcex.hIconSm = LoadIcon( wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL)); return RegisterClassExW(&wcex); } /* FUNCTION: InitInstance(HINSTANCE, int) PURPOSE: Saves instance handle and creates main window COMMENTS: In this function, we save the instance handle in a global variable and create and display the main program window */ BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) { // Store instance handle in a global variable hInst = hInstance; HWND hWnd = CreateWindowEx( WS_EX_NOREDIRECTIONBITMAP,//NULL,// szWindowClass, szTitle, WS_OVERLAPPEDWINDOW, nX, nY, //nWidth, nHeight, /* // use window's DPI to scale the window size */ static_cast(dpiX * (float)nWidth / 96.f), static_cast(dpiY * (float)nHeight / 96.f), //CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr); if (!hWnd) { return FALSE; } else { /* do something before showing window */ SendMessage(hWnd, WM_PAINT, NULL, NULL); ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); } return TRUE; } /* FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM) PURPOSE: Processes messages for the main window. WM_COMMAND - process the application menu WM_PAINT - Paint the main window WM_DESTROY - post a quit message and return */ LRESULT CALLBACK WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_CREATE: { /*creations(hWnd);*/ return 0; } break; case WM_LBUTTONDOWN: { if (!dcdCreate) { createDeviceObject(hWnd); dcdCreate = true; } } break; case WM_COMMAND: { int wmId = LOWORD(wParam); // Parse the menu selections: switch (wmId) { case IDM_ABOUT: { DialogBox( hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About); } break; case IDM_EXIT: { DestroyWindow(hWnd); } break; default: { return DefWindowProc( hWnd, message, wParam, lParam); } } } break; case WM_DISPLAYCHANGE: { InvalidateRect(hWnd, NULL, FALSE); } break; case WM_PAINT: { PAINTSTRUCT ps; HDC hdc = BeginPaint(hWnd, &ps); // TODO: Add any drawing code that uses hdc here /* Any drawing operation we perform on this HDC will immediately display on the screen */ /*FillRect( hdc, &ps.rcPaint, (HBRUSH)GetStockObject(BLACK_BRUSH));*/ /* store drawing area */ GetClientRect(hWnd, &defaultRect); /*drawBitmap(hdc);*/ CaptureAnImage(hWnd); if (!dcdCreate) { createDeviceObject(hWnd); dcdCreate = true; } /* d2d drawing */ drawSomething(ps, hdc); Rendering(); ValidateRect(hWnd, NULL); EndPaint(hWnd, &ps); } break; case WM_SIZE: { UINT nWidth = LOWORD(lParam); UINT nHeight = HIWORD(lParam); //OnResize(hWnd, nWidth, nHeight); return 0; } break; case WM_DESTROY: { Clean(); CoUninitialize(); PostQuitMessage(0); //return 0; } break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; } /* Message handler for about box */ INT_PTR CALLBACK About( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { UNREFERENCED_PARAMETER(lParam); switch (message) { case WM_INITDIALOG: { return (INT_PTR)TRUE; } case WM_COMMAND: { if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) { EndDialog(hDlg, LOWORD(wParam)); return (INT_PTR)TRUE; } break; } } return (INT_PTR)FALSE; }