using draw = System.Drawing; ... draw.Image thumb = Browser.WebView.Capture(false); //The original image. using (MemoryStream stream = new MemoryStream()) { thumb.Save(stream, draw.Imaging.ImageFormat.Bmp); stream.Position = 0; stream.Seek(0, SeekOrigin.Begin); BitmapImage bi = new BitmapImage(); bi.BeginInit(); bi.StreamSource = stream; bi.CacheOption = BitmapCacheOption.OnLoad; bi.EndInit(); Thumbnail.Source = bi; //The image element. thumb.Dispose(); }
08 October 2014
WPF - Use a System.Drawing.Image as ImageSource
06 October 2014
.net - Discretely perform a mouse click
First the following Windows functions need to be imported. I've put these in a static class called "OS".
[StructLayout(LayoutKind.Sequential)] public struct Win32Point { public Int32 X; public Int32 Y; }; [DllImport("user32.dll")] public static extern bool GetCursorPos(ref Win32Point pt); [DllImport("user32.dll")] public static extern bool SetCursorPos(int x, int y); [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] public static extern void mouse_event(long dwFlags, long dx, long dy, long cButtons, long dwExtraInfo);
The control in question is hidden. On it's load event this takes place:
OS.Win32Point pos = new OS.Win32Point(); OS.GetCursorPos(ref pos); //Gets the current mouse position. int x = ((int)Left + (int)Width) - 220; int y = ((int)Top + (int)Height) - 35; OS.SetCursorPos(x, y); //Moves the mouse the where I need my click. Browser.Visibility = Visibility.Visible; //Makes the control visible. OS.mouse_event(0x02 | 0x04, 0, 0, 0, 0); //Performs the click. Task.Run(async delegate { //Introduces a short delay to avoid that the mouse moves back before the click occures. await Task.Delay(100); //.net framework 4.5 is needed to delay it like this. OS.SetCursorPos(pos.X, pos.Y); //Moves the mouse back to it's original position. });
23 July 2014
Math - Extract the RGB values from a long color
extension Int { func toColor() -> UIColor { let r = self % 256 let g = ((self - r) % 65536) / 256 let b = (self - g) / 65536 return UIColor(red: Float(r), green: Float(g), blue: Float(b), alpha: 1) } }
08 July 2014
C# - Bits to connect to a database
The connection string
In a web application, we pick this up in the web.config as follows:private static string ConnectionString { get { var cs = ConfigurationManager.ConnectionStrings["ConnStrConsult"]; if (cs != null) return cs.ConnectionString; else throw new Exception("Connection string not found."); } }
Retrieve data
This method takes an SQL SELECT statement and an optional number of parameters that are used in this statement. Also see LINQ on datatable for further processing of the retrieved data and Retrieve objects to retrieve an IEnumerable of model objects instead.private static DataTable Retrieve(string query, params object[] parameters) { try { var data = new DataTable(); using (var adapter = new OdbcDataAdapter(query, ConnectionString)) { SetParameters(adapter.SelectCommand, parameters); adapter.Fill(data); } return data; } catch (OdbcException ex) { if (ex.Message.Contains("database not found")) throw new Exception("Could not find database."); else throw; } } private static void SetParameters(OdbcCommand command, params object[] parameters) { if (command != null && parameters != null && parameters.Length > 0) { int i = 0; while (i < parameters.Length) { command.Parameters.AddWithValue("p" + i, parameters[i] ?? DBNull.Value); i++; } } }
Execute statements
This one takes an INSERT, UPDATE or DELETE statement with optional parameters and executes it on the database.private static object Execute(string query, params object[] parameters) { using (var connection = new OdbcConnection(ConnectionString)) using (var command = new OdbcCommand(query, connection)) { SetParameters(command, parameters); connection.Open(); return command.ExecuteScalar(); } }
02 June 2014
Windows XP - Cannot validate SSL TCP connection
While I was working on my email client in .net, using a TcpClient, I tested it on a computer that ran Windows XP SP2, and it failed to connect to the IMAP servers. It always returned the error The remote certificate is invalid according to the validation procedure. It worked fine on a Windows 7 laptop.
It turned out that the certificate could not be validated on an XP SP2 machine because it doesn't have the updated cryptography API called Cryptography Next Generation or CNG.
The only solution for me was to update to XP SP3. Once installed, I ran the email client again and it all worked perfectly.
22 May 2014
C# - Asynchronious methods with a callback
The method
public void GetMailBoxes(Action<Exception, List<MailBox>> method) { BackgroundWorker worker = new BackgroundWorker(); worker.DoWork += (object sender, DoWorkEventArgs e) => { e.Result = Imap.Instance.GetMailBoxes(); }; worker.RunWorkerCompleted += (object sender, RunWorkerCompletedEventArgs e) => { method(e.Error, mMailBoxes); }; worker.RunWorkerAsync(); }
Calling the method
account.GetMailBoxes((Exception ex, ListmailBoxes) => { if (ex != null) { Program.Handle(ex); } else { lstMailBoxes.DataSource = mailBoxes; } });
05 May 2014
IMAP - Retrieving data from a mail box
Connect
This opens a secured TCP connection to the server.StringBuilder result = new StringBuilder(); TcpClient connection = new TcpClient("imap.telenet.be", 993); SslStream stream = new SslStream(connection.GetStream(), false); stream.AuthenticateAsClient("imap.telenet.be"); StreamWriter writer = new StreamWriter(stream); StreamReader reader = new StreamReader(stream); result.AppendLine(reader.ReadLine());
Login
This logs you in. Always flush the command to actualy send it. All commands are sent in this fashion. Notice how each command starts with a different tag to identify it. These are usually generated with an auto-increment.writer.WriteLine(@"e001 LOGIN myemail@telenet.be mypassword"); writer.Flush(); CheckResponseOk("Login");
CheckResponseOk
This function retrieves the response on a command and checks whether it is possitive. This is for commands that don't return data, like connect and login. These return "OK" if they succeed.private void CheckResponseOk(string context) { string[] response = GetResponse(); if (!response.Last().Contains("OK")) throw new ApplicationException(context + " failed:\n" + string.Join("\n", response)); }
GetResponse
This function retrieves the response on a command. A response can be multiple lines. The last line always starts with the tag that was sent in the command.private string[] GetResponse(int logLines = -1) { Listresult = new List (); string tag = GetTag(false); string line = mReader.ReadLine(); int loggedLines = 0; while (!line.StartsWith(tag)) { result.Add(line); if (logLines < 0 || loggedLines < logLines) { mLogWriter.WriteLine(line); loggedLines++; } line = mReader.ReadLine(); } result.Add(line); if (logLines < 0 || loggedLines < logLines) { mLogWriter.WriteLine(line); loggedLines++; } return result.ToArray(); }
Other commands
- e002 SELECT INBOX selects the INBOX mail box.
- e003 SEARCH ALL retrieves all of the mail ID's. It's also possible to pass a query.
- e004 FETCH 1:10 (RFC822.SIZE ENVELOPE FLAGS) retrieves the size, envelope and flags of mail ID 1 through 10.
- e005 FETCH 1 BODY[TEXT] retrieves the body of mail ID 1.
- e006 CLOSE closes the selected mail box.
- e007 LOGOUT logs you off again.
Disconnect
writer.Close(); reader.Close(); stream.Close(); connection.Close();
10 March 2014
MVC - Resize an image
public void FormatPicture(HttpPostedFileBase file) { WebImage image = new WebImage(file.InputStream); if (image.Width > 85 || image.Height > 85) { int w = image.Width; int h = image.Height; if (w > h) { w = 85; h = image.Height * w / image.Width; } else { h = 85; w = image.Width * h / image.Height; } image.Resize(w, h); } image.Save(PictureFilepath); }The HttpPostedFileBase file comes from the view model and contains the uploaded image from the file control. In this example the image is resized to a maximum of 85 pixels, with the smaller dimension interpolated, and stored.
MVC - Download a file from an action
[Authorize] public ActionResult Picture() { if (App.GetCurrentUser().HasPicture) { //Finds out if the current user has a picture in App_Data/UserPictures. io.FileStream stream = io.File.OpenRead(App.GetCurrentUser().PictureFilepath); byte[] data = new byte[stream.Length]; stream.Read(data, 0, data.Length); stream.Close(); stream.Dispose(); return File(data, MediaTypeNames.Application.Octet, App.GetCurrentUser() + ".jpg"); } else { return null; } }The file is read into memory and the streamed back as an action result of type File. This principle also allows for files to be generated on the fly without them ever being stored on disc.
06 February 2014
MVC - Multiple submit buttons with distinct actions
In standard MVC, a view (page) can only have one action. You retrieve (GET) the view and submit it (POST). Therefore only one POST-action can be triggered, and if you want multiple buttons in a single view you need to dive into the form values to differentiate between them and use a switch or something inside the POST-action.
It turns out there is a way to have multiple submit buttons that each trigger a distinct action though. You can put an attribute on the two POST-actions that lets MVC pick the right one depending on which button you clicked. It is important to know though that you can't have the standard submit action you would normally have:
[HttpPost] public ActionResult Index() { }Remove this action if you have it. It will cause a conflict between this standard action and the one for the submit button.
The attribute
First you need to create the following attribute class. I called it Submit:public class SubmitAttribute : ActionNameSelectorAttribute { public override bool IsValidName(ControllerContext controllerContext, string actionName, MethodInfo methodInfo) { if (actionName == methodInfo.Name) return true; else return controllerContext.RequestContext.HttpContext.Request[methodInfo.Name] != null; } }
The actions
Second, create the actions for - in this example - two submit buttons:[Submit] [HttpPost] public ActionResult SaveProjectFilter(ProjectModel model) { } [Submit] [HttpPost] public ActionResult DeleteProjectFilter(ProjectModel model) { }Notice I decorated both actions with my Submit attribute.
The buttons
Third, put these two submit buttons in the view:<input type="submit" name="SaveProjectFilter" value="@Dictionary.Get("Save")" class="icon-save" /> <input type="submit" name="DeleteProjectFilter" value="@Dictionary.Get("Delete")" class="icon-delete" />Notice how the buttons' names match their respective actions. This is the key to the whole thing! This is actually it. If you click any of the two buttons the proper action will execute.