I was making a program that draws two lines and a circle in the window, for this I used Direct2D. I was doing a program that draws two lines and a circle in the window. I noticed a problem and that is that when drawing a line of coordinates (100,200), (200,200), that line is not drawn in the pixels (100,200) and ( 200,200). I checked this by reading the coordinates of the mouse in the window and seeing if the line actually has the coordinates that I mentioned. Do a little more research, and according to Microsoft, direct2d works with dpi and not physical pixels. So is there a way to work directly with pixels like in Processing or Win32 where the position of the controls is expressed in physical pixels of the window.
#include <d2d1_3.h>
#include <d2d1_3helper.h>
#include <d3d11_1.h>
#include <dxgi1_6.h>
#include <string>
#pragma comment(lib,"d3d11")
#pragma comment(lib,"d2d1")
#pragma comment(lib,"dxgi")
#pragma warning(disable : 4996)
using namespace D2D1;
using namespace std;
template<typename Interface> void SafeRelease(Interface**);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInst
, _In_ LPWSTR lpCmdLine, _In_ int nCmdShow) {
UNREFERENCED_PARAMETER(hPrevInst);
UNREFERENCED_PARAMETER(lpCmdLine);
WNDCLASS wc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = NULL;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_WINLOGO));
wc.hInstance = hInstance;
wc.lpfnWndProc = WndProc;
wc.lpszClassName = L"Demo_Wnd_Class";
wc.lpszMenuName = NULL;
wc.style = 0;
RegisterClass(&wc);
DWORD dwTopLevelWndStyle = WS_OVERLAPPEDWINDOW ^ (WS_THICKFRAME | WS_MAXIMIZEBOX);
RECT clientRc = { 0,0,640,480 };
AdjustWindowRect(&clientRc, dwTopLevelWndStyle, FALSE);
HWND hWnd = CreateWindow(L"Demo_Wnd_Class", L"Direct2DDemo", dwTopLevelWndStyle, CW_USEDEFAULT, CW_USEDEFAULT
, clientRc.right - clientRc.left, clientRc.bottom - clientRc.top, NULL, NULL, hInstance, NULL);
ShowWindow(hWnd, SW_SHOWDEFAULT);
MSG msg;
ZeroMemory(&msg, sizeof(MSG));
ID3D11Device* d3dDevice;
IDXGIDevice* dxgiDevice = NULL;
D3D_FEATURE_LEVEL featureLevels[] = {
D3D_FEATURE_LEVEL_11_1,
D3D_FEATURE_LEVEL_11_0,
D3D_FEATURE_LEVEL_10_1,
D3D_FEATURE_LEVEL_10_0,
D3D_FEATURE_LEVEL_9_3,
D3D_FEATURE_LEVEL_9_2,
D3D_FEATURE_LEVEL_9_1,
};
HRESULT hr = D3D11CreateDevice(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, D3D11_CREATE_DEVICE_BGRA_SUPPORT, featureLevels
, 7, D3D11_SDK_VERSION, &d3dDevice, NULL, NULL);
if (SUCCEEDED(hr)) {
OutputDebugString(L"D3D11 Device created successful\n");
hr = d3dDevice->QueryInterface(__uuidof(IDXGIDevice), (void**)&dxgiDevice);
}
ID2D1Device6* d2dDevice = NULL;
ID2D1DeviceContext6* d2dDeviceContext = NULL;
IDXGIFactory2* dxgiFactory = NULL;
IDXGISwapChain1* dxgiSwapChain = NULL;
IDXGISurface *dxgiBackBufferSurface = NULL; // Back buffer
ID2D1Bitmap1* bmpTarget = NULL;
ID2D1SolidColorBrush* shapeBr = NULL;
DXGI_SWAP_CHAIN_DESC1 dscd;
dscd.AlphaMode = DXGI_ALPHA_MODE_IGNORE;
dscd.BufferCount = 2;
dscd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
dscd.Flags = 0;
dscd.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
dscd.Height = 480;
dscd.SampleDesc.Count = 1;
dscd.SampleDesc.Quality = 0;
dscd.Scaling = DXGI_SCALING_NONE;
dscd.Stereo = FALSE;
dscd.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
dscd.Width = 640;
if (SUCCEEDED(hr)) {
OutputDebugString(L"DXGI Device created successful\n");
hr = D2D1CreateDevice(dxgiDevice, CreationProperties(D2D1_THREADING_MODE_SINGLE_THREADED, D2D1_DEBUG_LEVEL_NONE, D2D1_DEVICE_CONTEXT_OPTIONS_NONE), (ID2D1Device**)&d2dDevice);
}
if (SUCCEEDED(hr)) {
OutputDebugString(L"D2D Device created successful\n");
hr = d2dDevice->CreateDeviceContext(D2D1_DEVICE_CONTEXT_OPTIONS_NONE, (ID2D1DeviceContext**)&d2dDeviceContext);
}
if (SUCCEEDED(hr)) {
OutputDebugString(L"D2D Device Context created successful\n");
hr = CreateDXGIFactory2(DXGI_CREATE_FACTORY_DEBUG, __uuidof(IDXGIFactory2), (void**)&dxgiFactory);
}
if (SUCCEEDED(hr)) {
OutputDebugString(L"DXGI Factory created successful\n");
hr = dxgiFactory->CreateSwapChainForHwnd(d3dDevice, hWnd, &dscd, NULL, NULL, &dxgiSwapChain);
}
if (SUCCEEDED(hr)) {
OutputDebugString(L"DXGI Swap Chain created successful\n");
hr = dxgiSwapChain->GetBuffer(0, __uuidof(IDXGISurface), (void**)&dxgiBackBufferSurface);
}
if (SUCCEEDED(hr)) {
hr = d2dDeviceContext->CreateBitmapFromDxgiSurface(dxgiBackBufferSurface, BitmapProperties1(D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW, PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_IGNORE),0,0), &bmpTarget);
}
if (SUCCEEDED(hr)) {
OutputDebugString(L"D2D Bitmap created successful\n");
d2dDeviceContext->SetTarget(bmpTarget);
hr = d2dDeviceContext->CreateSolidColorBrush(ColorF(ColorF::White), &shapeBr);
}
if (SUCCEEDED(hr)) {
OutputDebugString(L"D2D Solid Color Brush created successful\n");
d2dDeviceContext->SetUnitMode(D2D1_UNIT_MODE_PIXELS);
d2dDeviceContext->SetTransform(Matrix3x2F::Identity());
d2dDeviceContext->SetAntialiasMode(D2D1_ANTIALIAS_MODE::D2D1_ANTIALIAS_MODE_ALIASED);
}
while (msg.message != WM_QUIT) {
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else {
d2dDeviceContext->BeginDraw();
d2dDeviceContext->Clear(ColorF(ColorF::ForestGreen));
d2dDeviceContext->DrawLine(Point2F(400, 0), Point2F(400, 400), shapeBr);
d2dDeviceContext->DrawLine(Point2F(200.0f, 320.0f), Point2F(400.0f, 320.0f), shapeBr);
d2dDeviceContext->DrawEllipse(D2D1::Ellipse(Point2F(300.0f, 300.0f), 10.0f, 10.0f), shapeBr);
POINT cursorPos;
GetCursorPos(&cursorPos);
ScreenToClient(hWnd,&cursorPos);
wstring dbgCursorPos = wstring(L"(MouseX: " + to_wstring(cursorPos.x) + L" MouseY: " + to_wstring(cursorPos.y) + L")\n");
OutputDebugString(dbgCursorPos.c_str());
d2dDeviceContext->EndDraw();
dxgiSwapChain->Present(1, 0);
}
}
SafeRelease(&d3dDevice);
SafeRelease(&dxgiBackBufferSurface);
SafeRelease(&dxgiDevice);
SafeRelease(&dxgiFactory);
SafeRelease(&dxgiSwapChain);
SafeRelease(&d2dDevice);
SafeRelease(&d2dDeviceContext);
SafeRelease(&bmpTarget);
SafeRelease(&shapeBr);
return 0;
}
template<typename Interface> void SafeRelease(Interface** ppInterface) {
if (*ppInterface) {
(*ppInterface)->Release();
(*ppInterface) = NULL;
}
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) {
if (Msg == WM_DESTROY) {
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hWnd, Msg, wParam, lParam);
}