Getting image from clipboard - black when screenshots appear? - c#

I am using WPF to display the image in the clipboard. This works fine when going to Paint and copying something there, but when I hit "Print screen" to take a screenshot, the output there is just a black image, that has the same dimensions as the screen.
How come?
The code for taking data from the clipboard is as follows (yes, I do in fact want to use raw API calls).
...
case CF_BITMAP:
BitmapSource source = null;
System.Drawing.Bitmap finalBitmap = null;
IntPtr destinationHdc = CreateCompatibleDC(IntPtr.Zero);
if (destinationHdc != null)
{
IntPtr sourceHdc = CreateCompatibleDC(IntPtr.Zero);
if (sourceHdc != null)
{
if (OpenClipboard(MainWindow.Handle))
{
IntPtr sourceBitmap = GetClipboardData((uint)clipboardFormat);
SelectObject(sourceHdc, sourceBitmap);
BITMAP bmp;
GetObject(sourceBitmap, Marshal.SizeOf(typeof(BITMAP)), out bmp);
IntPtr destinationBitmap = CreateCompatibleBitmap(destinationHdc, bmp.bmWidth, bmp.bmHeight);
SelectObject(destinationHdc, destinationBitmap);
BitBlt(destinationHdc, 0, 0, bmp.bmWidth, bmp.bmHeight, sourceHdc, 0, 0, 0x00CC0020);
CloseClipboard();
finalBitmap = System.Drawing.Bitmap.FromHbitmap(destinationBitmap);
}
DeleteDC(sourceHdc);
}
DeleteDC(destinationHdc);
}
if (finalBitmap != null && ((LastData == null || !(LastData is System.Drawing.Bitmap)) || !finalBitmap.EqualsTo((System.Drawing.Bitmap)LastData)))
{
source = BitmapToSource(finalBitmap);
if (LastData == null || source != LastData)
{
tile = new ImageTile();
(tile as ImageTile).Image.Source = source;
tile.RawData = finalBitmap;
}
}
return tile;
...

I ended up using the inbuilt framework method instead, Clipboard.GetImage(). The WPF version of it seems to work better than the Windows Forms one.

Related

How to load a transparent Tile Image on Windows 10 Credential Provider?

I am trying to load an image as a tile on a Windows 10 Credential Provider that was originally written to work on Windows 7. But now the images on Windows 10 are a circle instead of a square and would like to have the rounded edges transparent. I have used a BMP image but that did not work, so I have tried loading a PNG file that is transparent on the edges but this also does not work.
I have used the following code to load a PNG file and the file loads but it only shows it as either black or white background but not transparent (the resourceId is a resource of an image that is PNG).
HBITMAP LoadPNG(HINSTANCE hInst, int resourceId)
{
HGLOBAL hGlobal;
LPSTREAM pStream;
HBITMAP tBmp = NULL;
ULONG_PTR token = 0;
Gdiplus::GdiplusStartupInput input = NULL;
Gdiplus::GdiplusStartup(&token, &input, NULL);
if (token != 0)
{
HRSRC hRsrc = FindResource(hInst, MAKEINTRESOURCE(resourceId), TEXT("PNG"));
HGLOBAL hGlob1 = LoadResource(hInst, hRsrc);
int size = SizeofResource(hInst, hRsrc);
hGlobal = GlobalAlloc(GMEM_FIXED, size);
LPVOID resPtr = LockResource(hGlob1);
memcpy(hGlobal, resPtr, size);
FreeResource(hGlob1);
CreateStreamOnHGlobal(hGlobal, true, &pStream);
Gdiplus::Bitmap* bmp = new Gdiplus::Bitmap(pStream, false);
bmp->GetHBITMAP(Gdiplus::Color::Transparent, &tBmp);
Gdiplus::GdiplusShutdown(token);
}
return tBmp;
}
Originally I was using this to load a BMP file but BMP does not really support transparency (in this case the IDB_TILE_IMAGE is a BMP file) :
HRESULT GetBitmapValue(DWORD dwFieldID, HBITMAP* phbmp)
{
HRESULT hr;
if ((SFI_TILEIMAGE == dwFieldID) && phbmp)
{
HBITMAP hbmp = LoadBitmap(HINST_THISDLL, MAKEINTRESOURCE(IDB_TILE_IMAGE));
if (hbmp != NULL)
{
hr = S_OK;
*phbmp = hbmp;
}
else
{
hr = HRESULT_FROM_WIN32(GetLastError());
}
}
else
{
hr = E_INVALIDARG;
}
return hr;
}
Any ideas on how to make a transparent tile image on Windows 10 Credential Provider so I can show an image with rounded transparent edges? What I am looking for is not a square image to be loaded as a tile but an actual circular image to match the Microsoft images that are out of the box from Windows 10.

A problem in Xamarin.forms with an icon.png "Cannot decode image. The image must be a Bitmap" [duplicate]

I'm working with Xamarin in the part of Xamarin.Forms i need to convert a file ("image.png") to a Bitmap because when project run its enter in "break mode" and show me this message "Java.Lang.IllegalArgumentException: 'Failed to decode image. The provided image must be a Bitmap.'". So i tried to convert the file in many ways like:
1_ Using methods from System.Drawing.Bitmap but it's show this exception "This operation is not supported in this platform"
2_ Cannot use Android.Graphics because i'm working in xamarin.forms not in xamarin.android.
3_ I tried to convert the "image.png" into a base64 or byte[] array and then into a bitmap but the problem is the same like in first problem because to convert from byte[] array or base64 to a Bitmap i have use methods from System.Drawing.Bitmap.
4_ I tried using the library SkiaSharp but i don't have success because i don't found so much information about how to convert .png to SKBitmap and then convert SKBitmap to Bitmap (even i don't know if this is possible).
5_ Finally i converted "image.png" to a "image.bmp" with an app and use the file .bmp in my project but it doesn't work too.
the "image.png" i have to save in a string variable, well that's the idea.
If you have a solution with SkiaSharp o whatever i will glad
EDIT
here is a part of my code, i just save in a variable the image
Icon = "pin_blue.png";
//i can't use a path because in xamarin you have many size from the same
//image for the different size of the screen
EDIT 2 This is my method to show the pins in google maps
private void ShowPins(List<PointsOfInterest> resultPointsOfInterest)
{
if (resultPointsOfInterest != null && resultPointsOfInterest.Any())
{
var location = Geolocation.GetLastKnownLocationAsync();
PointsOfInterest position = new PointsOfInterest();
if (location != null)
{
position.ccsm0166latitud = location.Result.Latitude;
position.ccsm0166longitud = location.Result.Longitude;
}
else {
position = resultPointsOfInterest.First();
}
//Distance = Distance.FromKilometers(new Random().Next(23,35));
Distance = Distance.FromKilometers(3);
Position = new Position(position.ccsm0166latitud, position.ccsm0166longitud);
PinsFiltered= Pins = new List<PinCustom>(resultPointsOfInterest.Select(
x => new PinCustom()
{
Position =
new Position(x.ccsm0166latitud, x.ccsm0166longitud),
Address = x.ccsm0166direccion,
Label = x.ccsm0166nombre,
Type = PinType.Place,
TypePointOfInterest = x.ccsm0166tipositio,
IconBM = Int32.Parse(x.ccsm0166tipositio) == (int)PointOfInterestType.branch ? PinCustom.ConvertToBitmap("pin_blue.png") :
Int32.Parse(x.ccsm0166tipositio) == (int)PointOfInterestType.branch ? "pin_blue.png" :
Int32.Parse(x.ccsm0166tipositio) == (int)PointOfInterestType.branchWithExtendedHours ? "pin_black.png" :
Int32.Parse(x.ccsm0166tipositio) == (int)PointOfInterestType.branchWithExtendedHours2 ? "pin_black.png" :
Int32.Parse(x.ccsm0166tipositio) == (int)PointOfInterestType.branchWithExtendedHours3 ? "pin_black.png" :
Int32.Parse(x.ccsm0166tipositio) == (int)PointOfInterestType.selfServiceTerminal ? "pin_green.png" :
Int32.Parse(x.ccsm0166tipositio) == (int)PointOfInterestType.atmServBox ? "pin_yellow.png" : string.Empty
}).ToList());
}
else
{
Pins = new List<PinCustom>();
}
}
This is the class Pin where i save the image
public class PinCustom : Pin
{
public string TypePointOfInterest { get; set; }
public string Icon { get; set; }
public Bitmap { get; set; }
//Here i create this variable to save a bitmap but i don't know if i do the things well
}
this is the icon .png i want to show in googlemaps
Pin Blue Image
To open your file and convert it to byte array:
string directory = Path.Combine(Android.OS.Environment.ExternalStorageDirectory.AbsolutePath, Android.OS.Environment.DirectoryDownloads);
// or your image directory, just replace it
var stream = File.OpenWrite(Path.Combine(directory, "image.png"));
byte[] buff = ConvertStreamToByteArray(stream);
stream.Close();
public static byte[] ConvertStreamToByteArray(Stream stream)
{
byte[] byteArray = new byte[16 * 1024];
using (MemoryStream mStream = new MemoryStream())
{
int bit;
while ((bit = stream.Read(byteArray, 0, byteArray.Length)) > 0)
{
mStream.Write(byteArray, 0, bit);
}
return mStream.ToArray();
}
}
then, to pass this byte array to SKBitmap:
SKBitmap bmp = SKBitmap.Decode(buff);
EDIT:
If you want to try without ConvertStreamToByteArray():
byte[] buff = null;
stream.Write(buff, 0, buff.Length);
This Write will depend of the type of your stream. In this example, I'm using FileStream.
EDIT 2:
string resourceID = "image.png";
Assembly assembly = GetType().GetTypeInfo().Assembly;
using (Stream stream = assembly.GetManifestResourceStream(resourceID))
{
resourceBitmap = SKBitmap.Decode(stream);
SKBitmap bmp = SKImage.FromBitmap(resourceBitmap);
}
and then you can use this bitmap to draw and fill your SKCanvas:
canvas.DrawBitmap(bmp, 0, 0);
Use ffmpeg
command for this: ffmpeg -i image.png image.bmp
i have 5 types of pins (pins are the image .png) when i put the pins
in format .png
if you want to custom the pins in your map, you can simply use Custom Renderers to achieve this.
The icon used to represent a marker can be customized by calling the MarkerOptions.SetIcon method. This can be accomplished by overriding the CreateMarker method, which is invoked for each Pin that's added to the map:
protected override MarkerOptions CreateMarker(Pin pin)
{
var marker = new MarkerOptions();
marker.SetPosition(new LatLng(pin.Position.Latitude, pin.Position.Longitude));
marker.SetTitle(pin.Label);
marker.SetSnippet(pin.Address);
marker.SetIcon(BitmapDescriptorFactory.FromResource(Resource.Drawable.pin));
return marker;
}
If you want to display different icons, you can refer to the following code:
protected override MarkerOptions CreateMarker(Pin pin)
{
var marker = new MarkerOptions();
marker.SetPosition(new LatLng(pin.Position.Latitude, pin.Position.Longitude));
marker.SetTitle(pin.Label);
marker.SetSnippet(pin.Address);
var customPin = (Element as CustomMap).CustomPins.FirstOrDefault(p => p.Position == pin.Position);
if (customPin != null)
{
if (customPin.IconType == "corporate")
{
marker.SetIcon(BitmapDescriptorFactory.FromResource(Resource.Drawable.corporate));
}
else if (customPin.IconType == "pickup")
{
marker.SetIcon(BitmapDescriptorFactory.FromResource(Resource.Drawable.bus));
}
}
return marker;
}
For more, check:Customizing the Marker.

Determine if two images are identical

Is there any way to determine if two images are identical?
I want to change an image every time my timer ticks (animation).
But, I need to see which image is displaying, so is there any way to compare 2 images
to do what I want?
if (myImage.Flags == (Image.FromFile(#"Images/Enemy.png").Flags))
{
myImage = Image.FromFile(#"Images/Enemy2.png");
}
else
{
myImage = Image.FromFile(#"Images/Enemy.png");
}
Don't compare the images, just maintain the index of the current image in a variable.
Here's an example that works for any number of images:
private int _currentImageIndex;
private string[] _imagePaths =
{
"Images/Enemy.png",
"Images/Enemy2.png",
"Images/Enemy3.png",
};
...
void NextImage()
{
// Dispose the current image
Image img = pictureBox1.Image;
pictureBox1.Image = null;
if (img != null)
img.Dispose();
// Show the next image
_currentImageIndex = (_currentImageIndex + 1) % _imagePaths.Length;
string path = _imagePaths[_currentImageIndex];
pictureBox1.Image = Image.FromFile(path);
}
I'd try to compare ImageLocation. Although it doesn't work if you have your pictures as resources.
if (PictureBox1.ImageLocation == PictureBox2.ImageLocation)
{
}
See my question:
Dynamically changing image in a picturebox
Here goes simple answer.
In case of just 2 images, use flag
// field, true if enemy2.png is loaded
bool _image2;
// somewhere
if(_image2)
{
myImage = Image.FromFile(#"Images/Enemy.png");
_image2 = false;
}
else
{
myImage = Image.FromFile(#"Images/Enemy2.png");
_image2 = true;
}

Put a metafile or bitmap in needed picturebox

Well I have two pictureboxes. First one is for metafile image, second is for bitmap image. When the picture is in clipboard after buttom has been pressed I need to check out the format of the picture and put it in the appropriate picturebox. I did next but for some reason it doesnt work. Help me out please.
if (iData.GetDataPresent(DataFormats.MetafilePict)== true )
try
{
if (ClipboardFunctions.OpenClipboard(this.Handle))
{
if (ClipboardFunctions.IsClipboardFormatAvailable(CF_ENHMETAFILE) != 0) //CF_ENHMETAFILE=14
{
IntPtr intptr = ClipboardFunctions.GetClipboardData(CF_ENHMETAFILE);
pictureBox2.SizeMode = PictureBoxSizeMode.Zoom;
pictureBox2.Image = new System.Drawing.Imaging.Metafile(intptr, true);
}
}
}
finally { ClipboardFunctions.CloseClipboard(); }
else if (iData.GetDataPresent(DataFormats.Bitmap) == true)
pictureBox1.Image = Clipboard.GetImage();

Fatal Execution Error on Browser.ReadyState [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Troubleshooting .NET “Fatal Execution Engine Error”
My code is throwing a Fatal Execution Error. The exact error is this:
The runtime has encountered a fatal error. The address of the error
was at 0xed40646c, on thread 0x2044. The error code is 0xc0000005.
This error may be a bug in the CLR or in the unsafe or non-verifiable
portions of user code. Common sources of this bug include user
marshaling errors for COM-interop or PInvoke, which may corrupt the
stack.
I'm not using unsafe user code as far as I know.
The code which is causing the issue is this one:
WebClient client = new WebClient();
string pageHtml = client.DownloadString(url);
browser.ScriptErrorsSuppressed = true;
browser.DocumentText = pageHtml;
do
{
Application.DoEvents();
} while (browser.ReadyState != WebBrowserReadyState.Complete); //CRASH OCCURS HERE
Now here's the kicker. This code is beign run on a loop. Every so often, it gives this error. Sometimes its on the 1000th run. Last time it was on the 5545th run. It seems to be very random indeed.
How do I solve this problem? Or how can I get more information to solve it?
My solution is based on How to wait until WebBrowser is completely loaded in VB.NET?
What u have to do is to add bool _pageReady variable to Completed event.
void web_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
var urlCurrent = e.Url.ToString();
var browser = (WebBrowser)sender;
if (!(urlCurrent.StartsWith("http://") || urlCurrent.StartsWith("https://")))
{
// in AJAX
}
if (e.Url.AbsolutePath != browser.Url.AbsolutePath)
{
// IFRAME
}
else
{
// DOCUMENT IS LOADED 100%
Debug.WriteLine("DocumentCompleted " + DateTime.Now.TimeOfDay.ToString());
_pageReady = true; // Here it goes!!!! :)
try
{
mshtml.IHTMLDocument2 docs2 = (mshtml.IHTMLDocument2)web.Document.DomDocument;
mshtml.IHTMLDocument3 docs3 = (mshtml.IHTMLDocument3)web.Document.DomDocument;
mshtml.IHTMLElement2 body2 = (mshtml.IHTMLElement2)docs2.body;
mshtml.IHTMLElement2 root2 = (mshtml.IHTMLElement2)docs3.documentElement;
// Determine dimensions for the image; we could add minWidth here
// to ensure that we get closer to the minimal width (the width
// computed might be a few pixels less than what we want).
int width = Math.Max(body2.scrollWidth, root2.scrollWidth);
int height = Math.Max(root2.scrollHeight, body2.scrollHeight);
//get the size of the document's body
Rectangle docRectangle = new Rectangle(0, 0, width, height);
web.Width = docRectangle.Width;
web.Height = docRectangle.Height;
//if the imgsize is null, the size of the image will
//be the same as the size of webbrowser object
//otherwise set the image size to imgsize
Rectangle imgRectangle;
if (imgsize == null) imgRectangle = docRectangle;
else imgRectangle = new System.Drawing.Rectangle() { Location = new System.Drawing.Point(0, 0), Size = imgsize.Value };
//create a bitmap object
__Bitmap = new Bitmap(imgRectangle.Width, imgRectangle.Height);
//Rectangle resolution = Screen.PrimaryScreen.Bounds;
//__Bitmap.SetResolution(resolution.Width, resolution.Height);
//get the viewobject of the WebBrowser
IViewObject ivo = web.Document.DomDocument as IViewObject;
using (Graphics g = Graphics.FromImage(__Bitmap))
{
//get the handle to the device context and draw
IntPtr hdc = g.GetHdc();
ivo.Draw(1, -1, IntPtr.Zero, IntPtr.Zero,
IntPtr.Zero, hdc, ref imgRectangle,
ref docRectangle, IntPtr.Zero, 0);
g.ReleaseHdc(hdc);
}
//var randomPart = System.IO.Path.GetRandomFileName();
//__Bitmap.Save(#"D:\t" + randomPart + ".png");
if (CropRectangle != null)
{
if (CropRectangle.Width > 0 && CropRectangle.Height > 0)
{
Bitmap bmpCrop = __Bitmap.Clone(CropRectangle, __Bitmap.PixelFormat);
__Bitmap = bmpCrop;
}
}
//__Bitmap.Save(#"D:\cropped" + randomPart + ".png");
bitmapPointer = __Bitmap.GetHbitmap();
}
catch
{
//System.Diagnostics.Process.GetCurrentProcess().Kill();
}
}
}
and also to do something like
public void HtmlCapture2()
{
try
{
if (web == null)
web = InitWebBrowser();
web.Navigate(_navigateURL);
try
{
while (_pageReady == false) // YEAH!!!!!! IT IS WORKING!!!!
{
System.Windows.Forms.Application.DoEvents();
}
//Thread.Sleep(WaitForWebsite); --- It works but....
//while (web.ReadyState != WebBrowserReadyState.Complete) --- it gives an ERROR
// System.Windows.Forms.Application.DoEvents();
}
catch (Exception)
{
}
}
catch (Exception)
{
}
}

Categories