⬆️ ⬇️

And one-click screenshots (C #) again

Synopsis



Not so long ago I began to study C # and very soon the experiments turned into a desire to write some easy, simple, but at the same time useful and convenient application. The idea of ​​a program designed to quickly take screenshots and automatically upload them to hosting was gradually born. I did not find any analogues that met my requirements, so I decided to do it myself, and after that one good person gave the idea to write an article about it.



The essence



So what does my program do?



Difficulties



And now the part which, probably, will seem obvious and banal to someone, and can help someone. Even with the development of such a small application, as it turned out, it is impossible to avoid difficult moments.



Upload image to hosting


The first thing I encountered was an error using the hosting API: the image was loaded, but the last few kilobytes of the file had disappeared. Initially I used the following code, found among the examples of using the API on the hosting itself:

using System; using System.IO; using System.Net; using System.Text; namespace ImgurExample { class Program { static void Main(string[] args) { PostToImgur(@"C:\Users\ashwin\Desktop\image.jpg", IMGUR_ANONYMOUS_API_KEY); } public static void PostToImgur(string imagFilePath, string apiKey) { byte[] imageData; FileStream fileStream = File.OpenRead(imagFilePath); imageData = new byte[fileStream.Length]; fileStream.Read(imageData, 0, imageData.Length); fileStream.Close(); string uploadRequestString = "image=" + Uri.EscapeDataString(System.Convert.ToBase64String(imageData)) + "&key=" + apiKey; HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create("http://api.imgur.com/2/upload"); webRequest.Method = "POST"; webRequest.ContentType = "application/x-www-form-urlencoded"; webRequest.ServicePoint.Expect100Continue = false; StreamWriter streamWriter = new StreamWriter(webRequest.GetRequestStream()); streamWriter.Write(uploadRequestString); streamWriter.Close(); WebResponse response = webRequest.GetResponse(); Stream responseStream = response.GetResponseStream(); StreamReader responseReader = new StreamReader(responseStream); string responseString = responseReader.ReadToEnd(); } } 


There were errors in the code, but even after fixing them, the problem did not disappear. After a long and painful search for errors and a lot of tried and tested options, I came to the hypothesis that the file may be cut off after encoding due to the slashes used in base64. They may have been interpreted as escape characters, but it was already too lazy to find out exactly: I would have to catch a sniffer about what was going on the network (everything was fine in the debugger up to streamWriter.Write (uploadRequestString)), compare base64 sequences, and so on .P. On the Internet, this problem was not specifically covered, but there were a couple of posts that were also suspected of slashes.



In the end, I used the second version of the code found on StackOverflow :

 using (var w = new WebClient()) { var values = new NameValueCollection { { "key", "433a1bf4743dd8d7845629b95b5ca1b4" }, { "image", Convert.ToBase64String(File.ReadAllBytes(@"hello.png")) } }; byte[] response = w.UploadValues("http://imgur.com/api/upload.xml", values); Console.WriteLine(XDocument.Load(new MemoryStream(response))); }"> 


He was already working like a clock, it only took to adapt it to his needs - the function was to return only the link, and not the entire answer.

')

Hotkeys


The second difficulty arose with hotkeys. Everywhere it is proposed to intercept global hotkeys by hanging the hook with the RegisterHotKey function, and then redefining WndProc and already perceive the message in it. It would seem, what could be the difficulty here? The difficulty arose in the fact that my application is windowless (although WinForms), therefore, there is neither a window handle for transmission to RegisterHotKey, nor the window itself, in which WndProc could be redefined. After intense smoking, the manuals revealed that it is not necessary to transfer the descriptor - in this case, the messages will be sent not to the window, but to the stream that caused RegisterHotKey. The first part of the problem was solved, but there was still nothing to catch the message itself. After a couple more glasses of coffee, I found a solution for this problem: Application.AddMessageFilter () . In order to use it, you need to implement a "filter" of messages, in my case, he caught WM_HOTKEY and called the appropriate procedure for pushing back in the context of the application. There were no more obstacles to the development.



Fin



The application, of course, freeware and source I also decided to make open . Comments left in those parts of the code, which, in my opinion, are not obvious by themselves. There is no localization support, the interface language is English. The application is written in VS2010 under .NET 4.0, no third-party libraries were used. The icon was found at iconfinder.com . I do not pretend to the uniqueness of the idea, the program was written to get a hand in the process of which I ran into certain tasks and described their solution in the article.



UPD. Filled the binaries separately so that you can use without downloading the entire repository: ScreenPaste.exe

Source: https://habr.com/ru/post/132541/



All Articles