C++/CLI
Redimensionando Array em C++/CLI
by paulorb on jun.29, 2012, under C++/CLI
Dica rápida:
* Redimensionando Array em C++/cli
// Create and initialize a new string array. array<String^>^myArr = {L"The", L"quick", L"brown", L"fox", L"jumps", L"over", L"the", L"lazy", L"dog"}; // Resize the array to a bigger size (five elements larger). Array::Resize(myArr, myArr->Length + 5);
C++/CLI out
by paulorb on fev.08, 2012, under C++/CLI
Dica Rápida: como especificar o atributo out em C++/CLI
using namespace System::Runtime::InteropServices; void Test([Out] ClasseTest^% x);
Windows Messages em C++/CLI Form
by paulorb on fev.07, 2012, under C++/CLI
Quando precisamos usar funções que trabalham com os windows messages, como PostMessage e SendMessage temos sempre que lembrar que programas em windows são baseados em eventos que são tratados no Message Loop como no exemplo abaixo:
#include <Windows.h> LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow ) { static TCHAR szAppName [] = TEXT("HelloWindows"); HWND hwnd; MSG msg; WNDCLASS wndClass; wndClass.style = CS_HREDRAW | CS_VREDRAW; wndClass.lpfnWndProc = WndProc; wndClass.cbClsExtra = 0; wndClass.cbWndExtra = 0; wndClass.hInstance = hInstance; wndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION); wndClass.hCursor = LoadCursor(NULL, IDC_ARROW); wndClass.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH); wndClass.lpszMenuName = NULL; wndClass.lpszClassName = szAppName; if (!RegisterClass(&wndClass)) { MessageBox(NULL, TEXT("Error registering class."), szAppName, MB_ICONERROR); return 0; } hwnd = CreateWindow(szAppName, TEXT("The Hello Windows Native Programming"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL ); ShowWindow(hwnd, iCmdShow); UpdateWindow(hwnd); while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam; } LRESULT CALLBACK WndProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam ) { HDC hdc; PAINTSTRUCT ps; RECT rect; switch (message) { case WM_PAINT: hdc = BeginPaint(hwnd, &ps); GetClientRect(hwnd, &rect); DrawText(hdc, TEXT("Hello, Windows Native Programming!"), -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER); EndPaint(hwnd, &ps); return 0; case WM_DESTROY: PostQuitMessage(0); return 0; } return DefWindowProc(hwnd, message, wParam, lParam); }
Agora vamos imaginar o seguinte cenario, você está desenvolvendo uma aplicação em C++/CLI que se integrará com uma API externa em .net , essa API tem uma propriedade chamada windowHandle onde você precisa passar um Handle válido de uma janela, o objetivo dessa API é te fornecer uma forma de receber requisições assincronas por isso tem um evento Changed que sera chamado sempre que uma nova requisição chegar, o problema que irei relatar nesse post é o de que não é so criar uma janela e chamar o metodo Show e esperar os eventos chegarem. Veja o exemplo abaixo essa foi a primeira tentativa que NAO FUNCIONOU, o metodo VariableValue_Changed nunca é chamado.
Form ^formDispather = gcnew Form(); API::Variable::VariableComp declaredAPI; declaredAPI = gcnew API::Variable::VariableComp(); declaredAPI->WindowHandle = formDispather->Handle; declaredAPI->Changed += gcnew System::EventHandler(this,&NameOftheClass::VariableValue_Changed); formDispather->Show();
Olhe agora a milionesima tentativa que funcionou. Perceba a diferença!
Form ^formDispather = gcnew Form(); API::Variable::VariableComp declaredAPI; declaredAPI = gcnew API::Variable::VariableComp(); declaredAPI->WindowHandle = formDispather->Handle; declaredAPI->Changed += gcnew System::EventHandler(this,&NameOftheClass::VariableValue_Changed); Application::Run(formDispather);
Perceba que a diferença é so que no primeiro que não funcionou eu usei o metodo Show do Form e no segundo que funcionou eu usei o Application::Run eis agora a explicação de porque funcionou: o aplication run inicia uma “aplication message loop” que trata as window messages enquanto o metodo show somente não faz isso. Isso me custou horas e horas de alguns colegas. Referencia para nunca cometer esse erro: http://msdn.microsoft.com/pt-br/library/ms157901(v=vs.90).aspx
EventHandler em C++/CLI
by paulorb on fev.06, 2012, under C++/CLI
Uma dica interessante de algo que não achei muita documentação na net, como usar EventHandler em C++/CLI. Vou mostrar a diferença entre as implementações em C# e C++/CLI
Em C#:
this.TestComponent.Changed += new EventHandler(VariableValue_Changed); void Event::VariableValue_Changed(Object sender , EventArgs e){ ... }
Em C++/CLI
this->TestComponent->Changed += gcnew System::EventHandler(this, &NameOfTheClass::VariableValue_Changed); void Event::VariableValue_Changed(System::Object^ sender , System::EventArgs^ e){ ... }
Re-throw Exception sem criar objeto de Exception
by paulorb on fev.01, 2012, under C++, C++/CLI
Dica rápida: veja a situação abaixo
try{ //something }catch(Exception^ e) { return false; }
Se você não usa o Objeto tratador da exception então não DECLARE-O.
Solução:
try{ //something }catch(...) { return false; }
E se precisar passar a diante qualquer exception use:
try{ //something }catch(...) { throw; }
Referencia: http://msdn.microsoft.com/en-us/library/6dekhbbc(v=vs.80).aspx
Convertendo String managed e unmanaged
by paulorb on jan.31, 2012, under C++/CLI
Dica rápida:
* Convertendo de unmanaged pra managed
TCHAR pszNome[50] = _T("Teste"); String^ uriString = gcnew String(pszNome);
* Convertendo de managed pra unmanaged
String^ uriString =gcnew String("teste"); pin_ptr<const wchar_t> wname = PtrToStringChars(uriString); tprintf(_T("%s"),wname);
Adicionando referencia no C++/CLI
by paulorb on jan.31, 2012, under C++/CLI
Se dentro de um projeto C++ você precisa adicionar referencia a um assembly managed esses passos poderão te ajudar.
Para adicionar referencia a um assembly “exemplo.dll” coloque no começo do seu arquivo CPP:
#using <exemplo.dll>;
Nas property pages não se esqueça de referenciar o PATH para que o include encontre sua DLL.