I tried capturing live thumbnail of running applications using these codes:
http://community.bartdesmet.net/blogs/bart/archive/2006/10/05/4495.aspx
I have successfully captured some applications except those borderless fullscreen windows.
I am actually trying to capture a UWP application that plays a video in a fullscreen mode and integrate the thumbnail into my application. I don't need to get a bitmap image of it, I just need to display in real-time.
I tried changing the values of
GWL_STYLE
WS_VISIBLE
WS_BORDER
but none of it works.
When trying to Alt+Tab windows, the Windows 10 DWM can handle it and displays the live thumbnail, so I believe this could work with some little modifications on the code.
Thanks!
I checked the window styles for the example uwp application in full screen with Spy++.
Styles were normal so then i hardcoded window handle and it worked. After a moment of debugging, it turned out that the EnumWindows method did not return this window, so it did not matter what styles were checked.
So I looked for a problem with this method and there are many topics, for example:
EnumWindows function in Win10 enumerates only desktop apps
Instead of using EnumWindows, get all windows using this method and insert your filter logic for your desired window handler
IntPtr thisWindow = IntPtr.Zero ;
IntPtr desktopWindow = GetDesktopWindow();
while (true)
{
if (desktopWindow == IntPtr.Zero)
break;
IntPtr nextWindow = FindWindowEx(desktopWindow, thisWindow, null, null);
if (nextWindow == IntPtr.Zero)
break;
/** your code here **/
thisWindow = nextWindow;
}
Related
Try to capture the MEmu emulator's window with bitblt() (or Printwindow() - have the same issue) but can't grab the content of the window, only the background picture.
Captured window:
Original window:
Tried with every program related window handlers manually (spy++, inspect etc..) and programmatically (enumwindows()).
Also tried with SRCCOPY and SRCCOPY | CAPTUREBLT options without success.
Do you have any suggestion what else to try or the Bitblt function doesn't work with every kind of windows and need to use different technique?
My program (C#) is a taskbar and in its menu I can launch applications, compatible XP to 8.1. I would like to start any applications with a specific window's size, because few applications (OpenOffice, LibreOffice...), start flattened when i launch them for the first time.
I've tested to maximize this window with ShellExecute with ShowCommands.SW_MAXIMIZE parameter:
ShellExecute(IntPtr.Zero, "open", executablePath, executableParam, "", ShowCommands.SW_MAXIMIZE);
But when I clicked on the "restore" button of the window, there is the same problem, the window is flattened.
While the "restored" size isn't configured by manual resizing, the used value is specific for each applications.
Instead of ShellExecute, I use CreateProcess to specify a size :
const uint NORMAL_PRIORITY_CLASS = 0x0020;
STARTUPINFO si = new STARTUPINFO();
si.dwY = 50;
si.dwX = 50;
si.dwXSize = 200;
si.dwYSize = 800;
si.dwFlags = 0x00000006; //STARTF_USESIZE + STARTF_USEPOSITION
PROCESS_INFORMATION pi = new PROCESS_INFORMATION();
CreateProcess(programPath, programParams, IntPtr.Zero, IntPtr.Zero, true, NORMAL_PRIORITY_CLASS, IntPtr.Zero, null, ref si, out pi);
But there is one problem, we can launch an other OpenOffice/LibreOffice process with File->New->... In this case the application isn't launch by my program so my default size isn't applied.
I've checked the Windows Registry before and after changing this value, two keys are changed :
[HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\ComDlg32\OpenSavePidlMRU\reg]
[HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\UserAssist\{CEBFF5CD-ACE2-4F4F-9178-9926F41749EA}\Count]
These keys contains hexa values (first key) :
before :
"MRUListEx"=hex:00,00,00,00,04,00,00,00,01,00,00,00,05,00,00,00,03,00,00,00,02,\00,00,00,ff,ff,ff,ff
after :
"MRUListEx"=hex:01,00,00,00,00,00,00,00,04,00,00,00,05,00,00,00,03,00,00,00,02,\00,00,00,ff,ff,ff,ff
It isn't understandable to me, so I'm still searching if exist a programmatic way to specific window size of an application/all applications or an other specification to set into the Windows Registry. I'm not searching a solution to resize or move a window already launched like SetWindowPos.
But many websites explain there's just one solution to define the window's size: "drag the window to the size, then close the window and restart it"
http://help.wfu.edu/public/computers/standard-load-software/windows-7---set-default-window-size
http://www.tomshardware.co.uk/forum/28659-45-change-default-window-size
This answer is the final solution or there is a way to do it programmatically?
Thanks in advance.
EDIT :
Actually, when a window is restored, I resize only the first time until the user kill it.
My program keeps every window's handle in an object with a boolean initialized to false to specify if my window has been resized. I use GetForegroundWindow then with GetWindowPlacement I check if WINDOWPLACEMENT.flags == WindowPlacementFlag.WPF_NONE and if my boolean is always egals to false in that case I use GetWindowRect and SetWindowPos to set a specific size with the same position and assign my boolean to true.
I think is a good solution, but I loose the saved position by user (I can do it when window's size is under a specific value but the problem still there) and we seen the resizing...
This problem usually occurs because the coder used GetWindowPos to get the position to save, but the window is closed while minimised, so the position is a tiny window hidden by the taskbar. This is then the position which is saved. The correct method is to use GetWindowPlacement to save the position.
You could enumerate all top-level windows, check GetWindowPlacement to see which are visible and restored but with an inappropriate size or position (e.g. off-screen, too small). Then you could call SetWindowPlacement to move those windows back to a reasonable minimum size on-screen.
In all likelihood when they save their position again they will save the new position.
Don't poll though. Instead make it a utility that the user can run when they need to. (You will probably need an exceptions list too - some utilities might create an off-screen window on purpose.)
I am playing a video using IVMRWindowlessControl9 i.e. WindowlessControl w/ VMR-9. When I initially had difficulty setting the video up, I noticed many examples found online had this piece of code in the Window's Paint handler:
IntPtr hdc = e.Graphics.GetHdc();
int hr = 0;
hr = windowlessCtrl.RepaintVideo(this.Handle, hdc);
e.Graphics.ReleaseHdc(hdc);
My video is playing correctly yet I do not have the above code. What does the above code do and is there a point in using it?
In most cases you don't need to repaint the video explicitly because the video renderer does it automatically. Yes, if the hosting window needs - for any reason - to request forced replaint, such as as part of WM_PAINT window message handler, then RepaintVideo method is here at your service.
See more on MSDN, VMR Windowless Mode:
During playback, the application should notify the VMR of the
following Windows messages:
WM_PAINT: Call IVMRWindowlessControl::RepaintVideo to repaint the
image.
As to what it does:
if the video is being drawn using a destination colour key, then it paints the key colour into the destination window.
if the image is letterboxed, or part of it falls on another monitor, it will paint the parts that are not covered by the image.
So it may be that you won't see any difference if it is not done at all, if none of these things apply.
I found out the Yahoo Messenger window that notifies you when someone signs in or out is the only window that actually appears on top of a full screen movie or game and won't force you to exit full screen.
So my question is how can I find out what makes this window behave like this? I tried Spy++ but nothing interesting came up.
There are different ways to do this. Some video card drivers on older versions of windows will behave differently.
1) Grab the desktop hwnd and paint to it.
HWND hwnd = GetDesktopWindow();
HDC hdc = GetDC(hwnd);
RECT rect = {};
GetClientRect(hwnd, &rect); // dimensions of the primary monitor are rect.right,rect.bottom
// Use hdc to paint whatever you want to the screen
2) Just create a top-most window without a titlebar and use the WS_EX_TOPMOST style. Then draw whatever you want on it
CreateWindowEx(WS_EX_TOPMOST, ...);
Could be using the windows notification API (I don't have Yahoo messenger, so I'm not sure). Here's some more information about the notification area:
http://msdn.microsoft.com/en-us/library/aa511448.aspx
I'm writing a simple Windows Forms utility to screenshot either the entire screen or an active window and save the file. The winform has a button called 'Capture' that, when clicked, takes the screenshot.
I have the code entirely working for the entire screen but can't figure it out for the active window.
By my current code, if I select 'Active Window', it ends up Print Screening the application itself which isn't what I want.
Here's my code (under the Capture_Click method):
try
{
this.Hide();
bmpScreenshot = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height, PixelFormat.Format32bppArgb);
//bmpScreenshot = new Bitmap(this.Bounds.Width, this.Bounds.Height, PixelFormat.Format32bppArgb);
gfxScreenshot = Graphics.FromImage(bmpScreenshot);
if (AltPrint.Checked)
{
gfxScreenshot.CopyFromScreen(this.Bounds.X, this.Bounds.Y, 0, 0, this.Bounds.Size, CopyPixelOperation.SourceCopy);
}
else
{
gfxScreenshot.CopyFromScreen(Screen.PrimaryScreen.Bounds.X, Screen.PrimaryScreen.Bounds.Y, 0, 0, Screen.PrimaryScreen.Bounds.Size, CopyPixelOperation.SourceCopy);
}
bmpScreenshot.Save(SaveLocation, ImageFormat.Png);
number++;
}
In your button_Click method, to capture a window other than the one which is doing the capturing, the only possible way I can see is to make use of the user32 Windows API.
You will first need to platform invoke some methods like this:
[DllImport("user32.dll", SetLastError = true)]
private static extern int GetWindowLong(IntPtr hWnd, GetWindowLongNIndex nIndex);
I recommend www.pinvoke.net/ for more info about this.
Here is my own Window class (work in progress, but useable) which you are welcome to use as an example: http://pastebin.com/fj2tEaPY
Some useful properties in there for you are:
get AllWindows
get TaskbarWindows
set ForegroundWindow
You'll need to get the handle of your current window (use get ForegroundWindow, then the Handle property), then find the window which you want to capture the image of, perhaps using code similar to that in TaskbarWindows. Once you have the window, you will need to send the keypresses Alt + PrtScn (again maybe using user32 API, but I won't go into it.) Then use the static ForegroundWindow property to set the orignal window as the forground using the handle which you saved at the start.
Good luck!
As far as I can see your code uses the bounds of its own form to capture the "active" window. That is probably not what you intend.
If you want to use the mouse to "print" a window (and not hotkey which probably is easier to implement) you need to be able to from your own form let the user point to another window to capture. Here is an idea describing how to do that:
When the user presses the "Capture" button capture the mouse and initiate a drag operation.
Let the user drag the mouse (perhaps now having a "bullseye" or a "camera" cursor) to the window to capture.
When the user releases the mouse determine the window it was on top and use the location and size of this window to capture the correct pixels.
You will probably need to use P/Invoke to get information about all top-level windows on the desktop.
Note that "mouse capture" is very different from "screen capture". When an application "captures the mouse" it takes ownership of the mouse cursor and doesn't the ability to track the mouse even when it is moved outside the bounds of the window of the application.
Your comments seem to understand that once your app gets the focus (when you click on it) the other app has lost it and is no longer 'active'.
A possible alternative: your application gets a WM_SETFOCUS message when it gets focus. The wParam of that message is a handle to whichever window has just given up the focus -- and that window belongs to the app you want to capture.
Of course, that window will only be a subwindow or control, but you can figure out which app owns that button.
I ended up taking a different route.
I allow the user to resize my form window to cover exactly the area they need to screenshot, and then when they click the button, the form hides itself, takes a screenshot of the area it was covering and appears again. Contrary to my initial plan, I believe this will be more beneficial, as my targeted users (friends at an overclocking forum I'm part of) seldom take screenshots of just one window. They mostly need a couple of windows covered (temp monitoring, clockspeed monitoring, stability test etc.).
Thanks for all the answers guys. They definitely got me thinking, and made me realize what my options were.
Should anyone else need it, this is the code I use for the button that captures only part of the screen:
try
{
this.Hide();
Thread.Sleep(250);
bmpScreenshot = new Bitmap(this.Bounds.Width, this.Bounds.Height, PixelFormat.Format32bppArgb);
gfxScreenshot = Graphics.FromImage(bmpScreenshot);
gfxScreenshot.CopyFromScreen(this.Bounds.X, this.Bounds.Y, 0, 0, this.Bounds.Size, CopyPixelOperation.SourceCopy);
bmpScreenshot.Save(SaveLocation, ImageFormat.Png);
tbxStatus.AppendText(Environment.NewLine);
tbxStatus.AppendText(Environment.NewLine);
tbxStatus.AppendText("Screenshot saved at " + SaveLocation);
numSuffix++;
}
catch (Exception ex)
{
tbxStatus.AppendText(Environment.NewLine);
tbxStatus.AppendText(Environment.NewLine);
tbxStatus.AppendText("Unable to take screenshot. Exception: " + ex.ToString());
}
finally
{
this.Show();
}
You need to borrow the design of commercially available screen capturing apps, such as Psp. I think you need to use a 'hot' key to trigger the capturing of the active window. Instead of doing it on Capture_Click event. This way, you can hide your application's window so that it does not become the active window. Then when the user pushes the 'hot' key, you can capture it.
What about SendKeys?
Windows.Forms.SendKeys.Send("%{PRTSC}");
It will copy currently selected window in to Clipboard object.
Than calling
BitmapSource image = Clipboard.GetImage();
you can get your image back