I am creating a system of dockable windows in win32 c++. In order to have real time feedback of where you are dragging the new window, I created a special debug window which only appears during dragging and shows where it will dock. In order to find out which pane will be docked to, I need to account for overlapping windows and find the topmost. To do this I am calling WindowFromPoint(x, y) which finds the HWND immediately under the mouse. This causes a problem because when the debug window is shown, it gets caught by WindowFromPoint, I would like to ignore it.
I have attached a picture.
If anyone has alternative suggestions for this plan, I'm happy to hear it. I thought of keeping some list of window order and tracking everytime a new window gets focus, but that seems like a big headache too...
Ok, I got it! I had the right idea but I didnt' realize that a global solution of returning 0 was a bad idea in the window procedure. Here's the right return:
case WM_NCHITTEST:
return HTTRANSPARENT;
Thanks to this thread: Find all windows beneath a point
Related
I have a program which is not written by me. I dont have its source and the developer of that program is developing independently. He gives me the HWND and HINSTANCE handles of that program.
I have created a child window ON his window, using win32 api.
First thing I need is to make this child window have transparency on some area and opaque on other area(like a Heads up display(HUD) for a game), so that the user may see things in both windows.
The second thing that I need is to direct all the input to the parent window. My child window needs no input.
I know that WS_EX_TRANSPARENT only makes the child draw at the end like in painters algorithm.
I cant use WS_EX_LAYERED because its a child window.
p.s.
I have looked everywhere but didn't find any solution though there were similar questions around the internet.
Actually this is a HUD like thing for that game. I can't draw directly on parent window because of the complexity with multi-threads any many other reasons.
-- EDIT ---------------------------
I am still working on it. I am trying different ways with what you all suggested. Is there a way to combine directX and SetWindowRgn() function or directx with BitBlt() function? I think that will do the trick. Currently I am testing all the stuff as a child window and a Layered window.
You can use WS_EX_LAYERED for child windows from Windows 8 and up.
To support earlier versions of windows, just create a level layered window as a popup (With no chrome) and ensure its positioned over the game window at the appropriate location. Most users don't move the windows they are working with all the time, so, while you will need to monitor for the parent window moving, and re position the HUD, this should not be a show stopper.
Not taking focus (in the case of being a child window) or activation (in the case of being a popup) is more interesting, but still quite do-able:- The operating system does not actually automatically assign either focus, or activation, to a clicked window - the Windows WindowProc always takes focus, or activation, by calling SetFocus, or some variant of SetActiveWindow or SetForegroundWindow on itself. The important thing here is, if you consume all mouse and non client mouse messages without passing them on to DefWindowProc, your HUD will never steal activation or keyboard focus from the Game window as a result of a click.
As a popup window, or a window on another thread, you might have to manually handle any mouse messages that your window proc does get, and post them to the game window. Otherwise, responding to WM_NCHITTEST with HTTRANSPARENT (a similar effect to that which WS_EX_TRANSPARENT achieves) can get the system to keep on passing the mouse message down the stack until it finds a target.
OK friends, finally I did some crazy things to make it happen. but its not very efficient, like using DirectX directly for drawing.
What I dis:
Used (WS_EX_TRANSPARENT | WS_EX_LAYERED | WS_EX_ TOOLWINDOW) and () on CreateWindowEx
After creating the window, removed (WS_EX_DLGMODALFRAME | WS_EX_CLIENTEDGE | WS_EX_STATICEDGE) from window styles, and also removed (WS_EX_DLGMODALFRAME | WS_EX_CLIENTEDGE | WS_EX_STATICEDGE | WS_EX_APPWINDOW) from extended window styles.
This gives me a window with no borders and its also now shown in the taskbar. also the hittest is passed to whatever that is behind my window.
Subclassed the window procedure of the other window and got the
WM_CLOSE,WM_DESTROY, to send the WM_CLOSE or WM_DESTROY respectively to my window
WM_SIZE,WM_MOVE, to resize and move my window according to the other window
WM_LBUTTONUP,WM_RBUTTONUP,WM_MBUTTONUP, to make my window brought to the top, and still keep focus on the other window, so that my window doesn't get hidden behind the other window
Made the DirectX device have two passes:
In the first pass it draws all the elements in black on top of a white background and copy the backbuffer data to an another surface (so it give a binary image of black & white).
In the second pass it draws the things normally.
Another thread is created to keep making the window transparency by reading that black & white surface, using the SetWindowRgn() function.
This is working perfectly, the only thing is it's not very good at making things transparent.
And the other issue is giving alpha blending to the drawn objects.
But you can easily set the total alpha (transparency) using the SetLayeredWindowAttributes() function.
Thanks for all the help you guys gave, all the things you guys told me was used and they guided me, as you can see. :)
The sad thing is we decided not to use this method because of efficiency problems :(
But I learned a lot of things, and it was an awesome experience. And that's all that matters to me :)
Thank You :)
You can make a hole in the parent window using SetWindowRgn.
Also, just because it is not your window doesn't mean you can't make it a layered window.
http://msdn.microsoft.com/en-us/library/ms997507.aspx
Finally, you can take control of another window by using subclassing - essentially you substitute your Wndproc in place of theirs, to handle the messages you wish to handle, then pass the remainder to their original wndproc.
I have a CFrameWndEx with several docked CDockablePanes but I can't seem to get notified when the size of the docked pane is changed (so I can resize my other windows accordingly). Tried Spy++ to check for messages, but custom draw seems to be the only one (which doesn't seem appropriate) and also tried overriding RecalcLayout, but that is not called under this circumstance. OnSize doesn't work because the size of the frame itself is not changed. Any ideas?
(Ps: I'm pretty sure it's possible because I used to have a splitter window as the 'client' area, and it would resize itself magically when the panes were resized)
OK this is a bit weird, but I had the exact same question, searched on Google, then saw that I had answered this question over a year ago but completely misunderstood what the question was about :)
Anyway for reference of future Google using people, the answer to this question is to override virtual void CFrameWndEx::EAdjustDockingLayout(HDWP hdwp) and do any resizing of client controls there. To get the client area after the hiding/closing/whatever of panes, use m_dockManager.GetClientAreaBounds(). My AdjustDockingLayout looks like this (m_View is the child window that is supposed to fill the whole client area regardless of the state of any docking panes, adjust as needed):
void CMainFrame::AdjustDockingLayout(HDWP hdwp)
{
CFrameWndEx::AdjustDockingLayout(hdwp);
if (m_View.GetSafeHwnd()) {
CRect rectUsable = m_dockManager.GetClientAreaBounds();
m_View.MoveWindow(rectUsable);
}
}
I think the issue is that the 'content' of the CFrameWndEx is itself a window, and in that window live the 'main content' windows. Check with Spy++ for the window hierarchy and if any of the child windows of the CFrameWndEx (other than the dockable panes) do get message when they are resized. Basically when docking panes are docked, the CFrameWndEx resizes its children, so you'd have to detect it there and (if required) reflect the message back to the CFrameWndEx if that's really where you need it.
Alternatively, maybe I'm misunderstanding and is what I described exactly what you're trying to do. In that case, I think there is something wrong with the way you add your window to the CFrameWndEx since that should handle the resizing itself. Is the parent of the child window set correctly to the CFrameWndEx when you create it?
Hello there I have issue with overlapping of child windows,I have created a software with menu driven interface( IDR_MAINFRAME - CFormView
etc) and upon clicking one of the menu items another child-window appears( Dialog based ) where I do the calculations as a normal
calculator.Now if I open any other entry say conversion of metrics which is also in menu entry then on overlapping with any other such
window the background windows gets horribly disfigured and if i move about the calculator or the metrics conversion calculator randomly
they get disfigured and its a mess.Also I have put up a bitmap image on the background.Upon moving the calculator the background image also
gets erased.
Please let me know about how to handle this issue.I have googled and found that handling of paint messages or WM_ERASEBKGND helps ..but I
have tried this piece of code which just doesn't help in OnEraseBkGnd();
BOOL COfficesoftDlg::OnEraseBkgnd(CDC* pDC)
{
// TODO: Add your message handler code here and/or call default
CRect Rect;
GetClientRect(Rect);
//ClientToScreen(&Rect);
//this->ScreenToClient(&Rect);
this->InvalidateRect(Rect);
return CDialog::OnEraseBkgnd(pDC);
}
how can i achieve the smooth overlapping of different windows like a notepad overlapping a word document or even a calculator or even a VC6
IDE in my project.
Please explain it with an example .I am just a newbie and I need to understand in detail...thanks and regards
Override OnEraseBkgnd and return true so it stops erasing the background you're painting. Returning TRUE says that you've done the work. If you simply call the base class implementation, it's going to do this for you, and you'll lose the background until it gets a chance to paint.
You're not getting paint messages to the parent window for some reason. Make sure you're calling the modal in the correct manner. DoModal() works fine. Make sure you're not just creating the modal and showing it.
If your windows are children on the same dialog/window and they overlap or you have children on either dialog/window, make sure that you use clipchildren and clipsiblings (if children on a window overlap). Otherwise they'll get to paint in any order they choose artifacting all over the place.
Ensure that you're painting to memory and bitblting back to your dialog, otherwise you'll get a flashing effect.
Currently it is floating on top of my rendered window, i dont think thats good for few reasons:
1) i waste rendering time for rendering stuff that isnt visible.
2) it must be rendered every frame again when i wouldnt be updating the whole statusbar every frame anyways.
So how i could create a window where it leaves space for my statusbar and none of my OpenGL stuff could be rendered in that area?
At this moment i just adjust my viewports in a way that creates empty space for statusbar, but it causes some problems in my current way of doing things. i would have to make my code look much more messier to make it work.
http://www.gamedev.net/community/forums/topic.asp?topic_id=291682
Edit: Its not a simple question to answer. If you don't know what a child window is under Win32 then you may be in a much better position. However asking someone to give you a full explanation of the windows windowing system is no mean feat.
Here is an overview:
Basically you need to create a child window which can be done using CreateWindow to create a window with the WS_CHILD style and with its hWndParent parameter set to the window handle you want the new window to be a child of.
When you created the window you will have, necessarily, create a window procedure When you call DispatchMessage from your message pump (The Loop that does a Get/PeekMessage and then dispatches the messages is the message pump). Inside the window procedure you can then switch on the message type and handle each message sent to your window.
From here you can handle things like setup. Your initial window will have either a WM_CREATE or a WM_INITDIALOG (Depending on what type of window you create). It is from there that you need to create the child windows (Don't forget to call ShowWindow to make them visible!!). From this point you can then set up the DirectX device to be attached to the child window handle (HWND).
Furthermore if you want to be able to re-size the window then you ALSO need to take into account the WM_SIZE mesage. However I'd strongly recommend trying to get the rest working before even beginning to look into this as it gets very complicated as you will need to destroy and re-create your DirectX device so that it is the right size.
Anyway thats just a simple overview. I hope it helps!
One way may be to make your "rendered window" and "statusbar" both children of a containing window, and to add some code for the WM_SIZE message for that containing window to position the children so they don't overlap.
I would like to send some keystrokes from a C++ program into another window.
For that reason I would like to have the user select the target window similar to how it is done in the Spy++ utility that comes with Visual Studio (drag a crosshair cursor over target window and have target window highlighted by a frame).
How is this dragging and selecting done in Windows? I am completely lost as to where I might start to look for a mechanism to implement this feature.
Here's how it's usually done:
Capture the mouse using SetCapture. This will cause all mouse messages to be routed toward your app's window.
Handle the WM_MOUSEMOVE message. In your handler code, grab the window underneath the mouse using WindowFromPoint. That will get you the HWND of the window the mouse is currently over.
Now that you've got the window, you need a device context (HDC). You can get one using GetWindowDC for the specified window.
Now you can draw into the DC using typical GDI functions.
There are some things you have to look out for - cleanly erasing the selection rectangle and so forth, but that's one way to do it.
You could also draw into a screen DC to do this, but in any case you'll need the window handle in order to get the window rect.
If you Google around Spy++ source code you'll see a few examples of this technique.
Formers answers are wrong.
Spy++ source code has been given on G. Groups for years (see mainly Win32 api ng news://194.177.96.26/comp.os.ms-windows.programmer.win32)