It's a little hard to explain what I need but i'll try:
I need to write application (winform) which will be some kind of filter to image/other forms behind it. With one exception - all behind form should looks as is except of red (for example) color, which have to be replaced to any other specified color, white for example.
So let's imagine I have opened windows Word with few lines of text. With red and black letters.
So when i place my application above this text - it should "filter" red symbols and fill them to white.
So as i understand this task: i have to snap area behind the form, then process it (replace colors) and after draw this image on my form body.
Any links or keywords for solution?
UPD:
so - this is my final solution:
do form transparent (using TransparencyKey and BackColor properties)
place picturebox over the form
when we need to update image in picturebox - we replace current image with pictureBox1.Image = null;, then refreshing form with (this.Refresh()) and do new snapshot
thanks for all ;-)
UPD 2:
sample http://dl.dropbox.com/u/4486681/result.png
UPD 3:
here are sources
you can create a snapshot of the desktop using the following code:
public Bitmap CaptureScreen()
{
Bitmap b = new Bitmap(SystemInformation.VirtualScreen.Width, SystemInformation.VirtualScreen.Height);
Graphics g = Graphics.FromImage(b);
g.CopyFromScreen(0, 0, 0, 0, b.Size);
g.Dispose();
return b;
}
Replace the dimensions and position with the coordinates of your form. This way you get a bitmap of what's behind your form. Then you can do the color replacement on that bitmap.
Please note that due to settings like ClearType and other anti-aliasing mechanisms, you have to also take into account "intermediate pixels" when doing the color replacement. Otherwise things will look funny :-)
I don't know if this can be done at all (let's see what others answer :-).
You can get a handle to the screen device context, which gives you a bitmap of the screen.
HDC dc = GetDC(NULL);
(This is C++, you'll have to use P/Invoke, or create a mixed-mode library in C++)
Then you can redraw a region of the screen with your filtering process.
Now the problems start:
how do you know that the pixels in your interesting region has changed ?
if the region changes, are the changes visible or are they hidden by your own drawing.
You could have a button somewhere that hides your own app momentarily and shows it back when re-pressed, and filters the new content.
Good luck. Any possibility of sharing the user scenario ?
Related
I've got this topimage with alpha channel in it and I need to put this image over another background image, while the alpha channel from the top image stays intact obviously.
Now I've seen some tutorials with Canvas, but my project doesn't seem to recognize Canvas.
Anyone got an idea why I cant use Canvas or how to put those 2 images over each other?
Ok, I will try to answer: after loading the image, like this more or less, pseudocode:
Bitmap bmp = new Bitmap("MyCooolSemiTransparentImage.png");
bmp.MakeTransparent(colorHaveToBeRenderedTransparent);
colorHaveToBeRenderedTransparent is a color wich results non transparent after loading it into Bitmap object.
EDIT
if alphachannel is ok, here is a simple tutorial how to draw in image on WinForms:
msdn: DrawImage
Call method provided in yuor forms OnPaint override and you will get what you want.
Hope this helps.
Regards.
I hope you can help me with this problem, attached videos to explain in a simpler way.
First example
Panel (has a textured background) with labels (the labels have a png image without background)
Events: MouseDown, MouseUp and MouseMove.
As you will notice in the video to drag the label the background turns white panel and regains its background image when I stop dragging the label
Panel controls have a transparent background as property, but changing the background with any color, let the problem occurred related to the substance, I do not understand why this happens and how to fix less.
Second Example
Contains the above, with the only difference that the panel controls instead of having transparent background, I chose black color for that property
You have to use double buffer and you don't have to stop using an image on the background, you can have everything running smoothly.
You have a couple of ways to do this, the fast way (not enough most of the time) is to enable doublebuffer of the panel.
The "slow" but better way is to do your own Double Buffer using a Bitmap object as a buffer.
This example creates a "side buffer" and accepts an image as parameter and draws it using created buffer.
public void DrawSomething(Graphics graphics, Bitmap yourimage)
{
Graphics g;
Bitmap buffer = new Bitmap(yourimage.Width, yourimage.Height, graphics);
g = Graphics.FromImage(buffer);
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
g.DrawImage(yourimage, 0, 0);
graphics.DrawImage(buffer, 0, 0);
g.Dispose();
}
Call this on your OnPaint event.
BTW... this is just a double buffer example.
Cheers
Change DoubleBuffered to true for both form and panel. I think that should solve your problem.
this is totally normal, because System.Windows.Forms.Control based items were not designed to do this kind of advanced Graphics operations.
in fact the reason that this effect happens here, is that when you assign any value other than 255 to the alpha component of a control BackColor, the form does the following when you change the control size or position:
it sets the new control position
it redraws the parent control
it gets the background of the control's parent as an image
it draws acquired image into the control body to seem as if the control is transparent
the control body gets drawn on top of the previously drawn background
the control children are drawn
* this is is a simplified explanation for the sake of illustration to deliver the idea
steps 1, 2 are responsible for the flickering effect that you see.
but you have two ways to solve this,
-the first is some kinda advanced solution but it's very powerful, which is you would have to create a double buffered custom control that would be your viewport.
the second is to use WPF instead of windows forms, as WPF was designed exactly to do this kind of things.
if you can kindly provide some code, i can show you how to do both.
I am having trouble getting my Form background image to display correctly with a gradient transparency. That is, the edge of the image (or anywhere for that matter) has a fading or non-255 Alpha value. The result is that everywhere the Alpha is NOT 255 (or 0 - I can't remember) I see my background color. Here is a screen shot:
What I have in this setup is a 24bit bmp file with a green background that I'm trying to key out via the Form.TransparencyKey property:
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
Color key = ((Bitmap)this.BackgroundImage).GetPixel(0, 0);
this.TransparencyKey = key;
}
I have also tried setting the Form's BackColor property to the same key value but that did not make a difference.
I also tried saving my image as a png with transparency and keying out the entire form background but that didn't work either.
I know this is possible somehow, I've seen applications like Photoshop use this for a decade. I'm on WinXP Pro if that matters.
Anyone have experience with this and have an idea what step I'm missing or doing incorrectly?
The WinForms implementation of Form only permits a solid colour to be used as the transparency key. It's not possible to have varying levels of transparency.
Most apps with splash screens like yours take a screenshot of the desktop (within the bounds that their splash screen will occupy) and then composite their splash screen on top of this screenshot. They then display the resulting bitmap to the user, giving the impression of an alpha gradient.
I've had my share of failure time with exactly that.
I found that WinForms is simple weak at handling this.
Here is some solutions that you might find useful:
http://www.c-sharpcorner.com/UploadFile/scottlysle/XparentFormsCS10282007212944PM/XparentFormsCS.aspx
Link
http://www.vcskicks.com/splash-screen.php
How can I show something on screen wihtout using forms?
Actually, I want to show some text and images popping on screen.
EDIT: just like i said HERE
What you can do is to create a alphatransparent form that draws the PNG and position it at the correct location and bind move etc.
http://www.codeproject.com/KB/GDI-plus/perpxalpha_sharp.aspx
PerPixelAlphaForm transparentImageForm = new PerPixelAlphaForm();
transparentImageForm.SetBitmap(<IMAGE GOES HERE>,<OPACITY GOES HERE>);
//opacity is the opacity that the image will be drawn with, a value of 255 = all transparent parts will be alpha/transparent just as much as the original PNG etc..
and you can put a timer that calls SetBitmap and changes the Opacity to fade in/out the image on the screen
And you can generate the text (on the fly) in a nice way with code from THIS article
and pass that image to the SetBitmap of the AlphaTransparent form.
EDIT: OR GO TO WPF.
I don't think you can: a form is equivalent to a window, and Windows applications draw into a window and not directly onto the screen (unless perhaps it's the backgroun/wallpaper, which I don't know about).
I think that's overdoing it but XNA will allow you to draw to the screen, but it is meant to be used for games so you will have trouble fitting it to a normal application.
I am trying to take a screenshot of an application and I would like to make the parts of the rectangle that are not part of the applications region be transparent. So for instance on a standard windows application I would like to make the rounded corners transparent.
I wrote a quick test application which works on on XP (or vista/windows 7 with aero turned off):
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
Graphics g = e.Graphics;
// Just find a window to test with
IntPtr hwnd = FindWindowByCaption(IntPtr.Zero, "Calculator");
WINDOWINFO info = new WINDOWINFO();
info.cbSize = (uint)Marshal.SizeOf(info);
GetWindowInfo(hwnd, ref info);
Rectangle r = Rectangle.FromLTRB(info.rcWindow.Left, info.rcWindow.Top, info.rcWindow.Right, info.rcWindow.Bottom);
IntPtr hrgn = CreateRectRgn(info.rcWindow.Left, info.rcWindow.Top, info.rcWindow.Right, info.rcWindow.Bottom);
GetWindowRgn(hwnd, hrgn);
// fill a rectangle which would be where I would probably
// write some mask color
g.FillRectangle(Brushes.Red, r);
// fill the region over the top, all I am trying to do here
// is show the contrast between the applications region and
// the rectangle that the region would be placed in
Region region = Region.FromHrgn(hrgn);
region.Translate(info.rcWindow.Left, info.rcWindow.Top);
g.FillRegion(Brushes.Blue, region);
}
When I run this test app on XP (or Vista/Windows 7 with Aero off), I get something like this, which is great because I can eek an xor mask out of this that can be used later with BitBlt.
removed dead Imageshack link - Screenshot
Here is the problem, on Vista or Windows 7 with Aero enabled, there isn't necessarily a region on the window, in fact in most cases there isn't. Can anybody help me figure out some way to build a mask like this on these platforms?
Here are some of the approaches I have already tried...
1. Using the PrintWindow function: This doesn't work because it gives back a screenshot taken of the window with Aero off and this window is a different shape from the window returned with Aero on
2 Using the Desktop Window Manager API to get a full size thumbnail: This didn't work because it draws directly to the screen and from what I can tell you can't get a screenshot directly out of this api. Yeah, I could open a window with a pink background, show the thumbnail, take a screenshot then hide this temporary window but thats a horrible user experience and a complete hack I would rather not have my name on.
3. Using Graphics.CopyFromScreen or some other pinvoke variant of this: This doesn't work because I can't assume that the window I need information from is at the top of the z-order on the screen.
Right now, the best solution I can think of is to special case Aero on Windows 7 and Vista to manually rub out the corners by hard coding some graphics paths I paint out but this solution would suck since any application that performs custom skinning will break this.
Can you think of another or better solution?
If you are here, thanks for taking time to read this post, I appreciate any help or direction that you can offer!
If you are looking for a finished application, there is 7capture, which captures also the translucency, so images can be saved to PNG format for later compositing.
EDIT:
The original question and comments indicate you are looking to produce a region on Windows Vista/7 that you can then use to mask out parts the captured image, as is done with Windows XP and non-Aero UIs. Using a region is not going to give you the result you are looking for, since the window outline is not computed as a region, but as an image with variable transparency - RGBA. The Alpha channel in that image is your mask, but it's not an on-off mask like a region, but a gradual mask with a range of values from pixels being fully included to being fully masked out.
Although it uses undocumented APIs, the code at http://spazzarama.wordpress.com/2009/02/12/screen-capture-with-vista-dwm/ will capture to a RGBA buffer which you can then use to render or save the image with the shadow and other translucency effects intact.
In DwmCapture.cs Change
BackBufferFormat = Format.X8R8G8B8
to
BackBufferFormat = Format.A8R8G8B8
(X8->A8)
And you should then be able to access both the usual RGB data plus transparency from the captured buffer. This can then be saved as a PNG or other format with alpha-channel for composing.
Removed idea that is terrible but would have been awesome back in the '90s
You say that using the DWM API only allows you to capture directly to the screen... could you create a window offscreen (say, X = -100000px, Y = -100000px) but visible (maybe even hidden?) and draw the screenshot to it? Since when using the DWM each window has a backing texture, I'm thinking it might still get drawn fine even though the target isn't directly onscreen.
Also, if you want to go the DirectX route and access the actual DX texture backing the window, I found a few leads that might help (especially the first link):
http://spazzarama.wordpress.com/2009/02/12/screen-capture-with-vista-dwm/
http://channel9.msdn.com/forums/TechOff/251261-Help-Getting-the-shared-window-texture-out-of-DWM-/
http://web.archive.org/web/20080625183653/http://www.aeroxp.org/board/index.php?showtopic=6286
http://www.youtube.com/watch?v=hRTgFTMnT_U
Using Graphics.CopyFromScreen or some other pinvoke variant of this:
This doesn't work because I can't
assume that the window I need
information from is at the top of the
z-order on the screen.
If you know which window you need the information from, can you bring it to the front, call Graphics.CopyFromScreen, and then reset its z-index? I know from experience that Aero does odd things when items are in the background in order to make their glass interface work correctly (partial rendering etc). This may not be great UX; however, it would be a special case and used only when Aero is turned on.
You can take a look at the source code of AeroShot, as described on the main page, it can capture rounded edges and with the Aero Glass transparency effect and save it to a PNG file. It's written in C#.