In windows: I would like to know if it is possible (and if so, how) to make a program in C++ that displays images/text on the screen directly, meaning no window; if you are still confused about what I am after some examples are: Rocketdock and Rainmeter.
you can do it certainly without using Qt or any other framework. Just Win32 API helps you do that and internally, every framework calls these API so there is no magic in any of these frameworks
First of all, understand that no image or text can be displayed without a window. Every program uses some kind of window to display text or image. You can verify it using the Spy++ that comes with windows SDK. click the cross-hair sign, click the image or text you think is displayed without any windows. The Spy++ will show you the window it is contained in.
Now how to display such image or text that seems like not contained in any window. Well you have to perform certain steps.
Create a window with no caption bar, resize border, control box, minimize, maximize or close buttons. Use the CreateWindowEx() and see the various windows style WS_EX_XXX, WS_XXX for the desired window style.
Once the window is there you need to cut the window. Much like a cookie cutter. for this you need to define an area. This area is called region and you can define it using many functions like CreateEllipticRgn(), CreatePolygonRgn(), CreateRectRgn(), CreateRoundRectRgn() etc. all these functions return a HRGN which is the handle to the region. Elliptical or rectangle regions are OK as starter.
Now the last part. You have to cut the window like that particular region. Use the SetWindowRgn() function which requires a handle to your window and a handle to that region (HRGN). This function will cut the window into your desired shape.
Now for the image or text. Draw the image or text inside the window. I assume you must have cut the window according to your image, You just need to give window a face. so just draw the image either on WM_ERRASE BACKGROUND or WM_PAINT messages
Use the SetWindowPos() to move the window to the location you wish to on screen. If you have used correct parameters in CreateWindowEx() then this step is not necessary
You can set any further styles of windows using SetWindowLong() function.
Congratulations, you have your image displayed without using any windows ;)
Related
I have a simple c++ wIn32 program that allows you to paint over windows in Windows OS.
This program has a UI that lets a user to choose windows he wants to paint over.
The problem I'm facing is that if a user chooses a specific Microsoft PowerPoint window and than starts a slide show (by pressing 'F5' for example) than another new window is opened on full sceen and my program is unaware of it and does not paint over it.
I need to find out how may I identify this new window, assuming I can perform periodic polling on existing windows using EnumWindows method.
I have tryied using the methods GetAncestor & GetParent on the Slide Show window and on the PowerPoint window to see if they match but both of them return different HWND handle.
Moreover, a solution of identifying that a specific HWND handle is a PowerPoint Slide show window is not sufficient since if I have for example 2 instances of 2 different Power Point windows and the user has chosen to paint only over one of them, than I want to make sure that only if the chosen PowerPoint window is going to slide show window than I will paint over it. If the slide show window was started from the non-chosen PowerPoint window than I don't want to paint over it.
I create the bitmap first, and then the button and call button->Raise().
The button doesn't show up until I hover over it, and even though I'm supplying it with a transparent png as an image, the transparency is screwed up as can be seen here:
As Raise() documentation says, this function only works for the top level windows. Overlapping child windows are not supported by wxWidgets and won't work correctly under all platforms.
The closest you can do to what you want is to use a custom background on your parent window, which will, indeed, show behind your bitmap button.
First of all this is not MFC.
Here is a cropped version of the GUI I have been working on:
As you can see there is a bitmap image above the tab control (which uses the default window's handle), I will refer to it as "Blue Bitmap" I have no problems with it, it is functioning perfectly.
The problem I am having is setting another bitmap (from a bitmap file on disk) to the background of the child window (more specifically the tab control child window), replacing the grey colour. Here are some things I did to try and set the bitmap as the background for the child window (the tab).
1) I used the same method as was used to assign the blue bitmap to the window by first importing the bitmap using LoadImage like so:
index->hbmBitmapBanner = (HBITMAP)LoadImage(index->hInstance,L"Images\\horizontal.bmp",IMAGE_BITMAP,0,0,LR_LOADFROMFILE);
Then in the WM_PAINT message:
case WM_PAINT:
{
PAINTSTRUCT ps1;
if (BeginPaint(WINDOWHANDLE,&ps1))
{
HDC hdcBanner = CreateCompatibleDC(ps1.hdc);
HBITMAP hbmOldHorizontal = (HBITMAP)SelectObject(hdcBanner,index->hbmBitmapBanner); // banner
BitBlt(ps1.hdc,0,0,516,101,hdcBanner,5,0,SRCCOPY);
SelectObject(hdcBanner,hbmOldHorizontal);
DeleteDC(hdcBanner);
EndPaint(WINDOWHANDLE,&ps1);
}
break;
}
That code was successful in setting blue bitmap to the window, but not in setting the other bitmap into the window, (with the blue bitmap's variables substituted into, size and orientation changed as well of course). It simply did not display the bitmap on the screen, and the window remained unchanged, yet no functions failed. ALSO, when I swapped the file locations around, it loaded the bitmap into where the blue bitmap was, so there is definitely no failure in the loading function.
2) Using the above code, I tried changing the first argument of BeginPaint to the window handle of the tab control box, this proved yet again of no use, and the window remained unchanged. I also tried changing the first argument of BeginPaint to a child window which is displayed on the information tab, this caused the child window (which is a groupbox) to disappear, yet still no bitmap appeared on the window.
3) As a last resort I stupidly attempted to use this function on the child window
SetClassLongPtr(tab->hTabIndex[0],GCLP_HBRBACKGROUND,(DWORD)GetStockObject(BLACK_BRUSH));
And of course, it didn't work
If it is of any use, here is how I created the tabbing in my window:
TCITEM tie = {0};
tab->hTab = CreateWindowEx(0,WC_TABCONTROL,L"",WS_CHILD | WS_VISIBLE,0,101,600,400,
WINDOWHANDLE,NULL,(HINSTANCE)GetWindowLong(WINDOWHANDLE,GWLP_HINSTANCE),NULL
);
Is the main tab control, followed by inserting individual the tabs (i.e the information tab)
TCHAR pszTab1 [] = L"Information"; // tab1's text
tie.pszText = pszTab1; // the tab's text/caption
TabCtrl_InsertItem(tab->hTab, 0, &tie); // insert the tab
Additional info: The tab control, and the windows are working/interacting perfectly apart from this. I was testing/attempting this for only one tab, because I knew if it worked on one tab, then it would work on all the tabs, hence saving time.
I have Programming For Windows Fifth Edition, by Charles Petzold beside me as reference, and there is a rather large section on bitmaps, but he doesn't go into talking about loading a bitmap to a child window, the closest he gets is using a bitmap in a menu, which is completely different than a window.
I think that the issue here is that Windows Common Controls do not interact with your application via your main thread's window procedure but via their own (system-defined) window procedures.
So, for example, when your tab window redraws itself, it does not do so in response to a WM_PAINT message arriving at the window procedure defined in your code. You should be able to verify for yourself that this is so by examining the window handles of messages passed to your window procedure, eg WM_PAINT.
If you wish to 'tap into' the default behaviour of a common control you have to 'subclass' it (see here) but in my experience attempting to change the re-draw behaviour is generally problematic.
In the case of a tab control the best thing to do is create an array of child windows sized to the client area of the tab control and arrange that the one displayed at any one time corresponds to the tab that is selected.
If you're using C++ you might consider creating a base class to wrap these windows in which the background (bitmap) drawing is handled. You can then derive a series of wrappers to handle each individual tab. I've used exactly this approach in the past and it works well.
It may be helpful to bear in mind that the tabs of the tab control do not extend over the whole of the control's client area but are just literally the tabs themselves. I don't remember the details but I think they are handled internally by the control and that manipulating them in any way is rather trick, even when the control is subclassed - may be wrong about that.
Hope that helps.
Cheers, Ian.
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 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)