getrawinputdata within a simple main() - c++

I am trying to read values from the joystick using simple C++ techniques and Windows.
My aim is to write a program that sends a keyboard command whenever the joystick signal exceeds a predefined threshold. The keyboard command will be picked up by whichever window would be active at the time.
My C++ coding skills are limited so I wish to do this in the simplest way, preferably within one main().
Up to now I have managed to register the joystick.
But I stumbled across the first problem, which is how to use GetRawInputData(). I found a lot of examples about this within a win32 structure, but am struggling to translate this to a simple main().
My code till now is the following:
#include <windows.h>
#include <iostream>
RAWINPUTDEVICE Rid[1];
int main()
{
UINT bufferSize;
Rid[0].usUsagePage = 0x01;
Rid[0].usUsage = 0x05;
Rid[0].dwFlags = 0;
Rid[0].hwndTarget = 0;
if (RegisterRawInputDevices(Rid, 1, sizeof(Rid[0])) == FALSE)
{
std::cout << "Registration failed" << std::endl;
return 1;
}
else
{
std::cout << "Registration OK" << std::endl;
while (1)
{
// This is the part in which I would like to read the joystick values
// and determine whether to send a keyboard event or not.
}
}
return 0;
}
Can you help?
Thanks.
UPDATE
Following the suggestion to use joyGetInput(), here is the updated code:
#include<Windows.h>
#include<iostream>
#include<time.h>
using namespace std;
#define mid 32767
#define trig 1804
#define reset 1475
int main()
{
JOYINFO pos;
UINT result;
SYSTEMTIME st;
INPUT xi, yi, zi;
int i = 0;
int state[6] = { 0,0,0,0,0,0 };
int uu = mid + trig;
int ul = mid + reset;
xi.type = INPUT_KEYBOARD;
yi.type = INPUT_KEYBOARD;
zi.type = INPUT_KEYBOARD;
while (1)
{
result = joyGetPos(i, &pos);
if (result != JOYERR_NOERROR)
{
cout << "JoyID " << i << " returned an error. Trying the next one." << endl;
i++;
if (i > 15)
{
cout << "Reached the maximum allowed attempts. Exiting." << endl;
return 1;
}
}
else
{
//GetSystemTime(&st);
//cout << st.wHour << ":" << st.wMinute << ":" << st.wSecond << ":" << st.wMilliseconds << "\tX: " << pos.wXpos << "\tY: " << pos.wYpos << "\tZ: " << pos.wZpos << endl;
if (pos.wXpos > uu && state[0] == 0)
{
xi.ki.wVk = 0x30;
xi.ki.dwFlags = 0;
SendInput(1, &xi, sizeof(INPUT));
state[0] = 1;
GetSystemTime(&st);
cout << "Key down - X axis" << endl;
cout << st.wHour << ":" << st.wMinute << ":" << st.wSecond << ":" << st.wMilliseconds << "\tX: " << pos.wXpos << "\tY: " << pos.wYpos << "\tZ: " << pos.wZpos << endl;
}
if (pos.wXpos < ul && state[0] == 1)
{
xi.ki.wVk = 0x30;
xi.ki.dwFlags = KEYEVENTF_KEYUP;
SendInput(1, &xi, sizeof(INPUT));
state[0] = 0;
GetSystemTime(&st);
cout << "Key up - X axis" << endl;
cout << st.wHour << ":" << st.wMinute << ":" << st.wSecond << ":" << st.wMilliseconds << "\tX: " << pos.wXpos << "\tY: " << pos.wYpos << "\tZ: " << pos.wZpos << endl;
}
}
}
return 0;
}
My new question now is:
How do you simulate a long key press? I would like the target window to behave just like a user kept pressing on the key. With the above code, the key is issued only once.

GetRawInputData() takes an HRAWINPUT handle as input. The only place you can get that handle is from the LPARAM parameter of the WM_INPUT window message.
Your main() function needs to use CreateWindow/Ex() to create a window (if you don't want the user to see it, consider making a message-only window), specify that window in the joystick's RAWINPUTDEVICE::hwndTarget field when you call RegisterRawInputDevices(), and then run a message loop so the window can receive messages. For example:
#include <windows.h>
#include <iostream>
int main()
{
WNDCLASSEX wx = {};
wx.cbSize = sizeof(WNDCLASSEX);
wx.lpfnWndProc = DefWindowProc;
wx.hInstance = GetModuleHandle(NULL);
wx.lpszClassName = TEXT("MyRawInputWndClass");
if (!RegisterClassEx(&wx))
{
std::cout << "Window Class Registration failed" << std::endl;
return 1;
}
HWND hWnd = CreateWindowEx(0, wx.lpszClassName, NULL, 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, wx.hInstance, NULL);
if (!hWnd)
{
std::cout << "Window Creation failed" << std::endl;
return 1;
}
RAWINPUTDEVICE Rid = {};
Rid.usUsagePage = 0x01;
Rid.usUsage = 0x05;
Rid.dwFlags = 0;
Rid.hwndTarget = hWnd;
if (!RegisterRawInputDevices(&Rid, 1, sizeof(RAWINPUTDEVICE)))
{
std::cout << "Device Registration failed" << std::endl;
return 1;
}
std::cout << "Device Registration OK" << std::endl;
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
if (msg.message == WM_INPUT)
{
HRAWINPUT hRawInput = reinterpret_cast<HRAWINPUT>(msg.lParam);
// retrieve and process data from hRawInput as needed...
}
else
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return 0;
}
Alternatively:
#include <windows.h>
#include <iostream>
LRESULT CALLBACK MyWndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
if (Msg == WM_INPUT)
{
HRAWINPUT hRawInput = reinterpret_cast<HRAWINPUT>(lParam);
// retrieve and process data from hRawInput as needed...
}
return DefWindowProc(hWnd, Msg, wParam, lParam);
}
int main()
{
WNDCLASSEX wx = {};
wx.cbSize = sizeof(WNDCLASSEX);
wx.lpfnWndProc = &MyWndProc;
wx.hInstance = GetModuleHandle(NULL);
wx.lpszClassName = TEXT("MyRawInputWndClass");
if (!RegisterClassEx(&wx))
{
std::cout << "Window Class Registration failed" << std::endl;
return 1;
}
HWND hWnd = CreateWindowEx(0, wx.lpszClassName, NULL, 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, wx.hInstance, NULL);
if (!hWnd)
{
std::cout << "Window Creation failed" << std::endl;
return 1;
}
RAWINPUTDEVICE Rid = {};
Rid.usUsagePage = 0x01;
Rid.usUsage = 0x05;
Rid.dwFlags = 0;
Rid.hwndTarget = hWnd;
if (!RegisterRawInputDevices(&Rid, 1, sizeof(RAWINPUTDEVICE)))
{
std::cout << "Device Registration failed" << std::endl;
return 1;
}
std::cout << "Device Registration OK" << std::endl;
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
I suggest you read the Raw Input documentation more carefully. This is all explained in detail. If you don't specify a window to RegisterRawInputDevices(), the OS will send the WM_INPUT messages to whichever window currently has the keyboard focus, which is not what you want.
That being said, if you want something simplier, you might consider using joyGetPosEx() instead of Raw Input.

Related

What is causing these strange colors in the console when using WriteConsoleOutputAttribute?

I am currently trying to format a console window with characters in certain positions with color-coding to make things fun. All was fine and simple until I tried to perform a simple coloring operation to a line of text on row 4, which resulted in many odd background colors and foreground colors being mixed. What could be the cause of this?
I have created a simple reproducible example:
#define UNICODE
#include <iostream>
#include <Windows.h>
#include <string>
#pragma comment(lib, "User32.lib")
using namespace std;
int main()
{
HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
HANDLE hStdIn = GetStdHandle(STD_INPUT_HANDLE);
HANDLE hStdErr = GetStdHandle(STD_ERROR_HANDLE);
SMALL_RECT consoleCoords{0, 0, 79, 19};
COORD sbSize{80, 20};
if(!SetConsoleWindowInfo(hStdOut, TRUE, &consoleCoords)) /* HANDLE hConsoleOutput, BOOL bAbsolute, const SMALL_RECT* lpConsoleWindow */
{
wcout << L"SetConsoleWindowInfo failed. Error Code: " << GetLastError() << L'\n';
system("pause");
return 0;
}
if(!SetConsoleScreenBufferSize(hStdOut, sbSize)) /* HANDLE hConsoleOutput, COORD dwSize */
{
wcout << L"SetConsoleScreenBufferSize failed. Error Code: " << GetLastError() << L'\n';
system("pause");
return 0;
}
DWORD cCharsWritten{};
DWORD attrsWritten{};
CONSOLE_SCREEN_BUFFER_INFO bufferInfo{};
DWORD dwConsoleSz{};
system("pause");
if(!GetConsoleScreenBufferInfo(hStdOut, &bufferInfo))
{
wcout << L"GetConsoleScreenBufferInfo failed. Error Code: " << GetLastError() << '\n';
system("pause");
return 0;
}
dwConsoleSz = bufferInfo.dwSize.X * bufferInfo.dwSize.Y; /* X (character cells) * Y (character cells) */
COORD cursorHome{0, 0};
/* Now we fill the entire screen with blanks. */
if(!FillConsoleOutputCharacter(
hStdOut,
L' ',
dwConsoleSz,
cursorHome,
&cCharsWritten
)
)
{
wcout << L"FillConsoleOutputCharacter failed. Error Code: " << GetLastError() << '\n';
system("pause");
return 0;
}
if(!SetConsoleCursorPosition(hStdOut, cursorHome))
/*Research is needed regarding this function as it does not seem to move the cursor. */
{
wcout << L"SetConsoleCursorPosition failed. Error Code: " << GetLastError() << '\n';
system("pause");
return 0;
}
wchar_t topmiddlebottomRow[] = L"================";
wchar_t separatorString[] = L"================================================================================";
LPCWSTR writeRow = topmiddlebottomRow;
LPCWSTR writeSeparator = separatorString;
WORD S_attr = FOREGROUND_GREEN;
if(!WriteConsoleOutputCharacterW(hStdOut, writeRow, 16, COORD{64, 0}, &cCharsWritten))
{
wcout << L"WriteConsoleOutputCharacterW failed. Error Code: " << GetLastError() << L'\n';
system("pause");
return 0;
}
if(!WriteConsoleOutputCharacterW(hStdOut, writeRow, 16, COORD{64, 1}, &cCharsWritten))
{
wcout << L"WriteConsoleOutputCharacterW failed. Error Code: " << GetLastError() << L'\n';
system("pause");
return 0;
}
if(!WriteConsoleOutputCharacterW(hStdOut, writeRow, 16, COORD{64, 2}, &cCharsWritten))
{
wcout << L"WriteConsoleOutputCharacterW failed. Error Code: " << GetLastError() << L'\n';
system("pause");
return 0;
}
if(!WriteConsoleOutputCharacterW(hStdOut, writeSeparator, 80, COORD{0, 4}, &cCharsWritten))
{
wcout << L"WriteConsoleOutputCharacterW failed. Error Code: " << GetLastError() << L'\n';
system("pause");
return 0;
}
if(!WriteConsoleOutputAttribute(hStdOut, &S_attr, 80, COORD{0, 4}, &attrsWritten))
{
wcout << L"WriteConsoleOutputAttribute failed. Error Code: " << GetLastError() << L'\n';
system("pause");
return 0;
}
while(1)
{
}
return 0;
}
The #pragma comment preprocessor line may be unnecessary - I am still learning.

WriteProcessMemory not working for some reason

This is all the source code for a program i'm trying to make, and I can't get WriteProcessMemory to work at all. It returns the correct messages, saying that everything went successfully, but nothing actually changes in the game. Does anyone know of a fix?
#include <iostream>
#include <Windows.h>
using namespace std;
// variables
int plcHold = 1;
string hlthLoop = "OFF";
string ammoLoop = "OFF";
DWORD pid;
DWORD playerAddr;
DWORD hlthOffs = 0xF8;
// main function
int main()
{
// finding pid, opening proc, finding player address
HWND hwnd = FindWindowA(NULL, "AssaultCube");
if(hwnd == NULL)
{
cout << "Error; Couldn't find window" << endl;
} else{
GetWindowThreadProcessId(hwnd, &pid);
HANDLE pHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
if(pHandle == NULL)
{
cout << "Error; Couldn't open process" << endl;
} else{
ReadProcessMemory(pHandle, (LPCVOID)0x50F4F4, &playerAddr, sizeof(playerAddr), 0);
if(ReadProcessMemory != FALSE)
{
cout << "Health successfully read!" << endl;
} else{
cout << "Error code " << GetLastError << endl;
}
}
while(plcHold == 1){
cout << "========== *****'s Assault Cube Trainer ==========\n" << endl;
cout << "=============== Health Loop - " << hlthLoop << " ================" << endl;
Sleep(1500);
system("cls");
if(GetAsyncKeyState(0x5A))
{
cout << "Health successfully edited!" << endl;
WriteProcessMemory(pHandle, LPVOID(playerAddr + hlthOffs), 0, sizeof(999), 0);
CloseHandle(pHandle);
}
}
}
return 0;
}
You're passing a null pointer to WriteProcessMemory for the third (lpBuffer) parameter. You have to pass the address of the actual value, not the value itself. If you want to write an integer value, try this:
DWORD val = 0; // or 999?
WriteProcessMemory(
pHandle, static_cast<LPVOID>(playerAddr + hlthOffs),
&val, sizeof(val), 0);

mingw-w64 gcc does not recognize DXGI_FORMAT from dxgiformat.h

i just wanted to make sure i don't lose my mind here. I wanted to build a simple Direct3D 11 application and had a basic window running. I now wanted to add some actual rendering but unfortunately my compiler won't recognize the DXGI_FORMAT enum type from dxgiformat.h. I tried many thinks of one was to literally copy the content of the header manually but no luck. Also i checked the output of the preprocessor and confirmed that gcc actually draws its resources from the right places and that the content of the header was in there correctly. Furthermore this is the only dxgiformat.h header on this machine. I'm aware of the unused variable since this is what i was going to use before this problem occured. I now just wanted to be save this is not a user problem before trying to report any bugs. As i stated i'm using the MinGW-w64 toolchain from the installer. These are my Error messages:
$ make
[BUILD] D3D11App.o
In file included from D3D11App.cpp:4:
D3D11App.hpp:11:2: error: 'DXGI_FORMAT_R32G32B32_FLOAT' does not name a type
DXGI_FORMAT_R32G32B32_FLOAT position;
^~~~~~~~~~~~~~~~~~~~~~~~~~~
D3D11App.hpp:12:2: error: 'DXGI_FORMAT_R8G8B8_UNORM' does not name a type; did you mean 'DXGI_FORMAT_R8G8_UNORM'?
DXGI_FORMAT_R8G8B8_UNORM color;
^~~~~~~~~~~~~~~~~~~~~~~~
DXGI_FORMAT_R8G8_UNORM
D3D11App.cpp: In constructor 'D3D11App::D3D11App(HWND)':
D3D11App.cpp:103:20: warning: unused variable 'bufferDesc' [-Wunused-variable]
D3D11_BUFFER_DESC bufferDesc = {
^~~~~~~~~~
make: *** [makefile:15: D3D11App.o] Fehler 1
and my code:
main.cpp
#include <iostream>
#include <d3d11.h>
#include <windows.h>
#include <windowsx.h>
#include "D3D11App.hpp"
using namespace std;
HWND init(HINSTANCE hInstance, const int x, const int y, const int w, const int h);
LRESULT CALLBACK windowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
D3D11App *d3d11;
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE prevInstance, LPSTR cmdLine, int cmdShow) {
cout << "Reslution: " << GetSystemMetrics(SM_CXSCREEN) << "x" << GetSystemMetrics(SM_CYSCREEN) << endl;
HWND window = init(hInstance, 0, 0, 800, 600);
if (window == NULL) {
cout << "Error while initializing: " << GetLastError() << endl;
return GetLastError();
}
d3d11 = new D3D11App(window);
ShowWindow(window, cmdShow);
UpdateWindow(window);
MSG msg;
while (msg.message != WM_QUIT) {
if ( PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) ) {
TranslateMessage(&msg);
DispatchMessage(&msg);
} else {
d3d11->render();
}
}
return 0;
}
HWND init(HINSTANCE hInstance, const int x, const int y, const int w, const int h) {
WNDCLASSEX windowClass = {
sizeof(WNDCLASSEX),
CS_HREDRAW | CS_VREDRAW,
windowProc,
0,
0,
hInstance,
NULL,
NULL,
(HBRUSH)COLOR_WINDOW,
"Window",
"windowClass",
NULL
};
if(RegisterClassEx(&windowClass) == 0) {
cout << "Error while registering class: " << GetLastError() << endl;
return NULL;
}
return CreateWindowEx (
WS_EX_TOPMOST,
"windowClass",
"D3D11",
WS_POPUP,
x, y,
w, h,
NULL,
NULL,
hInstance,
NULL
);
}
LRESULT CALLBACK windowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {
switch(msg) {
case WM_DESTROY:
PostQuitMessage(0);
return 0;
case WM_KEYDOWN:
switch(wParam) {
case VK_ESCAPE:
PostQuitMessage(0);
return 0;
}
case WM_MOUSEMOVE:
cout << "x :" << GET_X_LPARAM(lParam) << ", y: " << GET_Y_LPARAM(lParam) << endl;
return 0;
}
return DefWindowProc(hWnd, msg, wParam, lParam);
}
D3DApp11.hpp
#ifndef D3D11APP_HPP
#define D3D11APP_HPP
#include <d3d11.h>
#include <dxgiformat.h>
#include <vector>
struct customVertex {
DXGI_FORMAT_R32G32B32_FLOAT position;
DXGI_FORMAT_R8G8B8_UNORM color;
};
class D3D11App {
ID3D11Device *device;
ID3D11DeviceContext *devcon;
IDXGISwapChain *swapChain;
ID3D11RenderTargetView *backbuffer;
ID3D11Buffer *vertexBuffer;
public:
D3D11App(HWND hWnd);
~D3D11App();
void render();
};
#endif /* D3D11APP_HPP */
D3D11App.cpp
#include <iostream>
#include <dxgiformat.h>
#include <memory>
#include "D3D11App.hpp"
using namespace std;
D3D11App::D3D11App(HWND hWnd) {
HRESULT status;
WINDOWINFO windowInfo;
IDXGIAdapter * pAdapter;
IDXGIFactory * pFactory;
status = CreateDXGIFactory(__uuidof(IDXGIFactory), reinterpret_cast<void**>(&pFactory));
for(int i = 0; pFactory->EnumAdapters(i, &pAdapter) != DXGI_ERROR_NOT_FOUND; i++) {
DXGI_ADAPTER_DESC adapterDesc;
pAdapter->GetDesc(&adapterDesc);
cout << "Video Adapter " << i << ":" << endl
<< "Description: " << adapterDesc.Description << endl
<< "VendorId: 0x" << hex << adapterDesc.VendorId << endl
<< "DeviceID: 0x" << adapterDesc.DeviceId << endl
<< "SubSysId: 0x" << adapterDesc.SubSysId << endl
<< "Revision: " << adapterDesc.Revision << endl
<< dec << endl;
}
if(status != S_OK) {
cout << "Error while creating factory Error(0x" << hex << status << dec << ")" << endl;
}
if( ! GetWindowInfo(hWnd, &windowInfo) ) {
cout << "Error while retreiving window informattion" << endl;
}
cout << "client width: " << windowInfo.rcClient.right << " client height: " << windowInfo.rcClient.bottom << endl;
DXGI_SWAP_CHAIN_DESC scd = {
/* BufferDesc */
{
static_cast<UINT>(windowInfo.rcClient.right),
static_cast<UINT>(windowInfo.rcClient.bottom),
60,
DXGI_MODE_SCALING_UNSPECIFIED,
DXGI_FORMAT_R8G8B8A8_UNORM,
DXGI_MODE_SCANLINE_ORDER_PROGRESSIVE
},
/* SampleDesc */
{
8,
0
},
DXGI_USAGE_RENDER_TARGET_OUTPUT,
1,
hWnd,
true,
DXGI_SWAP_EFFECT_DISCARD
};
status = D3D11CreateDeviceAndSwapChain(
NULL,
D3D_DRIVER_TYPE_HARDWARE,
NULL,
D3D11_CREATE_DEVICE_SINGLETHREADED,
NULL,
0,
D3D11_SDK_VERSION,
&scd,
&(this->swapChain),
&(this->device),
NULL,
&(this->devcon)
);
if(status != S_OK) {
cout << "Error while creating device and swap chain Error(0x" << hex << status << dec << ")" << endl;
return;
}
ID3D11Texture2D *pBackBuffer;
status = swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBackBuffer);
if (status != S_OK) {
cout << "Error while getting backbuffer adress Error(0x" << hex << status << dec << ")" << endl;
return;
}
status = device->CreateRenderTargetView(pBackBuffer, NULL, &backbuffer);
if (status != S_OK) {
cout << "Error while creating render target view Error(0x" << hex << status << dec << ")" << endl;
return;
}
pBackBuffer->Release();
devcon->OMSetRenderTargets(1, &backbuffer, NULL);
D3D11_VIEWPORT viewPort;
ZeroMemory(&viewPort, sizeof(D3D11_VIEWPORT));
viewPort.TopLeftX = (FLOAT)0.0;
viewPort.TopLeftY = (FLOAT)0.0;
viewPort.Width = static_cast<FLOAT>(windowInfo.rcClient.right);
viewPort.Height = static_cast<FLOAT>(windowInfo.rcClient.bottom);
devcon->RSSetViewports(1, &viewPort);
D3D11_BUFFER_DESC bufferDesc = {
3 * sizeof(customVertex),
D3D11_USAGE_DYNAMIC,
D3D11_BIND_VERTEX_BUFFER,
D3D11_CPU_ACCESS_WRITE,
0,
sizeof(customVertex)
};
}
D3D11App::~D3D11App() {
this->swapChain->Release();
this->backbuffer->Release();
this->device->Release();
this->devcon->Release();
}
void D3D11App::render() {
devcon->ClearRenderTargetView(backbuffer, (const FLOAT[]){0.0,0.2,0.5,1.0});
if(swapChain->Present(0, 0) != S_OK) {
cout << "Error while presenting" << endl;
}
}
DXGI_FORMAT_R32G32B32_FLOAT is an enum that describes a particular memory layout, but is not itself a C++ structure you can declare in your vertex type.
You can use float position[3], but many DirectX C++ programs use the various DirectXMath types such as DirectX::XMFLOAT3 position;. There's a fairly complete list of equivalents here.

SetWindowPos() sometimes does not resize child-windows

First, I use Createprocess() to open all desired windows. (Not Listed)
After the successful opening of the processes I find with the FindWindow () and FindWindowEx() all available windows. (Listed)
Sometimes the function SetWindowPos() does not work properly. A few windows were sorted out a few not. But this case does not always occur!
For improvements I always have an open ear!
//Some Variables comming from other code : numberOfWindows / numberOfStartedWindows
//Variables
bool trigger = true;
bool targetProcess = true;
HWND hwnd, hwndChilds = NULL;
int targetsFound = 0;
int targetsFoundMath = 0;
bool searchWindows = true;
//Start targetProcess
while (targetProcess) {
//If targetsFround == numberOfWindows then exit targetProcess.
if (targetsFound == numberOfWindows)
{
targetProcess = false;
}
//If all Windows are Started then start search loop
if (numberOfStartedWindows == numberOfWindows)
{
trigger = false;
}
//We starting search loop...
if (!trigger && targetProcess) {
//Find the Main Window.
hwnd = FindWindow(0, _T("World of Warcraft"));
if (hwnd)
{
targetsFound += 1;
//Set Window Foreground and call SetWindowPos to change Position
if (SetForegroundWindow(hwnd)) {
if (!SetWindowPos(hwnd, HWND_TOP, 0, 0, 1920, 800, SWP_SHOWWINDOW))
{
cout << "Error: HWND Failed with SETWINDOWPOS" << endl;
}
}
//Store HWND in StoreWindows
StoreWindows.emplace_back(hwnd);
//Now we search for child Windows
while (searchWindows)
{
//do it if targetsFound not numberOfWindows
if (targetsFound != numberOfWindows)
{
//Get Child Window
hwndChilds = FindWindowEx(NULL, hwnd, NULL, _T("World of Warcraft"));
if (hwndChilds != NULL)
{
//Little Math for Position
targetsFoundMath = (targetsFound - 1) * 384;
//if window in foreground SetWindowPos.
if(SetForegroundWindow(hwndChilds)){
if (!SetWindowPos(hwndChilds, HWND_TOP, targetsFoundMath, 800, 384, 280, SWP_SHOWWINDOW))
{
cout << "Error: HWNDChilds Failed with SETWINDOWPOS" << endl;
}
}
/*targetsFound += 1;
StoreWindows.emplace_back(hwndChilds);*/
//If all targetsFound then quit this loop after finish
if (targetsFound == numberOfWindows) {
searchWindows = false;
cout << "false" << targetsFound << endl;
}
//StoreChild Window and Add targetsfround +1
targetsFound += 1;
StoreWindows.emplace_back(hwndChilds);
}
else {
searchWindows = false;
cout << "no more child objects found!" << endl;
}
}
else
{
searchWindows = false;
}
}
}
}
}
cout << "Window Size: " << StoreWindows.size() << endl;
Funny when I debugs:
RECT debugRect;
for (int x = 0; x < StoreWindows.size(); x++)
{
GetClientRect(StoreWindows[x], &debugRect);
cout << debugRect.left << " " << debugRect.right<< " " << debugRect.bottom<< " " << debugRect.top << endl;
//debugRect.right = breite vom fenster // debugRect.bottom = Höhe
}
The output from the Position looks good but the Window isnt on the right place :/
Debug:
Im out of ideas and hope you can help me! If you need more explanations, do not hesitate to ask.
With problems it looks so..
If everything goes without problems it looks like this:
The problem was the duplicate (same) window partial to be found. Because the start process takes longer than the Find Func. Now i have Fixxed the loop. (Its wait now for all success windows.)
bool mainWindow = false;
bool searchHwndStrike = false;
int targetResult = 0;
while (true)
{
//Search first Window
if (!mainWindow) {
hwnd = FindWindow(0, _T("World of Warcraft"));
if (hwnd != NULL)
{
if (SetForegroundWindow(hwnd)) {
if (!SetWindowPos(hwnd, HWND_TOP, 0, 0, 1920, 800, SWP_SHOWWINDOW))
{
cout << "Error: HWND Failed with SETWINDOWPOS" << endl;
}
}
cout << "Main window found." << endl;
mainWindow = true;
StoreWindows.emplace_back(hwnd);
}
}else {
if (StoreWindows.size() < numberOfWindows) {
hwnd = FindWindowEx(NULL, hwnd, NULL, _T("World of Warcraft"));
if (hwnd != NULL)
{
for (int x = 0; x < StoreWindows.size(); x++)
{
if (StoreWindows[x] == hwnd)
{
searchHwndStrike = true;
}
}
if (!searchHwndStrike)
{
cout << "Child window found." << endl;
cout << targetResult << endl;
targetResult = (StoreWindows.size()-1) * 384;
//if window in foreground SetWindowPos.
if (SetForegroundWindow(hwnd)) {
if (!SetWindowPos(hwnd, HWND_TOP, targetResult, 800, 384, 280, SWP_SHOWWINDOW))
{
cout << "Error: HWNDChilds Failed with SETWINDOWPOS" << endl;
}
}
StoreWindows.emplace_back(hwnd);
}
searchHwndStrike = false;
}
}
else {
break;
}
}
}
cout << StoreWindows.size() << endl;

CreateDC returns an error 1801

I need to receive screenshots from MS Mirror driver, but unexpectedly I noticed, that CreateDC() function returns NULL and GetLastError gives me Error#1801 ("The printer name is invalid")
extern "C" __declspec(dllexport) HDC InitDC() {
DWORD dwAttach = 0;
DEVMODE devmode;
// Make sure we have a display on this thread.
BOOL change = EnumDisplaySettings(NULL,
ENUM_CURRENT_SETTINGS,
&devmode);
LPCWSTR driverName = L"Microsoft Mirror Driver";
devmode.dmFields = DM_BITSPERPEL |
DM_PELSWIDTH |
DM_PELSHEIGHT |
DM_POSITION ;
devmode.dmSize = sizeof(DEVMODE);
devmode.dmDriverExtra = 0;
if (change)
{
// query all display devices in the system until we hit a primary
// display device. Using it get the width and height of the primary
// so we can use that for the mirror driver. Also enumerate the
// display devices installed on this machine untill we hit
// our favourate mirrored driver, then extract the device name string
// of the format '\\.\DISPLAY#'
DISPLAY_DEVICE dispDevice;
FillMemory(&dispDevice, sizeof(DISPLAY_DEVICE), 0);
dispDevice.cb = sizeof(DISPLAY_DEVICE);
LPCWSTR deviceName = NULL;
devmode.dmDeviceName[0] = '\0';
INT devNum = 0;
BOOL result;
DWORD cxPrimary = 0xFFFFFFFF;
DWORD cyPrimary = 0xFFFFFFFF;
// First enumerate for Primary display device:
while ((result = EnumDisplayDevices(NULL,
devNum,
&dispDevice,
0)) == TRUE)
{
wcout << "DriverName: " << dispDevice.DeviceString << endl;
wcout << "DevName: " << dispDevice.DeviceName << endl;
if (dispDevice.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE)
{
// Primary device. Find out its dmPelsWidht and dmPelsHeight.
EnumDisplaySettings(dispDevice.DeviceName,
ENUM_CURRENT_SETTINGS,
&devmode);
cxPrimary = devmode.dmPelsWidth;
cyPrimary = devmode.dmPelsHeight;
wcout << "Selected Primary DevName (width, height): " << dispDevice.DeviceName << " (" << cxPrimary << "," << cyPrimary << ")" << endl << endl;
break;
}
devNum++;
}
// error check
if (!result)
{
wcout << "No " << driverName << " found " << endl;
exit(0);
}
if (cxPrimary == 0xffffffff || cyPrimary == 0xffffffff)
{
wcout << "cxPrimary or cyPrimary not valid" << endl;
exit(0);
}
// Enumerate again for the mirror driver:
devNum = 0;
while ((result = EnumDisplayDevices(NULL,
devNum,
&dispDevice,
0)) == TRUE)
{
LPCWSTR devString = dispDevice.DeviceString;
wcout << " devString: "<< devString << endl;
if (wcscmp(devString, driverName ) == 0) {
wcout << " Driver selected: "<< driverName << endl;
break;
}
devNum++;
}
// error check
if (!result)
{
wcout << "No " << driverName << " found " << endl;
exit(0);
}
wcout << "DevNum " << devNum << endl <<
"DeviceName: " << dispDevice.DeviceName << endl <<
"DeviceString: " << dispDevice.DeviceString << endl <<
"DeviceID: " << dispDevice.DeviceID << endl <<
"DeviceKey: " << dispDevice.DeviceKey << endl;
CHAR *deviceNum = new CHAR[MAX_PATH];
LPSTR deviceSub;
// Simply extract 'DEVICE#' from registry key. This will depend
// on how many mirrored devices your driver has and which ones
// you intend to use.
_wcsupr(&dispDevice.DeviceKey[0]);
deviceSub = (LPSTR)(wcsstr(&dispDevice.DeviceKey[0],
L"\\DEVICE"));
if (!deviceSub) {
printf("deviceSub - yes \n");
deviceNum[0] = (CHAR)(((string)("DEVICE0")).c_str());
}
else {
printf("!deviceSub \n");
deviceNum[0] = (CHAR)(((string)("DEVICE1")).c_str());
}
// Reset the devmode for mirror driver use:
FillMemory(&devmode, sizeof(DEVMODE), 0);
devmode.dmSize = sizeof(DEVMODE);
devmode.dmDriverExtra = 0;
devmode.dmFields = DM_BITSPERPEL |
DM_PELSWIDTH |
DM_PELSHEIGHT |
DM_POSITION;
//wcscpy( devmode.dmDeviceName, sizeof(devmode.dmDeviceName, L"mirror" );
deviceName = dispDevice.DeviceName;
StringCbCopy(devmode.dmDeviceName, sizeof(devmode.dmDeviceName), dispDevice.DeviceName);
wcout << "dmDeviceName: " << devmode.dmDeviceName << endl;
wcout << "deviceName: " << deviceName << endl;
wcout << "driverName: " << driverName << endl;
/* !!! THE PROBLEM IS HERE !!!*/
HDC hdc = CreateDC(driverName, deviceName, NULL, &devmode );
if ( hdc == NULL ) {
wcout << "CreateDC error: " << GetLastError() << endl;
return NULL;
}
return hdc;
}
return NULL;
}
Thanks for an assistance!
UPD1:
deviceName = "\\.\DISPLAYV1"
driverName = "Microsoft Mirror Driver"
devmode.dmDeviceName = "\\.\DISPLAYV1"