Sem categoria

.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

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: Classe EditableBitmapImage (Implementando método SetPixel e GetPixel) – C#

Olá galera!!

Neste post, apresento à você uma implementação bem simples e funcional dos métodos SetPixel e GetPixel, para Wpf:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices;
using System.Windows.Media;
using System.Windows.Media.Imaging;

namespace HL.IconPro.Lib.Wpf
{
    public sealed class EditableBitmapImage
    {
        #region Constructors
        public EditableBitmapImage(BitmapSource Source)
        {
            Initialize(Source);
        }
        public EditableBitmapImage(int PixelWidth, int PixelHeight, double DpiX, double DpiY)
        {
            WriteableBitmap bp = new WriteableBitmap(PixelWidth, PixelHeight, DpiX, DpiY, PixelFormats.Bgra32, null);
            Initialize(bp);
        }
        #endregion

        #region Destructors
        ~EditableBitmapImage()
        {
            _Buffer = null;
            GC.Collect();
        }
        #endregion

        #region Fields
        private BitmapSource _OriginalSource;
        private WriteableBitmap _Source;
        private byte[] _Buffer;
        #endregion

        #region Properties
        public WriteableBitmap Source
        {
            get
            {
                _Source.Lock();
                Marshal.Copy(_Buffer, 0, _Source.BackBuffer, _Buffer.Length);
                _Source.AddDirtyRect(new System.Windows.Int32Rect(0, 0, _Source.PixelWidth, _Source.PixelHeight));
                _Source.Unlock();
                return _Source;
            }
            set
            {
                if (value == null) throw new NullReferenceException("Value can not be null");
                Initialize(value);
            }
        }
        public BitmapSource OriginalSource
        {
            get
            {
                return _OriginalSource;
            }
            set
            {
                if (value == null) throw new NullReferenceException("Value can not be null");
                Initialize(value);
            }
        }
        public byte[] Buffer
        {
            get
            {
                return _Buffer;
            }
            set
            {
                if (value == null) throw new NullReferenceException("Value can not be null");
                if (value.Rank > 1) throw new NullReferenceException("Invalid buffer: Can not be multidimensional");
                if (value.Length != _Buffer.Length) throw new NullReferenceException("Invalid buffer: Can not have a different length from the source");
                _Buffer = value;
            }
        }
        public int PixelWidth
        {
            get { return _OriginalSource.PixelWidth; }
        }
        public int PixelHeight
        {
            get { return _OriginalSource.PixelHeight; }
        }
        public double DpiX
        {
            get { return _OriginalSource.DpiX; }
        }
        public double DpiY
        {
            get { return _OriginalSource.DpiX; }
        }
        public double Width
        {
            get { return _OriginalSource.Width; }
        }
        public double Height
        {
            get { return _OriginalSource.Height; }
        }
        #endregion

        #region Procedures
        private void Initialize(BitmapSource Source)
        {
            _OriginalSource = Source;
            BitmapSource bgra = new FormatConvertedBitmap(Source, PixelFormats.Bgra32, null, 0);
            _Source = new WriteableBitmap(bgra);
            _Buffer = new byte[_Source.BackBufferStride * _Source.PixelHeight];
            Marshal.Copy(_Source.BackBuffer, _Buffer, 0, (_Source.BackBufferStride * _Source.PixelHeight));
        }
        public void SetPixel(int x, int y, Color Color)
        {
            if ((x > _Source.PixelWidth - 1) || (x < 0)) return;
            if ((y > _Source.PixelHeight - 1) || (y < 0)) return;
            if (Color == null) return;

            int loc = (x * 4) + (y * _Source.BackBufferStride);
            _Buffer[loc] = Color.B;
            _Buffer[loc + 1] = Color.G;
            _Buffer[loc + 2] = Color.R;
            _Buffer[loc + 3] = Color.A;
        }

        public Color GetPixel(int x, int y)
        {
            if ((x > _Source.PixelWidth - 1) || (x < 0)) return Color.FromArgb(0, 0, 0, 0);
            if ((y > _Source.PixelHeight - 1) || (y < 0)) return Color.FromArgb(0, 0, 0, 0);

            int loc = (x * 4) + (y * _Source.BackBufferStride);
            return Color.FromArgb(_Buffer[loc + 3], _Buffer[loc + 2], _Buffer[loc + 1], _Buffer[loc]);
        }
        #endregion

        #region Static

        #endregion

        #region Others
        public static implicit operator BitmapSource(EditableBitmapImage Source)
        {
            return Source.Source;
        }
        #endregion
    }
}

Essa classe é na verdade uma espécie de “interface” para a classe WriteableBitmap.
Com ela você pode fazer coisas do tipo:

EditableBitmapImage eb = new EditableBitmapImage(Source);
eb.SetPixel(23, 23, Color.FromArgb(245, 12, 45, 23));
BitmapSource bp = eb;

Como é possível notar no código, você precisa declara-la fornecendo uma imagem, um objeto do tipo BitmapImage ou BitmapFrame. Então você usa o objeto EditableBitmapImage para fazer as edições.

Devo ressaltar algo importante: Toda vez que você converte um EditableBitmapImage de volta para um BitmapSource, ele recria na memória um objeto do tipo WriteableBitmap. Então, por questões de desempenho, faças todas as edições na imagem de uma vez, e no final, quando você tiver certeza que não será feita mais nenhuma edição, faça a conversão para BitmapSource.

Divirta-se!!!

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!!!

Baixa frequencia no MSDN e no Blog

Olá pessoal,

Já faz um certo tempinho desde o meu último post, e por isso vim aqui dizer que o blog não morreu! Tampouco eu.. kkk

Minha participação nos fóruns do MSDN também diminuiu muito e irei explicar o porquê.

Na minha região onde vivo (Extremo Sul da Bahia, Sta. Cruz Cabrália) há bem poucas oportunidades de emprego relacionado à TI, a economia da região é basicamente turismo.

Me surgiu uma possibilidade de emprego em um novo hotel da cidade, bem aqui perto de onde moro, e consegui ser admitido. Por isso não me sobra tempo livre para o blog e o fórum, a não ser nas folgas (como hoje, por exemplo).

Masss, eu não larguei fórum e muito menos o blog. Vou continuar postando, assim que eu tiver alguma coisa interessante em mente, postarei hehe…

That’s all folks!