Mês: fevereiro 2014

WAVE Engine: Desenvolvendo Jogos (Mobile) – C#

Que tal desenvolver jogos para as principais plataformas mobile (Android, iOS, Windows Phone) e Windows Desktop usando sua linguagem de programação favorita e o .Net Framework?

Eis aqui uma ótima engine, a WAVE:

WAVE cross platform engine

É uma engine para desenvolvimento de jogos 2D e 3D multiplataforma. Você desenvolve os jogos no Visual Studio (2010+) usando o .Net Framework + C#. O projeto ainda está em fase BETA, mas me parece muito promissor (Ainda não tive a oportunidade de testar a engine).

Ela é gratuita, veja as suas características aqui:

Overview – WAVE cross platform engine

Se alguém já a tiver testado ou for testa-la, por favor comente o que achou dela!

Json.NET: Trabalhando com json no .Net Framework

Esses tempos eu estava precisando realizar a leitura de arquivos no formato JSON no C#, e foi aí que eu encontrei esta ótima API:

James Newton-King – Json.NET

É gratuita, open-source, e muito completa. Vou citar algumas de suas características:

  1. Serializador de qualquer classe: Permite serializar e desserializar qualquer objeto da plataforma .Net usando JSON.
  2. LINQ to JSON: Crie, leie, consulte, e modifique arquivos JSON usando LINQ.
  3. JSON Schema Validation: Valide um JSON usando JSON Schema.
  4. Alta performance!
  5. Fácil de usar, possui uma API amigável.
  6. Suporte a XML: Se você precisar converter XML para JSON (e vice-versa) poderá faze-lo.
  7. Multiplataforma: JSON.NET suporta Windows, Silverlight, Windows Phone, Mono, MonoTouch e MonoDroid.
  8. A mais popular: Com mais de 3 milhões de downloads, e contando, é a libraria .Net número um no NuGet.

Onde conseguir ícones para meus aplicativos?

Se você está precisando de ícones para utilizar em seus aplicativos, eu recomendo que você visite estes dois sites:

Icons & Icon Packs – Download Free PNG Icons | IconsPedia

Icon Archive – Search 477,540 free icons, desktop icons, download icons, social icons, xp icons, vista icons

Tanto um, quanto o outro, disponibilizam os ícones de forma gratuita em formato *.png e *.ico.

Só procure tomar cuidado com uma coisa: Os ícones possuem licença e termos de uso, então procure não violá-los e dê os créditos ao autor, afinal o ícone é uma parte muito importante de um aplicativo!

Paletta de Cores do Windows 8

Pois bem, o Windows 8 introduziu uma nova interface, mas simples e limpa chamada anteriormente de Metro UI (Não utilize este nome, pertence à uma empresa lá de não sei aonde…) com uma nova Tela Inicial que possui Tiles e etc. Esta tela inicial possui a opção do usuário definir uma cor de fundo, e baseada nesta escolha, é selecionada uma cor para os Tiles.

Como um desenvolvedor atento à atualidade, você irá querer criar aplicativos que se adaptem bem à essa nova interface, e para isso nada melhor que ter em mãos a palleta de cores do Windows 8.

Para isso visite o artigo Jason N. Gaylord | Windows 8 Color Palette.

Win32: C++ para .NET – Interoperabilidade

Este post foi baseado no artigo Win32 API: C++ to .NET – CodeProject.

Certas vezes precisamos chamar alguma função de uma API externa não gerenciada, como por exemplo, as API’s do Windows. Mas isso não é algo muito simples de se fazer pois temos muitas coisas à considerar…

Para começar irei apresentar uma tabela de equivalência entre os tipos presentes no C++ e os tipos presentes no .Net Framework:

Termo Descrição
ATOM .NET = ushort C++ = typedef WORD ATOM;
BOOL .NET = bool or int C++ = typedef int BOOL;
BOOLEAN .NET = bool or byte C++ = typedef BYTE BOOLEAN;
BYTE .NET = byte C++ = typedef unsigned char BYTE;
CALLBACK .NET = delegate C++ = #define CALLBACK __stdcall
CHAR .NET = char C++ = typedef char CHAR;
COLORREF .NET = uint C++ = typedef DWORD COLORREF;
CONST .NET = const C++ = #define CONST const
DWORD .NET = uint C++ = typedef unsigned long DWORD;
DWORDLONG ulong C++ = typedef ULONG LONG DWORDLONG;
DWORD_PTRDWORD * .NET = uint or IntPtr C++ = typedef ULONG_PTR DWORD_PTR;
DWORD32 .NET = uint C++ = typedef unsigned int DWORD32;
DWORD64 .NET = ulong C++ = typedef unsigned __int64 DWORD64;
FLOAT .NET = single C++ = typedef float FLOAT;
HACCEL .NET = IntPtr C++ = typedef HANDLE HACCEL;
HANDLE .NET = IntPtr C++ = typedef PVOID HANDLE;
HBITMAP .NET = IntPtr C++ = typedef HANDLE HBITMAP;
HBRUSH .NET = IntPtr C++ = typedef HANDLE HBRUSH;
HCOLORSPACE .NET = IntPtr C++ = if(WINVER >= 0x0400) C++ = typedef HANDLE HCOLORSPACE;
HCONV .NET = IntPtr C++ = typedef HANDLE HCONV;
HCONVLIST .NET = IntPtr C++ = typedef HANDLE HCONVLIST;
HCURSOR .NET = IntPtr C++ = typedef HICON HCURSOR;
HDC .NET = IntPtr C++ = typedef HANDLE HDC;
HDDEDATA .NET = IntPtr C++ = typedef HANDLE HDDEDATA;
HDESK .NET = IntPtr C++ = typedef HANDLE HDESK;
HDROP .NET = IntPtr C++ = typedef HANDLE HDROP;
HDWP .NET = IntPtr C++ = typedef HANDLE HDWP;
HENHMETAFILE .NET = IntPtr C++ = typedef HANDLE HENHMETAFILE;
HFILE .NET = int C++ = typedef int HFILE;
HFONT .NET = IntPtr C++ = typedef HANDLE HFONT;
HGDIOBJ .NET = IntPtr C++ = typedef HANDLE HGDIOBJ;
HGLOBAL .NET = IntPtr C++ = typedef HANDLE HGLOBAL;
HHOOK .NET = IntPtr C++ = typedef HANDLE HHOOK;
HICON .NET = IntPtr C++ = typedef HANDLE HICON;
HINSTANCE .NET = IntPtr C++ = typedef HANDLE HINSTANCE;
HKEY .NET = IntPtr C++ = typedef HANDLE HKEY;
HKL .NET = IntPtr C++ = typedef HANDLE HKL;
HLOCAL .NET = IntPtr C++ = typedef HANDLE HLOCAL;
HMENU .NET = IntPtr C++ = typedef HANDLE HMENU;
HMETAFILE .NET = IntPtr C++ = typedef HANDLE HMETAFILE;
HMODULE .NET = IntPtr C++ = typedef HINSTANCE HMODULE;
HMONITOR .NET = IntPtr if(WINVER >= 0x0500) C++ = typedef HANDLE HMONITOR;
HPALETTE .NET = IntPtr C++ = typedef HANDLE HPALETTE;
HPEN .NET = IntPtr C++ = typedef HANDLE HPEN;
HRESULT .NET = int or uint C++ = typedef LONG HRESULT;
HRGN .NET = IntPtr C++ = typedef HANDLE HRGN;
HRSRC .NET = IntPtr C++ = typedef HANDLE HRSRC;
HSZ .NET = IntPtr C++ = typedef HANDLE HSZ;
HWINSTA .NET = IntPtr C++ = typedef HANDLE WINSTA;
HWND .NET = IntPtr C++ = typedef HANDLE HWND;
INT .NET = int C++ = typedef int INT;
INT_PTR .NET = IntPtr

#if defined(_WIN64)

C++ = typedef __int64 INT_PTR;

#else

C++ = typedef int INT_PTR;

INT32 .NET = int C++ = typedef signed int INT32;
INT64 .NET = long C++ = typedef signed __int64 INT64;
LANGID .NET = ushort or int C++ = typedef WORD LANGID;
LCID .NET = uint C++ = typedef DWORD LCID;
LCTYPE .NET = uint C++ = typedef DWORD LCTYPE;
LGRPID .NET = uint C++ = typedef DWORD LGRPID;
LONG .NET = int C++ = typedef long LONG;
LONGLONG .NET = long

#if !defined(_M_IX86)

C++ = typedef __int64 LONGLONG;

#else

C++ = typedef double LONGLONG;

LONG_PTR .NET = IntPtr

#if defined(_WIN64)

C++ = typedef __int64 LONG_PTR;

#else

C++ = typedef long LONG_PTR;

LONG32 .NET = int C++ = typedef signed int LONG32;
LONG64 .NET = long C++ = typedef __int64 LONG64;
LPARAM .NET = IntPtr C++ = typedef LONG_PTR LPARAM;
LPBOOLBool * .NET = IntPtr or bool C++ = typedef BOOL *LPBOOL;
LPBYTEByte * .NET = IntPtr or byte C++ = typedef BYTE *LPBYTE;
LPCOLORREF .NET = IntPtr or uint C++ = typedef DWORD *LPCOLORREF;
LPCSTR .NET = string or IntPtr or StringBuilder C++ = typedef CONST CHAR *LPCSTR;
LPCTSTR .NET = string or IntPtr or StringBuilder 

#ifdef UNICODE

C++ = typedef LPCWSTR LPCTSTR;

#else

C++ = typedef LPCSTR LPCTSTR;

LPCVOID .NET = IntPtr C++ = typedef CONST void *LPCVOID;
LPCWSTR .NET = string or IntPtr or StringBuilder C++ = typedef CONST WCHAR *LPCWSTR;
LPDWORD .NET = IntPtr or uint C++ = typedef DWORD *LPDWORD;
LPHANDLE .NET = IntPtr C++ = typedef HANDLE *LPHANDLE;
LPINT .NET = IntPtr or int C++ = typedef int *LPINT;
LPLONG .NET = IntPtr or int C++ = typedef long *LPLONG;
LPSTR .NET = string or IntPtr or StringBuilder C++ = typedef CHAR *LPSTR;
LPTSTR .NET = string or IntPtr or StringBuilder

#ifdef UNICODE

C++ = typedef LPWSTR LPTSTR;

#else

C++ = typedef LPSTR LPTSTR;

LPVOID .NET = IntPt rC++ = typedef void *LPVOID;
LPWORD .NET = IntPtr or ushort C++ = typedef WORD *LPWORD;
LPWSTR .NET = string or IntPtr or StringBuilder C++ = typedef WCHAR *LPWSTR;
LRESULT .NET = IntPtr or int C++ = typedef LONG_PTR LRESULT;
PBOOL .NET = IntPtr or bool C++ = typedef BOOL *PBOOL;
PBOOLEAN .NET = IntPtr or bool C++ = typedef BOOLEAN *PBOOLEAN;
PBYTE .NET = IntPtr or byte C++ = typedef BYTE *PBYTE;
PCHAR .NET = IntPtr or char C++ = typedef CHAR *PCHAR;
PCSTR .NET = string or IntPtr or StringBuilder C++ = typedef CONST CHAR *PCSTR;
PCTSTR .NET = string or IntPtr or StringBuilder

#ifdef UNICODE

C++ = typedef LPCWSTR PCTSTR;

#else

C++ = typedef LPCSTR PCTSTR;

PCWSTR .NET = string or IntPtr or StringBuilder C++ = typedef CONST WCHAR *PCWSTR;
PDWORD .NET = IntPtr or uint C++ = typedef DWORD *PDWORD;
PDWORDLONG .NET = IntPtr or ulong C++ = typedef DWORDLONG *PDWORDLONG;
PDWORD_PTR .NET = IntPtr or uint C++ = typedef DWORD_PTR *PDWORD_PTR;
PDWORD32 .NET = IntPtr or uint C++ = typedef DWORD32 *PDWORD32;
PDWORD64 .NET = IntPtr or ulong C++ = typedef DWORD64 *PDWORD64;
PFLOAT .NET = IntPtr or single C++ = typedef FLOAT *PFLOAT;
PHANDLE .NET = IntPtr C++ = typedef HANDLE *PHANDLE;
PHKEY .NET = IntPtr C++ = typedef HKEY *PHKEY;
PINT .NET = IntPtr or int C++ = typedef int *PINT;
PINT_PTR .NET = IntPtr C++ = typedef INT_PTR *PINT_PTR;
PINT32 .NET = IntPtr or int C++ = typedef INT32 *PINT32;
PINT64 .NET = IntPtr or long C++ = typedef INT64 *PINT64;
PLCID .NET = IntPtr or uint C++ = typedef PDWORD PLCID;
PLONG .NET = IntPtr or int C++ = typedef LONG *PLONG;
PLONGLONG .NET = IntPtr or long C++ = typedef LONGLONG *PLONGLONG;
PLONG_PTR .NET = IntPtr or int C++ = typedef LONG_PTR *PLONG_PTR;
PLONG32 .NET = IntPtr or int C++ = typedef LONG32 *PLONG32;
PLONG64 .NET = IntPtr or long C++ = typedef LONG64 *PLONG64;
POINTER_32 .NET = IntPtr or int

#if defined(_WIN64)

#define POINTER_32 __ptr32

#else

#define POINTER32

POINTER_64 .NET = IntPtr or long #define POINTER_64 __ptr64
PSHORT .NET = IntPtr or short C++ = typedef SHORT *PSHORT;
PSIZE_T .NET = IntPtr C++ = typedef SIZE_T *PSIZE_T;
PSSIZE_T .NET = IntPtr C++ = typedef SSIZE_T *PSSIZE_T;
PSTR .NET = IntPtr or string or StringBuilder C++ = typedef CHAR *PSTR;
PTBYTE .NET = IntPtr or char C++ = typedef TBYTE *PTBYTE;
PTCHAR .NET = IntPtr or string or StringBuilder C++ = typedef TCHAR *PTCHAR;
PTSTR .NET = IntPtr or string or StringBuilder

#ifdef UNICODE

C++ = typedef LPWSTR PTSTR;

#else

C++ = typedef LPSTR PTSTR;

PUCHAR .NET = IntPtr or string or StringBuilder C++ = typedef UCHAR *PUCHAR;
PUINT .NET = IntPtr or uint C++ = typedef UINT *PUINT;
PUINT_PTR .NET = IntPtr or uint C++ = typedef UINT_PTR *PUINT_PTR;
PUINT32 .NET = IntPtr or uint C++ = typedef UINT32 *PUINT32;
PUINT64 .NET = IntPtr or ulong C++ = typedef UINT64 *PUINT64;
PULONG .NET = IntPtr or uint C++ = typedef ULONG *PULONG;
PULONGLONG .NET = IntPtr or ulong C++ = typedef ULONGLONG *PULONGLONG;
PULONG_PTR .NET = IntPtr or uint C++ = typedef ULONG_PTR *PULONG_PTR;
PULONG32 .NET = IntPtr or uint C++ = typedef ULONG32 *PULONG32;
PULONG64 .NET = IntPtr or ulong C++ = typedef ULONG64 *PULONG64;
PUSHORT .NET = IntPtr or ushort C++ = typedef USHORT *PUSHORT;
PVOID .NET = IntPtrC++ = typedef void *PVOID;
PWCHAR .NET = IntPtr or string: C++ = typedef WCHAR *PWCHAR;
PWORD .NET = IntPtr or ushort C++ = typedef WORD *PWORD;
PWSTR .NET = IntPtr or string or StringBuilder C++ = typedef WCHAR *PWSTR;
SC_HANDLE .NET = IntPtr C++ = typedef HANDLE SC_HANDLE;
SC_LOCK .NET = IntPtr C++ = typedef LPVOID SC_LOCK;
SERVICE_STATUS_HANDLE .NET = IntPtr C++ = typedef HANDLE SERVICE_STATUS_HANDLE;
SHORT .NET = short C++ = typedef short SHORT;
SIZE_T .NET = uint or IntPtr C++ = typedef ULONG_PTR SIZE_T;
SSIZE_T .NET = int or IntPtr C++ = typedef LONG_PTR SSIZE_T;
TBYTE .NET = char

#ifdef UNICODE

C++ = typedef WCHAR TBYTE;

#else

C++ = typedef unsigned char TBYTE;

TCHAR .NET = char

#ifdef UNICODE

C++ = typedef WCHAR TCHAR;

#else

C++ = typedef char TCHAR;

UCHAR .NET = char C++ = typedef unsigned char UCHAR;
UINT .NET = uint: C++ = typedef unsigned int UINT;
UINT_PTR .NET = UIntPtr or uint

#if defined(_WIN64)

C++ = typedef unsigned __int64 UINT_PTR;

#else

C++ = typedef unsigned int UINT_PTR;

UINT32 .NET = uint C++ = typedef unsigned int UINT32;
UINT64 .NET = ulong C++ = typedef usigned __int64 UINT64;
ULONG .NET = uint C++ = typedef unsigned long ULONG;
ULONGLONG .NET = ulong

#if !defined(_M_IX86)

C++ = typedef unsigned __int64 ULONGLONG;

#else

C++ = typedef double ULONGLONG

ULONG_PTR .NET = IntPtr or uint

#if defined(_WIN64)

C++ = typedef unsigned __int64 ULONG_PTR;

#else

C++ = typedef unsigned long ULONG_PTR;

ULONG32 .NET = uint C++ = typedef unsigned int ULONG32;
ULONG64 .NET = ulong C++ = typedef unsigned __int64 ULONG64;
USHORT .NET = ushort C++ = typedef unsigned short USHORT;
USN .NET = long C++ = typedef LONGLONG USN;
VOID .NET = void #define VOID void
WCHAR .NET = char C++ = typedef wchar_t WCHAR;
WINAPI .NET = standard is default, look at the CallingConvention enumeration #define WINAPI __stdcall
WORD .NET = ushort C++ = typedef unsigned short WORD;
WPARAM .NET = IntPtr or uint C++ = typedef UINT_PTR WPARAM;

Algumas dicas quando você for trabalhar com estas coisas:

  1. Na tabela acima, um Ponteiro para um tipo de dados é representado com um P, por exemplo DWORD* = PDWORD.
  2. Alguns tipos como o UIntPtr não são compatíveis com o CLS, por isso eu uso IntPtr, mas você pode usar qualquer um dos dois.
  3. A primeira opção que vem logo após um ‘=’ no Intellisense da IDE é a melhor opção, geralmente.
  4. Quando usarmos strings em interoperabilidade COM, para entrada (input) deveremos sempre usar string para WCHAR* e TCHAR*, etc. Para saída (output) podemos usar string ou StringBuilder, mas certas vezes precisamos usar um IntPtr e marshar (Marshal) os caracteres usando Marshal.PtrToStructure() e incrementar o ponteiro até termos um caractere nulo. Para incrementar um ponteiro transforme-o em um int e incremente o tamanho cada vez pelo tamanho obtido por Marshal.PtrToStructure() Ex.: pointer += Marshal.SizeOf(<o último objeto que você recebeu>);.
  5. Certas vezes, tipos de dados que estão incorretos irão funcionar. Dependendo do caso um int pode funcionar no lugar de um uint e assim por diante.
  6. Se você precisar converter um IntPtr de volta para um int ou outra classe use Marshal.PtrToStructure() ou outro método que trabalhe com IntPtr.
  7. Se a API que você está usando é dependente da codificação ANSI ou UNICODE, tenha certeza que você informou a codificação corretamente (Através da enumeração CharSet) ou senão suas strings serão formatadas incorretamente.
  8. Grande parte das chamadas para API’s podem ser escritas em código gerenciado, mas algumas necessitam de ponteiros. Para isso você deverá usar C# com a palavra chave unsafe e usar a opção de compilação /unsafe.
  9. Se você quer ter certeza que o GC não “comeu” o seu IntPtr numa chamada para uma API então use o tipo HandleRef.
  10. Quando você precisar declarar structs para usar em uma chamada para uma API certifique-se de usar o atributo StructLayout.Sequential. Contudo, certas vezes é preciso modificar a estrutura (empacotamento) da struct para funcionar direito, mas normalmente não é necessário.
  11. Quando for passar ou recuperar um array para/de um método de uma API, veja se ele realmente é um array ou se é um ponteiro (IntPtr) para o array. Se for um ponteiro terás que usar Marshal.
  12. Às vezes, escolher o tipo certo pode ser difícil, mas você vai pegar o jeito dele, depois de algumas vezes.
  13. As vezes quando eu vou usar um tipo como um ponteiro para um tipo, quero dizer um IntPtr, ou o tipo de dados para onde ele aponta, algumas vezes escolhemos usar ref ou out, mas a menos que ele seja um char* de entrada, você deve usar um IntPtr para entradas e ref IntPtr para saídas.
  14. Se a sua declaração de função não funciona nem sempre culpe o jeito que você escreveu a declaração, pode ser uma chamada para os métodos anteriores que estragou tudo, ou apenas a forma de transmitir os dados que está errada.
  15. Só use as classes Marshal e MarshalAs quando for realmente necessário, pois elas demandão mais processamento em algumas situações.

Para realizar uma chamada para um método que reside um uma API não gerenciada usamos o atributo DllImport. Exemplo:

C#:

[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);

VB.NET:

<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _
Private Shared Function SendMessage(ByVal hWnd As IntPtr, ByVal Msg As UInteger, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As IntPtr
End Function

Para finalizar:

A arte de chamar métodos de APIs não gerenciadas é chamada de P/Invoke ou Plataform Invoke. Existe um site chamado pinvoke.net que possui a implementação da chamada de muitas funções não gerenciadas, então antes de quebrar a cuca tentando implementar por si próprio, dê uma olhada lá!

Todas as funções exportadas pelas APIs do Windows estão devidamente documentadas no MSDN. É algo que irá facilitar as coisas.

Este post é apenas uma tradução do artigo referenciado no topo, porém com algumas adições minhas