2

I'm having a little problem with my application while trying to use WindowsAPI... I'm trying to connect to a handle in a way it works, but if I change the code it doesn't works anymore...

The code that works:

   handle_t porta; // Global var
   COMMTIMEOUTS tempos;  // Global var
   DCB configuracao; // Global var

   wchar_t pcCommPort[]= TEXT("COM1");
   //gate address to be accessed (COM1)

The code I'm trying to do:

   handle_t porta; // Global var
   COMMTIMEOUTS tempos;  // Global var
   DCB configuracao; // Global var

   String GATE = "COM" + Label1->Text;
   wchar_t pcCommPort[]= TEXT(GATE);
   //gate address to be accessed (Any gate)

I've also tried it:

   handle_t porta; // Global var
   COMMTIMEOUTS tempos;  // Global var
   DCB configuracao; // Global var

   wchar_t pcCommPort[]= TEXT("COM" + Label1->Text);
   //gate address to be accessed (Any gate)

And it:

   handle_t porta; // Global var
   COMMTIMEOUTS tempos;  // Global var
   DCB configuracao; // Global var

   String GATE = "COM" + Label1->Text;
   wchar_t pcCommPort[]= GATE;
   //gate address to be accessed (Any gate)

In any way or it says that I haven't mede the correct syntax or the error: Cannot convert unicode string into a wchar_t.

EDIT:

Full source (function):

void abrirporta(){
   wchar_t pcCommPort[]= TEXT("COM1");
   //endereço da porta a ser acessada (COM1)
   //porta foi declarado como HANDLE na seção private da declaração de classe Form
   //HANDLE porta
   porta = CreateFile(pcCommPort,GENERIC_READ+GENERIC_WRITE,0,NULL,OPEN_EXISTING,0,NULL);
   if(porta == INVALID_HANDLE_VALUE){
        log(7);
        throw Exception("Não foi possível abrir a porta COM.\nPor favor, tente novamente!");
    }

   //Tempo máximo entre o recebimento de 2 bytes (ms)
   tempos.ReadIntervalTimeout = 20;

   //Multiplicador de tempo de recebimento por byte
   tempos.ReadTotalTimeoutMultiplier = 0;
   tempos.ReadTotalTimeoutConstant = 100;
   tempos.WriteTotalTimeoutMultiplier = 0;
   tempos.WriteTotalTimeoutConstant = 100;
   if(!SetCommTimeouts(porta ,&tempos))
   {
      CloseHandle(porta);
      frmPrincipal->spLig->Visible = False;
      frmPrincipal->spStatusInd->Visible = False;
      log(6);
      throw Exception("Erro na configuração de Timeout");
   }

   GetCommState(porta, &configuracao);

   configuracao.BaudRate = 19200;
   configuracao.ByteSize = 8;
   configuracao.Parity = NOPARITY;
   configuracao.StopBits = ONESTOPBIT;

   if(!SetCommState(porta,&configuracao))
   {
        CloseHandle(porta);
        frmPrincipal->spLig->Visible = False;
        frmPrincipal->spStatusInd->Visible = False;
        log(5);
        throw Exception("Erro na Configuração da porta");
   }
    frmPrincipal->spLig->Visible = True;
    frmPrincipal->spStatusInd->Visible = False;
    log(3);
    frmPrincipal->btEnviar->Enabled = true;
    frmPrincipal->swSaida1->Enabled = true;
    log(8);
}

I hope you can help me... Since now thanks XD.

Alex K.
  • 171,639
  • 30
  • 264
  • 288
mauroaraujo
  • 332
  • 1
  • 10
  • 23
  • Why do you keep storing it in a `wchar_t[]` instead of keeping it in a string class of some sort? – Mooing Duck Sep 18 '14 at 00:03
  • You appear to be using C++/CLI, not C++. – Mooing Duck Sep 18 '14 at 00:06
  • If that's true, then you should be using the .Net APIs, rather than the Win32 API. Converting C++/CLI types to be Win32 compatible is a nightmare you don't want to get into. – Mooing Duck Sep 18 '14 at 00:07
  • The `TEXT()` macro is for constant strings only, and is legacy technology in any case: if you want a `wchar_t` constant string, just use `L"xyzzy"`. – Harry Johnston Sep 18 '14 at 00:08
  • I'm using C++ builder XE6 (I don't know if it cares...), I'm trying to conect to a serial gate like COM1, but I wnat a way to do it automatically, where the user could enter with the gate that he/she wants... Like COM2, COM3, ... , COM255. I just need to do it automatically, so I defined GATE as "COM"+ Label1->Text (The data of Label 1 comes from an Edit component). – mauroaraujo Sep 18 '14 at 00:20
  • Added full source for more details – mauroaraujo Sep 18 '14 at 00:22

1 Answers1

4

You are making this more difficult then it needs to be. System::String is an alias for System::UnicodeString, which holds wchar_t data on Windows. You don't need to copy the UnicodeString data into a wchar_t[] buffer. You can use the UnicodeString::c_str() method when you need to pass a String to a function that expects wchar_t* parameters, eg:

void abrirporta()
{
    String pcCommPort = L"COM" + Label1->Text;
    porta = CreateFile(pcCommPort.c_str(), ...);
    ...
}
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • So, I won't need of wchar_t anymore? The function c_str() converts the data from unicode string to wchat_t, correct? – mauroaraujo Sep 18 '14 at 00:56
  • @mauroraujo: An UnicodeString aldready contains an array of wchar_t (but will only give outsiders a `const` pointer to it). What remy is saying is, you don't need to copy its contents to a writable array of wchar_t because CreateFile() doesn't need a writable pointer. – Medinoc Sep 18 '14 at 09:20
  • @mauroaraujo: If the `UnicodeString` is not empty, `c_str()` (and `data()`) simply returns a pointer to its internal `wchar_t` data. There is no conversion. If the string is empty, `c_str()` returns a pointer to a null terminator (and `data()` returns NULL). – Remy Lebeau Sep 18 '14 at 16:07