Meus Projetos

.NET CORE: API para conversão de moedas – Yahoo Currency

Yahoo Currency

Salve galera. Na verdade, eu já havia feito uma postagem sobre isso no passado. Mas decidi reescrever algumas partes do código e atualizar o projeto (de Portable Class Library) para uma Class Library(.NET CORE 2) que é multi plataforma.

O funcionamento é o mesmo, a diferença principal fica pelo suporte à assincronicidade permitindo que você use métodos async e use await.

Esse é mais um projeto livre e open source que estou disponibilizando no meu GITHUB.

Os códigos estão sumarizados(documentados) e acompanham um Demo em WPF.

Abaixo uma pequena porção de código:

        ///

        /// O código abaixo é um exemplo simples de como usar os webservices de moeda de forma assíncrona
        /// 

        /// 
        public static async Task AsyncExample()
        {
            HL.YahooCurrency.Currency currency = new HL.YahooCurrency.Currency();

            //VOCÊ DEVE INCLUIR A LINHA ABAIXO OBRIGATORIAMENTE
            //É de extrema importância que você use o método WaitLoad() para aguardar a inicialização desse objeto, que ocorre de forma assíncrona
            await currency.WaitLoad();

            //Seleciona a moeda de origem
            currency.SourceUnit = currency.Units.ElementAt(0);
            //Seleciona a moeda de destino, para a qual se quer converter um valor
            currency.OutputUnit = currency.Units.ElementAt(1);
            //Dá um valor para conversão
            currency.SourceValue = 2.32f;
            //Mostra o valor convertido para a moeda de destino
            System.Diagnostics.Debug.WriteLine(currency.OutputValue);
        }

        ///

        /// O código abaixo é um exemplo simples de como usar os webservices de moeda de forma síncrona(normal)
        /// 

        public static void SynchronousExample()
        {
            HL.YahooCurrency.Currency currency = new HL.YahooCurrency.Currency();

            //VOCÊ DEVE INCLUIR A LINHA ABAIXO OBRIGATORIAMENTE
            //É de extrema importância que você use o método WaitLoad() para aguardar a inicialização desse objeto, que ocorre de forma assíncrona
            //Ao invés de usar await, você pode usar o método .Wait() em contextos síncronos.
            //Dessa forma, a thread em execução irá ser bloqueada por algumas frações de tempo, até que o carregamento dos dados seja feito completamente
            //Normalmente, isso deverá tomar cerca de 1 segundo, mas em conexões de internet mais lentas, pode levar até 6. Ou seja, a interface de usuário irá ficar bloqueada durante esse tempo
            currency.WaitLoad().Wait();

            //Seleciona a moeda de origem
            currency.SourceUnit = currency.Units.ElementAt(0);
            //Seleciona a moeda de destino, para a qual se quer converter um valor
            currency.OutputUnit = currency.Units.ElementAt(1);
            //Dá um valor para conversão
            currency.SourceValue = 2.32f;
            //Mostra o valor convertido para a moeda de destino
            System.Diagnostics.Debug.WriteLine(currency.OutputValue);
        }

Gostou?

Detalhe, esse objeto YahooCurrency pode ser usado diretamente no XAML, pois ele implementa a interface INotifyPropertyChanged, permitindo que seja feito Data Bindings. Quando usando em XAML ele irá operar, por padrão, de forma assíncrona. Você deverá utilizar a propriedade IsLoading para exibir alguma mensagem de carregamento para o usuário (enquanto os dados são baixados) e/ou desabilitar os controles da interface.

Isso tudo que mencionei acima está implementado no exemplo em WPF que acompanha a API.

Chega de papo, aí está o link:

GitHub – HerbertLausmann/HL.YahooCurrency: .NET C# Multiplatform wrapper for Yahoo Currency Web Service. Convert between over 100 different currencies.

Lembrando, que como ela é escrita sob os padrões do .NET STANDARD 2, você poderá usa-la no Xamarin, Mono e etc.

Um abraço!

Anúncios

.NET CORE: API de previsão do tempo – Yahoo Weather

Surprise modafocas!

Queridos colegas, amigos, parceiros, compatriotas, conterrâneos, irmãos!

Nesse post venho apresentar-vos a minha API (escrita em C#/.NET CORE2) para previsão do tempo.

Ela é, basicamente, uma ponte em C# para o WebService de clima do Yahoo. Com ela você consegue obter muitas informações sobre o clima numa dada região, como por exemplo:

  1. Horário do nascer e pôr do sol
  2. Umidade e pressão atmosférica
  3. A sensação térmica, direção e velocidade do vento
  4. As temperaturas máxima e mínima previstas para a previsão
  5. Previsão do dia atual e dos 9 dias à frente

O webservice do yahoo, originalmente, retorna apenas os resultados em inglês. Mas eu adicionei suporte à globalização e assim ela emite os textos da previsão (Ex: Parcialmente Nublado, Chuvoso) em português.

Vale destacar que, sendo uma api escrita para o .NET CORE, ela pode ser usada em múltiplas plataformas, incluindo o XAMARIN e o MONO.

Ela também implementa a interface INotifyPropertyChanged podendo ser usada tanto em código (C#/VB.NET, whatever) quanto no XAML com Data Binding.

Saliento, também, que implementei suporte assíncrono. Você pode fazer umas coisinhas assim:

            YahooWeather weather = await YahooWeather.LoadAsync("New York city");
            Console.WriteLine(weather.Condition.Text);

Bacana né?

Isso tudo disponibilizado gratuitamente e com código aberto no GITHUB:

GitHub – HerbertLausmann/HL.YahooWeather: A .NET C# Multiplatform wrapper for the Yahoo Weather API

Divirta-se!
That’s all folks!

Criando um ícone personalizado para seu Aplicativo Windows – DICA

Icon Pro

Criando um ícone a partir de um arquivo SVG

GitHub – HerbertLausmann/HL.IconPro

Fala galera, beleza?!

Neste post eu venho lhes (re)apresentar minha ferramenta open source para criação de ícones para o Windows.

Como vocês podem ver acima, no GIF, é bem simples!! Basta selecionar uma imagem (PNG ou SVG), selecionar os tamanhos que irão para dentro do ícone, e pronto! Só salvar!

(mais…)

WPF & Win Forms: Capturar um controle para uma imagem – C#

Fala galera,

As vezes, okay, muito raramente, aliás, eu nem mesmo tenho ideia de qual seja a utilidade disso, precisamos capturar um controle de nosso aplicativo, e “salva-lo” para uma Imagem.

Isso é possível, no Win Forms e de forma bem fácil no WPF.
Criei uma classe para fazer a captura no Win Forms, e outra classe para fazer a captura no WPF. A diferença? Você vê a seguir:

WPF:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace HerbertLausmann.Wpf
{
    class VisualToBitmap
    {
        public static System.Windows.Media.Imaging.BitmapSource Render(System.Windows.Media.Visual Visual, int Resolution = 96)
        {
            System.Windows.Media.Imaging.RenderTargetBitmap render;
            double width, height;
            int pixelWidth, pixelHeight;
            width = (double)Visual.GetValue(System.Windows.FrameworkElement.ActualWidthProperty);
            height = (double)Visual.GetValue(System.Windows.FrameworkElement.ActualHeightProperty);
            pixelWidth = Convert.ToInt32((width / 96) * Resolution);
            pixelHeight =  Convert.ToInt32((height / 96) * Resolution);
            render = new System.Windows.Media.Imaging.RenderTargetBitmap(
                pixelWidth, pixelHeight, Resolution, Resolution,
                System.Windows.Media.PixelFormats.Pbgra32);
            render.Render(Visual);
            return render;
        }
    }
}

Win Forms:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;

namespace HerbertLausmann.WinForms
{
    class HandleToBitmap
    {
        /// <summary>
        /// Gera um Bitmap diretamente do hWnd correspondente à Janela/Controle
        /// </summary>
        /// <param name="hWnd"></param>
        /// <returns></returns>
        public static System.Drawing.Bitmap RenderHwnd(IntPtr hWnd)
        {
            IntPtr hDC = USER32.GetDC(hWnd);
            USER32.RECT WndRect = new USER32.RECT();
            USER32.GetWindowRect(hWnd, out WndRect);

            IntPtr capHDC = GDI32.CreateCompatibleDC(hDC);
            IntPtr capBMP = GDI32.CreateCompatibleBitmap(hDC, WndRect.Width(false), WndRect.Height(false));

            if (capBMP == IntPtr.Zero)
            {
                USER32.ReleaseDC(hWnd, hDC);
                GDI32.DeleteDC(capHDC);
                return null;
            }

            IntPtr prvHDC = (IntPtr)GDI32.SelectObject(capHDC, capBMP);
            GDI32.BitBlt(capHDC, 0, 0, WndRect.Width(false), WndRect.Height(false), hDC, 0, 0, GDI32.SRCCOPY);
            GDI32.SelectObject(capHDC, prvHDC);

            System.Drawing.Bitmap bmp = System.Drawing.Bitmap.FromHbitmap(capBMP);

            USER32.ReleaseDC(hWnd, hDC);
            GDI32.DeleteDC(capHDC);
            GDI32.DeleteObject(capBMP);

            return bmp;
        }
        /// <summary>
        /// A grosso modo, essa função tira um Print Screen da tela e recorta a imagem para as proporções da janela/controle.
        /// </summary>
        /// <param name="hWnd"></param>
        /// <returns></returns>
        public static System.Drawing.Bitmap RenderFromDesktop(IntPtr hWnd)
        {
            IntPtr hDC = USER32.GetDC(USER32.GetDesktopWindow());
            USER32.RECT WndRect = new USER32.RECT();
            USER32.GetWindowRect(hWnd, out WndRect);

            IntPtr capHDC = GDI32.CreateCompatibleDC(hDC);
            IntPtr capBMP = GDI32.CreateCompatibleBitmap(hDC, WndRect.Width(), WndRect.Height());

            if (capBMP == IntPtr.Zero)
            {
                USER32.ReleaseDC(hWnd, hDC);
                GDI32.DeleteDC(capHDC);
                return null;
            }

            IntPtr prvHDC = (IntPtr)GDI32.SelectObject(capHDC, capBMP);
            GDI32.BitBlt(capHDC, 0, 0, WndRect.Width(), WndRect.Height(), hDC, WndRect.X(), WndRect.Y(), GDI32.SRCCOPY);
            GDI32.SelectObject(capHDC, prvHDC);

            System.Drawing.Bitmap bmp = System.Drawing.Bitmap.FromHbitmap(capBMP);

            USER32.ReleaseDC(USER32.GetDesktopWindow(), hDC);
            GDI32.DeleteDC(capHDC);
            GDI32.DeleteObject(capBMP);

            return bmp;
        }
        /// <summary>
        /// Gera um Bitmap correspondente à área cliente da Janela/Controle
        /// </summary>
        /// <param name="hWnd"></param>
        /// <returns></returns>
        public static System.Drawing.Bitmap RenderClientArea(IntPtr hWnd)
        {
            IntPtr hDC = USER32.GetDC(hWnd);
            USER32.RECT WndRect = new USER32.RECT();
            USER32.GetClientRect(hWnd, out WndRect);

            IntPtr capHDC = GDI32.CreateCompatibleDC(hDC);
            IntPtr capBMP = GDI32.CreateCompatibleBitmap(hDC, WndRect.Width(false), WndRect.Height(false));

            if (capBMP == IntPtr.Zero)// if no compatible bitmap
            {
                USER32.ReleaseDC(hWnd, hDC); //   release window context
                GDI32.DeleteDC(capHDC); //   delete capture context
                return null; //   return null bitmap
            }

            IntPtr prvHDC = (IntPtr)GDI32.SelectObject(capHDC, capBMP);
            GDI32.BitBlt(capHDC, 0, 0, WndRect.Width(false), WndRect.Height(false), hDC, WndRect.X(false), WndRect.Y(false), GDI32.SRCCOPY);
            GDI32.SelectObject(capHDC, prvHDC);

            System.Drawing.Bitmap bmp = System.Drawing.Bitmap.FromHbitmap(capBMP);

            USER32.ReleaseDC(hWnd, hDC);
            GDI32.DeleteDC(capHDC);
            GDI32.DeleteObject(capBMP);

            return bmp;
        }
        private class GDI32
        {
            public const int SRCCOPY = 13369376;

            [DllImport("gdi32.dll", EntryPoint = "DeleteDC")]
            public static extern IntPtr DeleteDC(IntPtr hDc);

            [DllImport("gdi32.dll", EntryPoint = "DeleteObject")]
            public static extern IntPtr DeleteObject(IntPtr hDc);

            [DllImport("gdi32.dll", EntryPoint = "BitBlt")]
            public static extern bool BitBlt(IntPtr hdcDest, int xDest,
                int yDest, int wDest, int hDest, IntPtr hdcSource,
                int xSrc, int ySrc, int RasterOp);

            [DllImport("gdi32.dll", EntryPoint = "CreateCompatibleBitmap")]
            public static extern IntPtr CreateCompatibleBitmap(IntPtr hdc,
                int nWidth, int nHeight);

            [DllImport("gdi32.dll", EntryPoint = "CreateCompatibleDC")]
            public static extern IntPtr CreateCompatibleDC(IntPtr hdc);

            [DllImport("gdi32.dll", EntryPoint = "SelectObject")]
            public static extern IntPtr SelectObject(IntPtr hdc, IntPtr bmp);

            [DllImport("gdi32.dll", CharSet = CharSet.Auto, SetLastError = true, ExactSpelling = true)]
            public static extern int GetDeviceCaps(IntPtr hDC, int nIndex);
        }
        private class USER32
        {
            public const int SM_CXSCREEN = 0;
            public const int SM_CYSCREEN = 1;

            [DllImport("user32.dll", EntryPoint = "GetDesktopWindow")]
            public static extern IntPtr GetDesktopWindow();

            [DllImport("user32.dll", EntryPoint = "GetDC")]
            public static extern IntPtr GetDC(IntPtr ptr);

            [DllImport("user32.dll", EntryPoint = "GetSystemMetrics")]
            public static extern int GetSystemMetrics(int abc);

            [DllImport("user32.dll", EntryPoint = "GetWindowDC")]
            public static extern IntPtr GetWindowDC(Int32 ptr);

            [DllImport("user32.dll", EntryPoint = "ReleaseDC")]
            public static extern IntPtr ReleaseDC(IntPtr hWnd, IntPtr hDc);

            [DllImport("user32.dll", EntryPoint = "GetWindowRect")]
            public static extern IntPtr GetWindowRect([In] IntPtr hWnd, out RECT lpRect);

            [DllImport("user32.dll", EntryPoint = "GetClientRect")]
            public static extern IntPtr GetClientRect([In] IntPtr hWnd, out RECT lpRect);

            [StructLayout(LayoutKind.Sequential)]
            public struct RECT
            {
                int left;
                int top;
                int right;
                int bottom;

                public int X(bool autoScale = true)
                {
                    if (autoScale)
                        return (int)Math.Round(left * getScalingFactor());
                    else
                        return left;
                }

                public int Y(bool autoScale = true)
                {
                    if (autoScale)
                        return (int)Math.Round(top * getScalingFactor());
                    else
                        return top;
                }
                public int Width(bool autoScale = true)
                {
                    if (autoScale)
                        return (int)Math.Round(Math.Abs(right - left) * getScalingFactor());
                    else
                        return (int)(Math.Abs(right - left));                    
                }

                public int Height(bool autoScale = true)
                {
                    if (autoScale)
                        return (int)Math.Round(Math.Abs(bottom - top) * getScalingFactor());
                    else
                        return (int)(Math.Abs(bottom - top));
                }
            }

            [DllImport("gdi32.dll")]
            static extern int GetDeviceCaps(IntPtr hdc, int nIndex);

            public enum DeviceCap
            {
                VERTRES = 10,
                DESKTOPVERTRES = 117,
            }

            public static float getScalingFactor()
            {
                IntPtr desktop = GetDC(GetDesktopWindow());
                int LogicalScreenHeight = GetDeviceCaps(desktop, (int)DeviceCap.VERTRES);
                int PhysicalScreenHeight = GetDeviceCaps(desktop, (int)DeviceCap.DESKTOPVERTRES);

                float ScreenScalingFactor = (float)PhysicalScreenHeight / (float)LogicalScreenHeight;
                USER32.ReleaseDC(GetDesktopWindow(), desktop);
                return ScreenScalingFactor; // 1.25 = 125%
            }
        }
    }
}

Como você pode ver, a diferença é que o WPF oferece uma opção nativa, enquanto que no Win Forms temos que lidar com interoperabilidade na API do Windows.

Um pequeno exemplo de uso para o WPF:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace WPF_Control_to_Image
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void btnRender_Click(object sender, RoutedEventArgs e)
        {
            BitmapSource bmp = VisualToBitmap.Render(MainBorder);
            Microsoft.Win32.SaveFileDialog dialog = new Microsoft.Win32.SaveFileDialog();
            dialog.Filter = "Imagem PNG(*.png)|*.png";
            if(dialog.ShowDialog() == true)
            {
                System.Windows.Media.Imaging.PngBitmapEncoder encoder = new PngBitmapEncoder();
                encoder.Frames.Add(BitmapFrame.Create(bmp));
                System.IO.FileStream fs = new System.IO.FileStream(dialog.FileName, System.IO.FileMode.Create);
                encoder.Save(fs);
                fs.Close();
            }
        }
    }
}

E um para o Win Forms:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace HWND_To_Image
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void btnRender_Click(object sender, EventArgs e)
        {
            Bitmap bmp = HandleToBitmap.RenderClientArea(this.Handle);
            SaveFileDialog dialog = new SaveFileDialog();
            dialog.Filter = "Imagem PNG (*.png)|*.png";
            dialog.AddExtension = true;
            if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                bmp.Save(dialog.FileName, System.Drawing.Imaging.ImageFormat.Png);
            }
        }

    }
}

E isso é tudo. Vou disponibilizar o download da Solution com os exemplos para Win Forms e WPF:

Control to Image.zip

Até a próxima, pessoal!!!

WPF Splash Screen

Fala aí pessoal!!! Depois de certo tempo parado, estou retornando com um belo post.

Vou disponibilizar o projeto de uma Splash Screen em C# WPF bem simples, mas com alguns efeitos bem atrativos e elegantes. Bom, os efeitos vocês só vão ter noção quando rodarem o executável. Segue uma imagem estática:

Splash Screen WPF

A Splash Screen pertence a um programa fictício para edição vetorial denominado Vector Art…

Segue link do projeto:

WPF Splash Screen.zip

Bom, por hoje é só pessoal! Espero que gostem.

OBS: A imagem de fundo do Splash eu peguei na net e dei umas retocadas, a logo Vector Art foi criada por mim…