I'm working on a simple GUI, though my GUI window is unaligned and I cant see any issues in the code. I'm throwing this out there in hopes someone has seen this before because im pretty new to ImGui and have been looking at this code for days lol.
this GUI is using direct x 9.
here's the main .cpp file.
#pragma once
#include "gui.h"
#include "imgui.h"
#include "imgui_impl_dx9.h"
#include "imgui_impl_win32.h"
extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(
HWND window,
UINT message,
WPARAM wideParameter,
LPARAM longParameter
);
long __stdcall WindowProcess(
HWND window,
UINT message,
WPARAM wideParameter,
LPARAM longParameter
)
{
if (ImGui_ImplWin32_WndProcHandler(window, message, wideParameter, longParameter))
return true;
switch (message)
{
case WM_SIZE: {
if (gui::device && wideParameter != SIZE_MINIMIZED)
{
gui::presentParams.BackBufferWidth = LOWORD(longParameter);
gui::presentParams.BackBufferHeight = LOWORD(longParameter);
gui::ResetDevice();
}
}return 0;
case WM_SYSCOMMAND: {
if ((wideParameter & 0xfff0) == SC_KEYMENU)
return 0;
}break;
case WM_DESTROY: {
PostQuitMessage(0);
}return 0;
case WM_LBUTTONDOWN: {
gui::pos = MAKEPOINTS(longParameter);
}return 0;
case WM_MOUSEMOVE: {
if (wideParameter == MK_LBUTTON)
{
const auto points = MAKEPOINTS(longParameter);
auto rect = ::RECT{};
GetWindowRect(gui::window, &rect);
rect.left += points.x - gui::pos.x;
rect.top += points.y - gui::pos.y;
if (gui::pos.x >= 0 &&
gui::pos.x <= gui::w &&
gui::pos.y >= 0 && gui::pos.y <= 19)
SetWindowPos(
gui::window,
HWND_TOPMOST,
rect.left,
rect.top,
0, 0,
SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOZORDER
);
}
}
}
return DefWindowProcW(window, message, wideParameter, longParameter);
}
void gui::CreateHWindow(const char* windowName, const char* className) noexcept
{
windowClass.cbSize = sizeof(WNDCLASSEXA);
windowClass.style = CS_CLASSDC;
windowClass.lpfnWndProc = WindowProcess;
windowClass.cbClsExtra = 0;
windowClass.cbWndExtra = 0;
windowClass.hInstance = GetModuleHandleA(0);
windowClass.hIcon = 0;
windowClass.hCursor = 0;
windowClass.hbrBackground = 0;
windowClass.lpszMenuName = 0;
windowClass.lpszClassName = className;
windowClass.hIconSm = 0;
RegisterClassExA(&windowClass);
window = CreateWindowA(
className,
windowName,
WS_POPUP,
0,
0,
w,
h,
0,
0,
windowClass.hInstance,
0
);
ShowWindow(window, SW_SHOWDEFAULT);
UpdateWindow(window);
}
void gui::DestroyHWindow() noexcept
{
DestroyWindow(window);
UnregisterClass(windowClass.lpszClassName, windowClass.hInstance);
}
bool gui::CreateDevice() noexcept
{
d3d = Direct3DCreate9(D3D_SDK_VERSION);
if (!d3d)
return false;
ZeroMemory(&presentParams, sizeof(presentParams));
presentParams.Windowed = TRUE;
presentParams.SwapEffect = D3DSWAPEFFECT_DISCARD;
presentParams.BackBufferFormat = D3DFMT_UNKNOWN;
presentParams.EnableAutoDepthStencil = TRUE;
presentParams.AutoDepthStencilFormat = D3DFMT_D16;
presentParams.PresentationInterval = D3DPRESENT_INTERVAL_ONE;
if (d3d->CreateDevice(
D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL,
window,
D3DCREATE_HARDWARE_VERTEXPROCESSING,
&presentParams,
&device) < 0)
return false;
return true;
}
void gui::ResetDevice() noexcept
{
ImGui_ImplDX9_InvalidateDeviceObjects();
const auto result = device->Reset(&presentParams);
if (result == D3DERR_INVALIDCALL)
IM_ASSERT(0);
ImGui_ImplDX9_CreateDeviceObjects();
}
void gui::DestroyDevice() noexcept
{
if (device)
{
device->Release();
device = nullptr;
}
if (d3d)
{
d3d->Release();
d3d = nullptr;
}
}
void gui::CreateGUI() noexcept
{
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGuiIO& io = ::ImGui::GetIO();
io.IniFilename = NULL;
// GUI style colors
ImGui::StyleColorsDark();
ImGui_ImplWin32_Init(window);
ImGui_ImplDX9_Init(device);
}
void gui::DestroyGUI() noexcept
{
ImGui_ImplDX9_Shutdown();
ImGui_ImplWin32_Shutdown();
ImGui::DestroyContext();
}
void gui::BeginRender() noexcept
{
MSG message;
while (PeekMessage(&message, 0, 0, 0, PM_REMOVE))
{
TranslateMessage(&message);
DispatchMessage(&message);
}
ImGui_ImplDX9_NewFrame();
ImGui_ImplWin32_NewFrame();
ImGui::NewFrame();
}
void gui::EndRender() noexcept
{
ImGui::EndFrame();
device->SetRenderState(D3DRS_ZENABLE, FALSE);
device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
device->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE);
device->Clear(0,0,D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_RGBA(100, 0, 230, 255), 1.0f, 0);
if (device->BeginScene() >= 0)
{
ImGui::Render();
ImGui_ImplDX9_RenderDrawData(ImGui::GetDrawData());
device->EndScene();
}
const auto result = device->Present(0, 0, 0, 0);
if (result == D3DERR_DEVICELOST && device->TestCooperativeLevel() == D3DERR_DEVICENOTRESET)
ResetDevice();
}
void gui::Render() noexcept
{
ImGui::SetWindowPos({0,0 });
ImGui::SetNextWindowSize({ w - 100,h - 100});
ImGui::Begin(
"Window",
&exit,
ImGuiWindowFlags_NoResize |
ImGuiWindowFlags_NoSavedSettings |
ImGuiWindowFlags_NoCollapse |
ImGuiWindowFlags_NoMove
);
}
[![GUI Image][1]][1]
[1]: https://i.stack.imgur.com/YBGdn.png
Related
been trying to make a basic auto clicker and cannot seem to get MouseInput to click the mouse. I believe it's probably something simple causing this issue. No errors occur it just won't do what it is intended to do.
Could somebody take a look at it and tell me whats wrong with it?
#include <iostream>
#include <Windows.h>
#include <thread>
#include <conio.h>
void loop()
{
int cps;
std::cout << "Enter desired clicks per second: ";
std::cin >> cps;
bool toggled = false;
while (true)
{
static bool bPressedToggle = false;
if (GetKeyState(VK_TAB) < 0)
bPressedToggle = true;
else if (bPressedToggle)
{
bPressedToggle = false;
toggled = !toggled;
std::cout << (toggled ? "Toggled" : "Disabled") << std::endl;
if (!toggled) continue;
}
if (toggled && (GetAsyncKeyState(VK_LBUTTON) & (1 << 16)))
{
POINT pntCurrentCursor;
GetCursorPos(&pntCurrentCursor);
INPUT inpMouseInput;
inpMouseInput.type = INPUT_MOUSE;
inpMouseInput.mi.dwFlags = MOUSEEVENTF_LEFTDOWN;
inpMouseInput.mi.dx = pntCurrentCursor.x;
inpMouseInput.mi.dy = pntCurrentCursor.y;
SendInput(1, &inpMouseInput, sizeof(INPUT)); // DOWN
RtlZeroMemory(&inpMouseInput, sizeof(INPUT));
inpMouseInput.type = INPUT_MOUSE;
inpMouseInput.mi.dwFlags = MOUSEEVENTF_LEFTUP;
inpMouseInput.mi.dx = pntCurrentCursor.x;
inpMouseInput.mi.dy = pntCurrentCursor.y;
SendInput(1, &inpMouseInput, sizeof(INPUT)); // UP
Sleep( 1000 / cps);
}
//Sleep(1);
}
}
int main()
{
loop();
return 0;
} ```
As a supplement, the screen coordinates returned by GetCursorPos need to be converted to absolute and passed to SendInput:
dx = (x * 65536) / GetSystemMetrics(SystemMetric.SM_CXSCREEN);
dy = (y * 65536) / GetSystemMetrics(SystemMetric.SM_CYSCREEN);
And #IInspectable had provided enough useful information, for this I have created a simple demo for reference only.
#include <iostream>
#include <Windows.h>
#include <thread>
#include <conio.h>
#define IDT_MOUSETRAP 100
HWND hWnd;
bool toggled = false;
int cps;
HANDLE hThread;
BOOL flag = true;
VOID CALLBACK MyTimerProc(HWND hwnd, UINT message, UINT idTimer, DWORD dwTime)
{
POINT pntCurrentCursor;
GetCursorPos(&pntCurrentCursor);
INPUT inpMouseInput;
inpMouseInput.type = INPUT_MOUSE;
inpMouseInput.mi.dwFlags = MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_LEFTDOWN;
inpMouseInput.mi.dx = (pntCurrentCursor.x * 65536) / GetSystemMetrics(SM_CXSCREEN);;
inpMouseInput.mi.dy = (pntCurrentCursor.y * 65536) / GetSystemMetrics(SM_CYSCREEN);;
SendInput(1, &inpMouseInput, sizeof(INPUT)); // DOWN
RtlZeroMemory(&inpMouseInput, sizeof(INPUT));
inpMouseInput.type = INPUT_MOUSE;
inpMouseInput.mi.dwFlags = MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_LEFTUP;
inpMouseInput.mi.dx = pntCurrentCursor.x;
inpMouseInput.mi.dy = pntCurrentCursor.y;
SendInput(1, &inpMouseInput, sizeof(INPUT)); // UP
}
DWORD WINAPI MyThreadFunction(LPVOID lpParam)
{
UINT uResult = SetTimer(hWnd, IDT_MOUSETRAP, 1000 / cps, (TIMERPROC)MyTimerProc);
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, NULL, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return 0;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static bool bPressedToggle = false;
DWORD ThreadId;
switch (message)
{
case WM_CREATE:
{
std::cout << "Enter desired clicks per second: ";
std::cin >> cps;
}
break;
case WM_KEYDOWN:
{
if (GetKeyState(VK_TAB) < 0)
{
bPressedToggle = true;
if (bPressedToggle)
{
bPressedToggle = false;
toggled = !toggled;
std::cout << (toggled ? "Toggled" : "Disabled") << std::endl;
}
if (toggled == true && flag == true)
{
flag = false;
hThread = CreateThread(NULL, 0, MyThreadFunction, NULL, 0, &ThreadId);
}
else if (toggled == false && flag == false)
{
KillTimer(hWnd, IDT_MOUSETRAP);
flag = true;
}
}
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
void Createyourwindow()
{
WNDCLASSEXW wcex = { 0 };
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = GetModuleHandle(NULL);
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wcex.lpszClassName = L"MyClass";
RegisterClassExW(&wcex);
hWnd = CreateWindowW(L"MyClass", L"window", WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, GetModuleHandle(NULL), NULL);
ShowWindow(hWnd, SW_SHOW);
UpdateWindow(hWnd);
MSG msg;
// Main message loop:
while (GetMessage(&msg, NULL, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, NULL, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
}
int main()
{
Createyourwindow();
return 0;
}
Note: Because the message loop of the window is needed, the mouse focus needs to be inside the window when pressing the TAB key.
I am extending an old console application. Trying to add a window( for an animation ). Are able to display first image, but unable to update the window with later images. Have created a minimum application to demonstrate the problem. In this app I have a red window that should change at each update of the window( it is not ). What am I doing wrong ?
#include "pch.h"
#include <iostream>
#include <Windows.h>
using namespace std;
HWND hWindow;
LRESULT __stdcall MyWindowProcedure(HWND hWnd, unsigned int msg, WPARAM wp, LPARAM lp)
{
PAINTSTRUCT ps;
HDC hdc;
HBITMAP hBitmap;
VOID * pvBits;
RGBQUAD *bmiColors;
static int j = 128;
HBITMAP hOldBmp;
BITMAPINFO MyBitmap;
BOOL qRetBlit;
switch (msg)
{
case WM_DESTROY:
std::cout << "\ndestroying window\n";
PostQuitMessage(0);
return 0L;
case WM_LBUTTONDOWN:
std::cout << "\nmouse left button down at (" << LOWORD(lp)
<< ',' << HIWORD(lp) << ")\n";
// fall thru
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
#if 1
// Create a device context that is compatible with the window
HDC hLocalDC;
hLocalDC = ::CreateCompatibleDC(hdc);
// Verify that the device context was created
if (hLocalDC == NULL) {
printf("CreateCompatibleDC Failed\n");
// return false;
break;
}
MyBitmap.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
MyBitmap.bmiHeader.biWidth = 256;
MyBitmap.bmiHeader.biHeight = -256;
MyBitmap.bmiHeader.biPlanes = 1;
MyBitmap.bmiHeader.biBitCount = 32;
MyBitmap.bmiHeader.biCompression = BI_RGB;
MyBitmap.bmiHeader.biSizeImage = 256 * 256 * 4;
MyBitmap.bmiHeader.biYPelsPerMeter = 1000;
MyBitmap.bmiHeader.biXPelsPerMeter = 1000;
MyBitmap.bmiHeader.biClrUsed = 0;
MyBitmap.bmiHeader.biClrImportant = 0;
hBitmap = CreateDIBSection(NULL, &MyBitmap, DIB_RGB_COLORS, &pvBits, NULL, NULL);
bmiColors = (RGBQUAD*)pvBits;
// note: BGR
for (int i = 0; i < 256 * 256; i++)
{
bmiColors[i].rgbBlue = 0;
bmiColors[i].rgbGreen = 0;
bmiColors[i].rgbRed = j % 256;
bmiColors[i].rgbReserved = 255;
}
j += 10;
bmiColors[1000].rgbRed;
// Select the bitmap into the device context
hOldBmp = (HBITMAP)::SelectObject(hLocalDC, hBitmap);
if (hOldBmp == NULL) {
printf("SelectObject Failed");
// return false;
break;
}
// Blit the dc which holds the bitmap onto the window's dc
qRetBlit = ::BitBlt(hdc, 0, 0, 256, 256, hLocalDC, 0, 0, SRCCOPY);
if (!qRetBlit) {
printf("Blit Failed");
// return false;
break;
}
// Unitialize and deallocate resources
SelectObject(hLocalDC, hOldBmp);
DeleteDC(hLocalDC);
DeleteObject(hBitmap);
#endif
EndPaint(hWnd, &ps);
break;
default:
std::cout << '.';
break;
}
return DefWindowProc(hWnd, msg, wp, lp);
}
int main()
{
WNDCLASSEX wndclass = { sizeof(WNDCLASSEX), CS_DBLCLKS | CS_HREDRAW, MyWindowProcedure,
0, 0, GetModuleHandle(0), LoadIcon(0,IDI_APPLICATION),
LoadCursor(0,IDC_ARROW), HBRUSH(COLOR_WINDOW + 1),
0, L"myclass", LoadIcon(0,IDI_APPLICATION) };
if (RegisterClassEx(&wndclass))
{
hWindow = CreateWindowEx(0, L"myclass", L"myclass", WS_OVERLAPPEDWINDOW, 1200, 600, 256 + 15, 256 + 38, 0, 0, GetModuleHandle(0), 0);
ShowWindow(hWindow, SW_SHOWDEFAULT);
UpdateWindow(hWindow);
MSG msg;
byte bRet;
while ((bRet = GetMessage(&msg, hWindow, 0, 0)) != 0)
{
if (bRet == -1)
{
return 1;
}
else
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
}
}
As pointed out. You do not want to call WM_PAINT your self. Let the system handle it. So in WM_LBUTTONDOWN do:
case WM_LBUTTONDOWN:
std::cout << "\nmouse left button down at (" << LOWORD(lp)
<< ',' << HIWORD(lp) << ")\n";
InvalidateRect(hWnd, nullptr, FALSE);
return 0;
Do not fall through. Wnen you call RedrawWindow the window is invalidated and then needs to be repainted. I just tested this, the window lightens up on each click.
UPDATE:
Thanks to Remy Lebeau
Difference between InvalidateRect and RedrawWindow
And yes, it is better to let windows use its own schedule for this kind of stuff.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I'm having a very annoying issue for something I'm working on. I've tried numerous solutions and researching this error doesnt help solve my exact issue. Is anyone able to help? I've included my Overlay.cpp below...
#include "Overlay.h"
Overlay::Overlay() {
m_hWnd = NULL;
m_hGame = NULL;
m_pDirect3D = nullptr;
m_pDevice = nullptr;
memset(&m_Present, NULL, sizeof(D3DPRESENT_PARAMETERS));
}
Overlay::~Overlay() {
if (m_pDevice) {
m_pDevice->Release();
m_pDevice = nullptr;
}
if (m_pDirect3D) {
m_pDirect3D->Release();
m_pDirect3D = nullptr;
}
}
bool Overlay::Attach(HWND hWnd) {
m_hGame = hWnd;
if (!m_hGame) {
return false;
}
RECT client;
GetClientRect(m_hGame, &client);
m_nSize[0] = client.right;
m_nSize[1] = client.bottom;
WNDCLASSEX wc = { NULL };
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_VREDRAW | CS_HREDRAW;
wc.lpfnWndProc = WndProcedure;
wc.cbClsExtra = NULL;
wc.cbWndExtra = NULL;
wc.hInstance = NULL;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
wc.lpszMenuName = NULL;
wc.lpszClassName = OVERLAY_NAME;
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
if (!RegisterClassEx(&wc)) {
return false;
}
m_hWnd = CreateWindowEx(WS_EX_TOPMOST | WS_EX_COMPOSITED | WS_EX_TRANSPARENT | WS_EX_LAYERED, OVERLAY_NAME, OVERLAY_NAME, WS_POPUP, CW_USEDEFAULT, CW_USEDEFAULT, m_nSize[0], m_nSize[1], NULL, NULL, NULL, NULL);
if (!m_hWnd) {
return false;
}
MARGINS margin = { -1, -1, -1, -1 };
DwmExtendFrameIntoClientArea(m_hWnd, &margin);
ShowWindow(m_hWnd, SW_SHOWDEFAULT);
UpdateWindow(m_hWnd);
RECT game;
GetWindowRect(m_hGame, &game);
RECT cl;
GetClientRect(m_hGame, &cl);
int w = game.right - game.left;
int h = game.bottom - game.top;
LONG_PTR dwStyle = GetWindowLongPtr(m_hGame, GWL_STYLE);
if (dwStyle & WS_BORDER) {
int x = GetSystemMetrics(SM_CXBORDER);
int y = GetSystemMetrics(SM_CYCAPTION) + GetSystemMetrics(SM_CYBORDER);
game.left += x;
game.top += y;
w -= x;
h -= y;
}
MoveWindow(m_hWnd, game.left, game.top, w, h, TRUE);
m_nSize[0] = w;
m_nSize[1] = h;
return InitDirectX();
}
int Overlay::OnFrame() {
MSG msg;
while (true) {
Sleep(1);
if (PeekMessage(&msg, NULL, NULL, NULL, PM_REMOVE)) {
if (msg.message == WM_QUIT) {
break;
}
TranslateMessage(&msg);
DispatchMessageA(&msg);
} else {
m_pDevice->Clear(NULL, NULL, D3DCLEAR_TARGET, NULL, 1.0f, NULL);
m_pDevice->BeginScene();
if (!m_pOnFrameList.empty()) {
for (auto& pOnFrame : m_pOnFrameList) {
if (pOnFrame) {
pOnFrame();
}
}
}
m_pDevice->EndScene();
m_pDevice->Present(NULL, NULL, NULL, NULL);
}
}
return (int)msg.wParam;
}
void Overlay::AddOnFrame(const OnFrameFn& pFunction) {
m_pOnFrameList.push_back(pFunction);
}
void Overlay::GetScreenSize(int* width, int* height) {
if (width) {
*width = m_nSize[0];
}
if (height) {
*height = m_nSize[1];
}
}
IDirect3DDevice9* Overlay::GetDevice() const {
return m_pDevice;
}
bool Overlay::InitDirectX() {
m_Present.EnableAutoDepthStencil = TRUE;
m_Present.AutoDepthStencilFormat = D3DFMT_D16;
m_Present.Windowed = TRUE;
m_Present.BackBufferCount = 1;
m_Present.BackBufferFormat = D3DFMT_A8R8G8B8;
m_Present.BackBufferWidth = m_nSize[0];
m_Present.BackBufferHeight = m_nSize[1];
m_Present.MultiSampleType = D3DMULTISAMPLE_NONE;
m_Present.SwapEffect = D3DSWAPEFFECT_DISCARD;
m_Present.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
m_Present.hDeviceWindow = m_hWnd;
m_pDirect3D = Direct3DCreate9(D3D_SDK_VERSION);
if (!m_pDirect3D) {
return false;
}
if (FAILED(m_pDirect3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, m_hWnd, D3DCREATE_HARDWARE_VERTEXPROCESSING, &m_Present, &m_pDevice))) {
return false;
}
if (!m_pDevice) {
return false;
}
return true;
}
LRESULT WINAPI Overlay::WndProcedure(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
switch (message) {
case WM_DESTROY:
PostQuitMessage(NULL);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return NULL;
}
My error occurs at this line m_pDevice->Clear(NULL, NULL, D3DCLEAR_TARGET, NULL, 1.0f, NULL);
Any help would be much appreciated
NULL means 0x0.
So probably you are passing NULL to m_pDevice->Clear() where its going to be read.
Additionally, make sure that m_pDevice is not nullptr.
In a short sample I generate a HwndRenderTarget, a Brush, a PathGeometry in this two lines are drawn both starting at the same Point. But in the rendered Frame they don't start at the same point but clearly intersect each other ( they are extended beyond the starting point)
Main.cpp
#include<Windows.h>
#include "Graphics.h"
Graphics* graphics;
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_DESTROY:
PostQuitMessage(0);
return 0;
//case WM_PAINT:
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE prevInstance, LPWSTR cmd, int nCMDShow)
{
WNDCLASSEX windowclass;
ZeroMemory(&windowclass, sizeof(WNDCLASSEX));
windowclass.cbSize = sizeof(WNDCLASSEX);
windowclass.hbrBackground = (HBRUSH)COLOR_WINDOW;
windowclass.hInstance = hInstance;
windowclass.lpfnWndProc = WindowProc;
windowclass.lpszClassName = "MainWindow";
windowclass.style = CS_HREDRAW | CS_VREDRAW;
RegisterClassEx(&windowclass);
RECT rect = { 0,0,564,564 };
AdjustWindowRectEx(&rect, WS_OVERLAPPEDWINDOW, false, WS_EX_OVERLAPPEDWINDOW);
HWND windowhandle = CreateWindowEx(WS_EX_OVERLAPPEDWINDOW,"MainWindow", "Intersection Test", WS_OVERLAPPEDWINDOW, 100, 100,
rect.right - rect.left, rect.bottom- rect.top, NULL, NULL, hInstance, 0);
if (!windowhandle) return -1;
graphics = new Graphics();
if (!graphics->Init(windowhandle))
{
delete graphics;
return -1;
}
ShowWindow(windowhandle, nCMDShow);
graphics->PrepareSpirale();
MSG msg;
msg
.message = WM_NULL;
while (msg.message != WM_QUIT) //
{
if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
{
DispatchMessage(&msg);
}
else
{
graphics->BeginDraw();
graphics->ClearScreen(1, 1, 1);
graphics->DrawGraphics();
graphics->EndDraw();
}
}
delete graphics;
return 0;
}
Graphics.h
#pragma once
#include <Windows.h>
#include<d2d1.h>
#include <math.h>
class Graphics
{
ID2D1Factory* factory;
ID2D1HwndRenderTarget* renderTarget;
ID2D1PathGeometry * BorderCCW;
ID2D1GeometrySink * pSink;
ID2D1SolidColorBrush *RedBrush;
public:
Graphics();
~Graphics();
bool Init(HWND windowHandle);
void BeginDraw() { renderTarget->BeginDraw(); }
void EndDraw() { renderTarget->EndDraw(); }
void PrepareSpirale();
void DrawGraphics();
void ClearScreen(float r, float g, float b );
};
Graphics.cpp
#include"Graphics.h"
Graphics::Graphics()
{
factory = NULL;
renderTarget = NULL;
pSink = NULL;
BorderCCW = NULL;
RedBrush = NULL;
}
Graphics::~Graphics()
{
if (factory) factory->Release();
if (renderTarget) renderTarget->Release();
}
bool Graphics::Init(HWND windowHandle)
{
HRESULT res = 0;
// Create renderTarget
if (SUCCEEDED(res))
{
res = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &factory);
RECT rect;
GetClientRect(windowHandle, &rect);
D2D1_SIZE_U size = D2D1::SizeU(
rect.right - rect.left,
rect.bottom - rect.top
);
if (SUCCEEDED(res))
res = factory->CreateHwndRenderTarget(
D2D1::RenderTargetProperties(),
D2D1::HwndRenderTargetProperties(windowHandle, size),
&renderTarget);
FLOAT dpiX, dpiY;
factory->GetDesktopDpi(&dpiX, &dpiY);
// Create Other Resurces
if (SUCCEEDED(res))
{
// Brushes
res = renderTarget->CreateSolidColorBrush(
D2D1::ColorF(1.0f, 0.13f, 0.13f, 1.0f),
&RedBrush);
}
return true;
}
return false;
}
void Graphics::PrepareSpirale()
{
HRESULT res = 0;
if (SUCCEEDED(res))
{
res = factory->CreatePathGeometry(&BorderCCW);
if (SUCCEEDED(res))
{
res = BorderCCW->Open(&pSink);
D2D1_POINT_2F currentLocation = { 281.5f, 281.5f };
pSink->BeginFigure(currentLocation, D2D1_FIGURE_BEGIN_HOLLOW);
pSink->AddLine(D2D1::Point2F(132.5, 432.5));
pSink->EndFigure(D2D1_FIGURE_END_CLOSED);
pSink->BeginFigure(currentLocation, D2D1_FIGURE_BEGIN_HOLLOW);
pSink->AddLine(D2D1::Point2F(132+ 282.5f, 432.5));
pSink->EndFigure(D2D1_FIGURE_END_CLOSED);
}
//}
res = pSink->Close();
pSink->Release();
pSink = NULL;
}
}
void Graphics::DrawGraphics()
{
//renderTarget->SetAntialiasMode(D2D1_ANTIALIAS_MODE_ALIASED);
renderTarget->DrawGeometry(BorderCCW, RedBrush, 2.f);
}
void Graphics::ClearScreen(float r, float g, float b )
{
renderTarget->Clear(D2D1::ColorF(r, g, b));
}
Rendered Lines
As this is my first adventure into C++ any style comments are also most welcome, but them main question is to find an explaination for this strange phenomenon.
First thing first, I am not that good in programming yet, so forgive me if I cant solve trivial problems. I want to display a basic screen in a window, so I made a framework for it from 3 diferrent sources, cause I wanted to write it from step to step to fully understand it. But still, I am getting this 3 errors and I dont know how to solve them. Thanking you in advance of you help.
The first code:
#ifndef WINAPPFRAME_H
#define WINAPPFRAME_H
#include <windows.h>
#include <windowsx.h>
#include <d3d11.h>
#include <d3dx11.h>
#include <d3dx10.h>
#include <string>
#pragma comment (lib, "d3d11.lib")
#pragma comment (lib, "d3dx11.lib")
#pragma comment (lib, "d3dx10.lib")
#define Release(x) { if(x){ x->Release(); x = 0; } }
#ifndef HR
#define HR(x) (x)
#endif
class D3Dwap
{
public:
D3Dwap(HINSTANCE hInstance);
~D3Dwap();
HINSTANCE AppInst()const;
HWND MainWnd()const;
bool Initialize();
int Run();
void Draw();
static LRESULT CALLBACK MsgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
protected:
bool InitMainWindow();
bool InitDirect3D();
protected:
HINSTANCE hD3DwapInst;
HWND hMainWnd;
ID3D11Device* D3Dwap_device;
ID3D11DeviceContext* D3Dwap_dev_context;
IDXGISwapChain* D3Dwap_SwapChain;
ID3D11Texture2D* D3Dwap_DepthStencilBuffer;
ID3D11RenderTargetView* D3Dwap_RenderTargetView;
ID3D11DepthStencilView* D3Dwap_DepthStencilView;
D3D11_VIEWPORT D3Dwap_ScreenViewport;
ID3D11Texture2D* backBuffer;
std::wstring MainWndCaption;
D3D_DRIVER_TYPE d3dDriverType;
int ScreenWidth;
int ScreenHeight;
};
D3Dwap* d3dwapl = 0;
#endif
The second part:
#include "WinAppFrame.h"
LRESULT CALLBACK MainWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
return d3dwapl->MsgProc(hwnd, msg, wParam, lParam);
}
D3Dwap::D3Dwap(HINSTANCE hInstance):
hD3DwapInst(hInstance),
MainWndCaption(L"Engine 2.0"),
d3dDriverType(D3D_DRIVER_TYPE_HARDWARE),
ScreenWidth(800),
ScreenHeight(600),
hMainWnd(0),
D3Dwap_device(0),
D3Dwap_dev_context(0),
D3Dwap_SwapChain(0) {}
D3Dwap::~D3Dwap()
{
Release(D3Dwap_SwapChain);
if( D3Dwap_dev_context )
D3Dwap_dev_context->ClearState(); //Ha még aktív az ezköz tartalma, törli azt
Release(D3Dwap_dev_context);
Release(D3Dwap_device);
}
HINSTANCE D3Dwap::AppInst()const
{
return hD3DwapInst;
}
HWND D3Dwap::MainWnd()const
{
return hMainWnd;
}
int D3Dwap::Run()
{
MSG msg;
while(msg.message != WM_QUIT)
{
if(PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
Draw();
}
return msg.wParam;
}
bool D3Dwap::Initialize()
{
if(!InitMainWindow())
return false;
if(!InitDirect3D())
return false;
return true;
}
LRESULT D3Dwap::MsgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_DESTROY:
{
PostQuitMessage(0);
return 0;
}
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}
bool D3Dwap::InitMainWindow()
{
WNDCLASSEX wc;
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = MainWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hD3DwapInst;
wc.hIcon = LoadIcon(0, IDI_APPLICATION);
wc.hCursor = LoadCursor(0, IDC_ARROW);
wc.hbrBackground = (HBRUSH)GetStockObject(NULL_BRUSH);
wc.lpszClassName = L"D3Dwap_test";
if( !RegisterClassEx(&wc) )
{
MessageBox(0, L"Az ablakot nem sikerült regisztrálni", 0, 0);
return false;
}
RECT Rect = { 0, 0, ScreenWidth, ScreenHeight };
AdjustWindowRect(&Rect, WS_OVERLAPPEDWINDOW, false);
int width = Rect.right - Rect.left;
int height = Rect.bottom - Rect.top;
hMainWnd = CreateWindow (L"D3Dwap_test",
MainWndCaption.c_str(),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
width,
height,
0,
0,
hD3DwapInst,
0);
if( !hMainWnd )
{
MessageBox(0, L"Az ablakot nem sikerült létrehozni!", 0, 0);
return false;
}
ShowWindow(hMainWnd, SW_SHOW);
UpdateWindow(hMainWnd);
return true;
}
bool D3Dwap::InitDirect3D()
{
UINT create_D3Dwap_device_flags = 0;
D3D_FEATURE_LEVEL featurelevel;
HRESULT hr = D3D11CreateDevice(0,
d3dDriverType,
0,
create_D3Dwap_device_flags = 0,
0,
0,
D3D11_SDK_VERSION,
&D3Dwap_device,
&featurelevel,
&D3Dwap_dev_context);
if( FAILED(hr) )
{
MessageBox(0, L"A D3D11 eszközt nem sikerült létrehozni!", 0, 0);
return false;
}
if( featurelevel != D3D_FEATURE_LEVEL_11_0 )
{
MessageBox(0, L"A DirectX 11.0 a hardware által nem támogatott!", 0, 0);
return false;
}
DXGI_SWAP_CHAIN_DESC sd;
sd.BufferDesc.Width = ScreenWidth;
sd.BufferDesc.Height = ScreenHeight;
sd.BufferDesc.RefreshRate.Numerator = 60;
sd.BufferDesc.RefreshRate.Denominator = 1;
sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
sd.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
sd.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
sd.SampleDesc.Count = 1;
sd.SampleDesc.Quality = 0;
sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
sd.BufferCount = 1;
sd.OutputWindow = hMainWnd;
sd.Windowed = true;
sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
sd.Flags = 0;
IDXGIDevice* dxgiDevice = 0;
if(FAILED(HR(D3Dwap_device->QueryInterface(__uuidof(IDXGIDevice), (void**)&dxgiDevice))))
{
return false;
}
IDXGIAdapter* dxgiAdapter = 0;
if(FAILED(HR(dxgiDevice->GetParent(__uuidof(IDXGIAdapter), (void**)&dxgiAdapter))))
{
return false;
}
IDXGIFactory* dxgiFactory = 0;
if(FAILED(HR(dxgiAdapter->GetParent(__uuidof(IDXGIFactory), (void**)&dxgiFactory))))
{
return false;
}
HR(dxgiFactory->CreateSwapChain(D3Dwap_device, &sd, &D3Dwap_SwapChain));
ID3D11Texture2D* backBuffer;
if(FAILED(HR(D3Dwap_SwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), reinterpret_cast<void**>(&backBuffer)))))
{
return false;
}
if(FAILED(HR(D3Dwap_device->CreateRenderTargetView(backBuffer, 0, &D3Dwap_RenderTargetView))))
{
return false;
}
Release(backBuffer);
D3D11_TEXTURE2D_DESC depthStencilDesc;
depthStencilDesc.Width = ScreenWidth;
depthStencilDesc.Height = ScreenHeight;
depthStencilDesc.MipLevels = 1;
depthStencilDesc.ArraySize = 1;
depthStencilDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
depthStencilDesc.SampleDesc.Count = 1;
depthStencilDesc.SampleDesc.Quality = 0;
depthStencilDesc.Usage = D3D11_USAGE_DEFAULT;
depthStencilDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
depthStencilDesc.CPUAccessFlags = 0;
depthStencilDesc.MiscFlags = 0;
if(FAILED(HR(D3Dwap_device->CreateTexture2D(&depthStencilDesc, 0, &D3Dwap_DepthStencilBuffer))))
{
return false;
}
if(FAILED(HR(D3Dwap_device->CreateDepthStencilView(D3Dwap_DepthStencilBuffer, 0, &D3Dwap_DepthStencilView))))
{
return false;
}
D3Dwap_dev_context->OMSetRenderTargets(1, &D3Dwap_RenderTargetView, D3Dwap_DepthStencilView);
D3Dwap_ScreenViewport.TopLeftX = 0;
D3Dwap_ScreenViewport.TopLeftY = 0;
D3Dwap_ScreenViewport.Width = static_cast<float>(ScreenWidth);
D3Dwap_ScreenViewport.Height = static_cast<float>(ScreenHeight);
D3Dwap_ScreenViewport.MinDepth = 0.0f;
D3Dwap_ScreenViewport.MaxDepth = 1.0f;
D3Dwap_dev_context->RSSetViewports(1, &D3Dwap_ScreenViewport);
Release(dxgiDevice);
Release(dxgiAdapter);
Release(dxgiFactory);
return true;
}
and the third code:
#include "WinAppFrame.h"
class InitDirect3Dwap : public D3Dwap
{
public:
InitDirect3Dwap(HINSTANCE hInstance);
~InitDirect3Dwap();
bool Initialize();
void UpdateScene(float dt);
void Draw();
};
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE prevInstance,
PSTR cmdLine, int showCmd)
{
// Enable run-time memory check for debug builds.
#if defined(DEBUG) | defined(_DEBUG)
_CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
#endif
InitDirect3Dwap theApp(hInstance);
if( !theApp.Initialize() )
return 0;
return theApp.Run();
}
InitDirect3Dwap::InitDirect3Dwap(HINSTANCE hInstance)
: D3Dwap(hInstance)
{
}
InitDirect3Dwap::~InitDirect3Dwap()
{
}
bool InitDirect3Dwap::Initialize()
{
if(!D3Dwap::Initialize())
return false;
return true;
}
void InitDirect3Dwap::UpdateScene(float dt)
{
}
void InitDirect3Dwap::Draw()
{
D3Dwap_dev_context->ClearRenderTargetView(D3Dwap_RenderTargetView, D3DXCOLOR(0.0f, 0.2f, 0.4f, 1.0f));
D3Dwap_dev_context->ClearDepthStencilView(D3Dwap_DepthStencilView, D3D11_CLEAR_DEPTH|D3D11_CLEAR_STENCIL, 1.0f, 0);
HR(D3Dwap_SwapChain->Present(0, 0));
}
1st: Error 29 error LNK2005: "class D3Dwap * d3dwapl" (?d3dwapl##3PAVD3Dwap##A) already defined in main.obj C:\Users\Seraph\documents\visual studio 2012\Projects\Engine_2.0\Engine_2.0\WinAppFrame.obj Engine_2.0
2nd: Error 30 error LNK2019: unresolved external symbol "public: void __thiscall D3Dwap::Draw(void)" (?Draw#D3Dwap##QAEXXZ) referenced in function "public: int __thiscall D3Dwap::Run(void)" (?Run#D3Dwap##QAEHXZ) C:\Users\Seraph\documents\visual studio 2012\Projects\Engine_2.0\Engine_2.0\WinAppFrame.obj Engine_2.0
3rd: Error 31 error LNK1120: 1 unresolved externals C:\Users\Seraph\documents\visual studio 2012\Projects\Engine_2.0\Debug\Engine_2.0.exe 1 1 Engine_2.0
You include "WinAppFrame.h" twice which makes a class defined there to duplicate. A common solution to this issue is to put
#pragma once
at the beginning of you WinAppFrame.h file.
Then, you declare a method Draw in class D3Dwap but there's no definition in a corresponding .cpp file.