I am trying to write a program that takes in the visual output from another program (we'll call it P2) and displays it on a screen in a 3d world.
The flow of the image capture is as follows:
P2 -> BitBlt -> OpenGL Texture -> 3d World
I want the user to be able to look around and click on elements in P2 using a crosshair which would be stationary in the middle of the viewport of my program. However, in my implementation it seems that I would need to have 2 cursors - one to control the camera in my 3d world and one to control P2 - which I don't think is trivial.
Additionally, since a window only updates what part of it is visible and I want to have P2 constantly updating in as high resolution as possible, it makes sense to have P2 on a second virtual desktop. This makes the issue of interaction more difficult.
Some solutions I can think of with their downsides:
Make a Compositing Window Manager
- Sounds like a lot of work and I haven't been able to find any documentation on how this might be done.
Have the actual cursor over P2 but get the change in cursor position and use this to move the camera in the 3d world
- This wouldn't be a linear transformation from planar to spherical coordinates. Additionally, I'm not sure if the cursor could be on a different Desktop to the current Desktop.
I am open to suggestions of alternative capture methods if they would help. One example would be hooking the DirectX or OpenGL output of P2 and, if necessary, tricking it into rendering while not being active. This might allow P2 to be minimized but would not solve the issue of input.
Maybe it would be possible to hook the input functions of P2? Would this even be advised?
Here are some images to illustrate my program.
Update:
I have implemented SendNotifyMessage()
and found that when I sent a WM_LBUTTONDOWN
message to the application it became the foreground window. I set WS_EX_NOACTIVATE
on P2 to stop this behaviour however, it still steals focus. I then need to Sleep(), presumably until P2 processes the messages, and then use SetForegroundWindow()
. Note that SetFocus()
and SetActiveWindow()
do not result in my program regaining focus (so maybe focus is the wrong word). Are there any methods to remove this delay while keeping the SendNotifyMessage()
asynchronous?
Additionally, in trying to use PostMessage()
I found that the coordinate transformation was not correct. However, it worked perfectly in SendNotifyMessage()
. What could be causing this behaviour?
Relevant Code
After getting the handle to the window I want to capture I run this:
prevWndStyle = GetWindowLong(hwnd, GWL_EXSTYLE);
SetWindowLong(hwnd, GWL_EXSTYLE, prevWndStyle | WS_EX_NOACTIVATE);
After receiving a WM_INPUT
message in my WndProc
and processing the input I run this code:
if (raw->data.mouse.usButtonFlags & RI_MOUSE_LEFT_BUTTON_DOWN) {
int hitX, hitY;
if (gls->Click(vec3(0.0f, 0.0f, 1.0f), 0, hitX, hitY)) {
LPARAM lParam = MAKELPARAM(hitX, hitY);
SendNotifyMessage(gls->ic.GetHWND(), WM_MOUSEMOVE, 0, lParam);
SendNotifyMessage(gls->ic.GetHWND(), WM_LBUTTONDOWN, MK_LBUTTON, lParam);
SendNotifyMessage(gls->ic.GetHWND(), WM_LBUTTONUP, 0, lParam);
// I want to get rid of these
Sleep(100);
SetForegroundWindow(gls->aw.GetHWND());
}
}
Update 2
I have found that WS_EX_NOACTIVATE
stops the switch to the second desktop however when P2 is on the same desktop, P2 is brought to the foreground.