 |
Club Builder Foro de C++Builder en español
|
| Ver tema anterior :: Ver tema siguiente |
| Autor |
Mensaje |
JesúsGandia Master


Registrado: 17 Jul 2004Mensajes: 403Ubicación: Gandia, Valencia
|
Publicado: Mie 30 Sep, 2015 11:21 am Asunto: Comprobacion Tarjeta de Red y Dispositivo Wi-Fi |
|
|
En primer lugar agradecer a escafandra prácticamente todo el código, ya que es prácticamente obra suya.
El código intenta averiguar con qué tipo de conexión de RED está conectado el PC y al final se muestra el resultado en 12 fotos del resultado en mi programa que es un TPV Hostelería y se llama TPVBarman Start Elite. Lo que pretendo es averiguar qué tipo de conexión tienen mis clientes en su PC sin yo estar presente y en función de lo que tiene, darle unos servicios u otros.
Las opciones 1, 2 y 3 tienen el cable de RED DESCONECTADO y se prueba en combinación de los 3 posibles estados de un posible dispositivo Wi-Fi.
Las opciones 4, 5 y 6 lo mismo pero con el CABLE de RED puesto y la conexión de RED de la tarjeta DESABILITADA.
Las opciones 7, 8 y 9 lo mismo pero con la tarjeta de RED habilitada y con conexión a Internet.
Y por último 10, 11, 12 como la opción 7, 8, 9 pero sin acceso a Internet, ya sea porque los DNS no son correctos o porque está conectado a un P.A./Router/Switch sin acceso a Internet.
Explicación:
1. El código en primer lugar comprueba si tengo Wi-Fi. Si es verdadero, la desconecto y espero 5 segundos para dar tiempo al PC y asegurarme que está desconectada.
2. Una vez desconectada la Wi-Fi, compruebo si tengo acceso a Internet a través de la descarga de un fichero pequeño y por FTP. Si falla la conexión y en función del tiempo que tarda en responder:
(Tiempo < 5) = No tengo ni RED ni tampoco Internet
(Tiempo > 5) = Tengo RED pero no Internet.
3. Luego si detecto que en el paso 1 tenia Wi-Fi, la vuelvo a conectar y espero 5 segundos más para asegurarme la asociación y compruebo otra vez por FTP si puedo descargar un fichero, por lo cual me aseguro que tiene Internet.
Y ya para terminar y en función de los resultados puedo tomar una decisión de que funciones de mi programa están accesibles para el usuario. En el código existen unas barras de progreso y unos CheckBox que dan información al usuario y que no es necesario explicar.
Función de escafandra modificada a mis necesidades
| Código: |
//Función para comprobar si existe una conexión Wi-Fi (Hasta 3) CERO Desconecta y UNO Conecta
//Es necesario (#include "Wlanapi.h") y linkar la libreria Wlanapi.lib con el proyecto
bool __fastcall TfrmComprobacion::OnOffWiFi(bool OnOff)
{
struct WLANConnected{WCHAR strProfileName[256]; GUID InterfaceGuid;};//Estructura para guardar los 3 nombres SSID
static WLANConnected Interfaces[3] = {0};
HANDLE hClient;
DWORD dwVersion;
PWLAN_INTERFACE_INFO_LIST pIfList = NULL;
PWLAN_INTERFACE_INFO pIfInfo = NULL;//Para conocer el estado de la conexión
PGUID pInterfaceGuid;
PWLAN_CONNECTION_PARAMETERS pWLCP;
PWLAN_AVAILABLE_NETWORK_LIST pNetworkList;//Parametros para guardar los nombres de las SSID
bool Result = false;
if(ERROR_SUCCESS == WlanOpenHandle(1, NULL, &dwVersion, &hClient))
{
if(ERROR_SUCCESS == WlanEnumInterfaces(hClient, NULL, &pIfList))
{
for(unsigned int i = 0; i < pIfList->dwNumberOfItems; i++)
{
pInterfaceGuid = &pIfList->InterfaceInfo[pIfList->dwIndex].InterfaceGuid;
if(OnOff)
{
for(int j = 0; j < 3; j++)//Check de hata 3 adaptadores Wi-Fi
{
if(Interfaces[j].InterfaceGuid == *pInterfaceGuid)
{
pWLCP = (PWLAN_CONNECTION_PARAMETERS)WlanAllocateMemory(sizeof(WLAN_CONNECTION_PARAMETERS));
pWLCP->strProfile = Interfaces[j].strProfileName;
pWLCP->wlanConnectionMode = wlan_connection_mode_profile;;
pWLCP->pDot11Ssid = NULL; //pDot11_DDSI;
pWLCP->pDesiredBssidList = NULL;
pWLCP->dot11BssType = dot11_BSS_type_infrastructure;
pWLCP->dwFlags = 0;//0xF;
Result |= (ERROR_SUCCESS == WlanConnect(hClient, pInterfaceGuid, pWLCP, NULL));
WlanFreeMemory(pWLCP);
pIfInfo = (WLAN_INTERFACE_INFO *) &pIfList->InterfaceInfo[i];
switch(pIfInfo->isState)
{
case wlan_interface_state_not_ready:
LWiFi->Caption = "No está listo"; break;
case wlan_interface_state_connected:
LWiFi->Font->Color = clLime;
LWiFi->Caption = "Conexión Establecida"; break;
case wlan_interface_state_ad_hoc_network_formed:
LWiFi->Caption = "Probando configuración automática"; break;
case wlan_interface_state_disconnecting:
LWiFi->Caption = "Desconectando"; break;
case wlan_interface_state_disconnected:
LWiFi->Caption = "Desactivada y/o Desconectada"; break;
case wlan_interface_state_associating:
LWiFi->Caption = "Asociandose a la Red"; break;
case wlan_interface_state_discovering:
LWiFi->Caption = "Probando configuración de Red"; break;
case wlan_interface_state_authenticating:
LWiFi->Caption = "Procesando autenticación";break;
default:
LWiFi->Caption = "Estado desconocido"; break;
}
Application->ProcessMessages();
}
}
}
else
if(ERROR_SUCCESS == WlanGetAvailableNetworkList(hClient, pInterfaceGuid, 1, NULL, &pNetworkList))
{
for(unsigned int i = 0; i < pNetworkList->dwNumberOfItems; i++)
{
if(pNetworkList->Network[i].dwFlags & WLAN_AVAILABLE_NETWORK_CONNECTED)
{
lstrcpynW(Interfaces[i].strProfileName, pNetworkList->Network[i].strProfileName, 256);
Interfaces[i].InterfaceGuid = *pInterfaceGuid;
Result |= (ERROR_SUCCESS == WlanDisconnect(hClient, pInterfaceGuid, NULL));
pIfInfo = (WLAN_INTERFACE_INFO *) &pIfList->InterfaceInfo[i];
switch(pIfInfo->isState)
{
case wlan_interface_state_not_ready:
LWiFi->Caption = "No está listo"; break;
case wlan_interface_state_connected:
LWiFi->Font->Color = clLime;
LWiFi->Caption = "Conexión Establecida"; break;
case wlan_interface_state_ad_hoc_network_formed:
LWiFi->Caption = "Probando configuración automática"; break;
case wlan_interface_state_disconnecting:
LWiFi->Caption = "Desconectando"; break;
case wlan_interface_state_disconnected:
LWiFi->Caption = "Desactivada y/o Desconectada"; break;
case wlan_interface_state_associating:
LWiFi->Caption = "Asociandose a la Red"; break;
case wlan_interface_state_discovering:
LWiFi->Caption = "Probando configuración de Red"; break;
case wlan_interface_state_authenticating:
LWiFi->Caption = "Procesando autenticación";break;
default:
LWiFi->Caption = "Estado desconocido"; break;
}
Application->ProcessMessages();
}
}
WlanFreeMemory(pNetworkList);
}
}
WlanFreeMemory(pIfList);
}
WlanCloseHandle(hClient, NULL);
}
return Result;
}
//---------------------------------------------------------------------------
|
Utilización en mi programa:
| Código: |
void __fastcall TfrmComprobacion::ComprobarInternet(void)
{
IdFTP->Host = CrDat(L"ÀÒÖˆÐÏÕÓÇÊ‹ÕßÕÒÃËÕˆÃÕ");//Texto CODIFICADO
IdFTP->Username = CrDat(L"Ó’‘¾“——");//Texto CODIFICADO
IdFTP->Password = CrDat(L"–”——ìë”–––”¾¸”åÖ¸–—¾—Â");//Texto CODIFICADO
String UpdateLocal = fV->SV->DatSetPCRutaTPV_Ncr + CrDat(L"óÖÂÇÒÃúúÈÜÑ");//Texto CODIFICADO
String VersionDescarga = fV->SV->DatSetPCRutaTPV_Ncr + CrDat(L"óÖÂÇÒÃ") + L"//version_update";//Texto CODIFICADO
if(!DirectoryExists(fV->SV->DatSetPCRutaTPV_Ncr + CrDat(L"óÖÂÇÒÃ")))//Texto CODIFICADO
CreateDir(fV->SV->DatSetPCRutaTPV_Ncr + CrDat(L"óÖÂÇÒÃ"));//Texto CODIFICADO
// Creo variables de Proceso
double seg;
LARGE_INTEGER start, end, freq;
SetThreadAffinityMask(GetCurrentThread(), 1);
QueryPerformanceFrequency(&freq);
try
{
if(OnOffWiFi(0))//Comprueba Wi-Fi. CERO Desconecta y UNO conecta
LWiFi->Caption = "Desconectando Wi-Fi (5 seg.)";
Application->ProcessMessages();
Sleep(5000);
if(LWiFi->Caption == "Desconectando Wi-Fi (5 seg.)")
{
LWiFi->Caption = "Wi-Fi Desconectada";
Application->ProcessMessages();
}
QueryPerformanceCounter(&start);//Inicio Proceso Contador
PBConexionInternet->UserValue += 5;
IdFTP->Connect();
if(IdFTP->Connected())
{
IdFTP->ChangeDir(CrDat(L"ÈÜÑ"));//Texto CODIFICADO
PBConexionInternet->MaxValue = (IdFTP->Size("version_actual") + IdFTP->Size(CrDat(L"ÈÜÑ"))) / 1024;//Texto CODIFICADO
IdFTP->TransferType = ftASCII;
IdFTP->Get("version_update" , VersionDescarga, true);
IdFTP->Get(CrDat(L"ÈÜÑ") , UpdateLocal, true);//Texto CODIFICADO
IdFTP->Disconnect();
IdFTP->Tag = 1;//Para saver si ha tenido exito hasta aquí
fV->SV->AccesoInternet = 1;//Tengo conexión a Internet
//Encripto el fichero bajado
TStringList* cLineas = new TStringList();
cLineas->LoadFromFile(VersionDescarga.w_str());//Cargo el contenido del fichero de versión
fV->SV->VersionUpdate = cLineas->Strings[0];//Capturo la primera Linea del fichero
cLineas->LoadFromFile(UpdateLocal.w_str());//Cargo el contenido del fichero con seriales problematicos
for(int i = 0; i < cLineas->Count; i++)//Con el bucle, encripto todo el fichero
cLineas->Strings[i] = CrDat(cLineas->Strings[i]);
cLineas->SaveToFile(UpdateLocal.w_str());//Lo guardo encriptado en el disco Local
delete cLineas;
LRed->Font->Color = clLime;
LAccesoInternet->Font->Color = clLime;
LRed->Caption = "Conexión Establecida";
switch(IdFTP->Tag)
{
case 0: LAccesoInternet->Caption = "Sin Acceso a Internet"; break;
case 1: LAccesoInternet->Caption = "Conexión Establecida. Tarjeta Red"; break;
case 2: LAccesoInternet->Caption = "Conexión Establecida. Wi-Fi";break;
case 3: LAccesoInternet->Caption = "Conexión Establecida. Tarjeta Red + Wi-Fi"; break;
}
CB2->Enabled = true;
CB2->Checked = true;
CB3->Enabled = true;
CB3->Checked = true;
CB4->Enabled = true;
CB4->Checked = true;
CB5->Enabled = true;
CB5->Checked = true;
CB6->Enabled = true;
CB6->Checked = true;
CB7->Enabled = true;
CB7->Checked = true;
CB8->Enabled = true;
CB8->Checked = true;
CB9->Enabled = true;
CB9->Checked = true;
}
Application->ProcessMessages();
}
catch(...)
{
if(!IdFTP->Tag)//Si es igual a CERO es que algo ha ido mal.
fV->SV->AccesoInternet = 0;//Si tengo conexión a Internet
LAccesoInternet->Font->Color = clRed;
LAccesoInternet->Caption = "Sin Acceso a Internet";
QueryPerformanceCounter(&end);
seg = (end.QuadPart-start.QuadPart)/static_cast<double>(freq.QuadPart);
if(seg < 5)//Si tarda mas de 5 segundos no tengo tarjeta de RED o el cable está desconectado
{
LRed->Font->Color = clRed;
LRed->Caption = "Desactivada y/o Desconectada";
}
else//Si tarda mas de 5 segundos tengo tarjeta de RED con cable conectado, pero sin Acceso a Internet
{
LRed->Font->Color = TColor(33023);//Naranja
LRed->Caption = "Conectado a la Red";
CB2->Enabled = true;
CB2->Checked = true;
}
PBConexionInternet->UserValue = PBConexionInternet->MaxValue;
Application->ProcessMessages();
}
if(LWiFi->Caption == "Wi-Fi Desconectada")
{
LWiFi->Caption = "Desconectando y probando Tarjeta de Red";
LWiFi->Font->Color = TColor(33023);//Naranja
}
else
{
LWiFi->Caption = "Desactivada y/o Desconectada";
LWiFi->Font->Color = clRed;
}
Application->ProcessMessages();
if(LWiFi->Caption == "Desconectando y probando Tarjeta de Red")//Conecto el Wifi si antes esta conectado y lo desconecte para hacer la prueba de la tarjeta de Red
{
if(OnOffWiFi(1))//CERO Desconecta y UNO conecta
{
LWiFi->Caption = "Conexión Establecida";
LWiFi->Font->Color = clLime;
LAccesoInternet->Caption = "Comprobando Internet con Wi-Fi (5 seg.)";
LAccesoInternet->Font->Color = TColor(33023);//Naranja
Application->ProcessMessages();
Sleep(5000);//Diez segundos para dar tiempo a reconectar la Wi-Fi
try
{
IdFTP->Connect();
if(IdFTP->Connected())
{
IdFTP->ChangeDir(CrDat(L"ÈÜÑ"));//Texto CODIFICADO
PBConexionInternet->MaxValue = (IdFTP->Size("version_actual") + IdFTP->Size(CrDat(L"ÈÜÑ"))) / 1024;//Texto CODIFICADO
PBConexionInternet->UserValue = 0;
IdFTP->TransferType = ftASCII;
IdFTP->Get("version_update" , VersionDescarga, true);
IdFTP->Get(CrDat(L"ÈÜÑ") , UpdateLocal, true);//Texto CODIFICADO
IdFTP->Disconnect();
if(IdFTP->Tag)//Si es igual a UNO tengo internet con Tarjeta de RED
IdFTP->Tag = 3;//Tengo Internet con Tarjeta de Red y Wi-Fi
else
IdFTP->Tag = 2;//Tengo Internet con Wi-Fi
fV->SV->AccesoInternet = 1;//Tengo conexión a Internet
LAccesoInternet->Font->Color = clLime;
switch(IdFTP->Tag)
{
case 0: LAccesoInternet->Caption = "Sin Acceso a Internet"; break;
case 1: LAccesoInternet->Caption = "Conexión Establecida. Tarjeta Red"; break;
case 2: LAccesoInternet->Caption = "Conexión Establecida. Wi-Fi";break;
case 3: LAccesoInternet->Caption = "Conexión Establecida. Tarjeta Red + Wi-Fi"; break;
}
if(IdFTP->Tag == 2)
{
CB2->Enabled = false;
CB2->Checked = false;
}
CB2->Checked = true;
CB3->Enabled = true;
CB3->Checked = true;
CB4->Enabled = true;
CB4->Checked = true;
CB5->Enabled = true;
CB5->Checked = true;
CB6->Enabled = true;
CB6->Checked = true;
CB7->Enabled = true;
CB7->Checked = true;
CB8->Enabled = true;
CB8->Checked = true;
CB9->Enabled = true;
CB9->Checked = true;
}
}
catch(...)
{
if(!IdFTP->Tag)//Si es igual a CERO es que algo ha ido mal.
fV->SV->AccesoInternet = 0;//Si tengo conexión a Internet
LAccesoInternet->Font->Color = clRed;
switch(IdFTP->Tag)
{
case 0: LAccesoInternet->Caption = "Sin Acceso a Internet"; break;
case 1: LAccesoInternet->Caption = "Conexión Establecida. Tarjeta Red"; break;
case 2: LAccesoInternet->Caption = "Conexión Establecida. Wi-Fi";break;
case 3: LAccesoInternet->Caption = "Conexión Establecida. Tarjeta Red + Wi-Fi"; break;
}
}
}
}
else
{
LWiFi->Caption = "Desactivada y/o Desconectada";
LWiFi->Font->Color = clRed;
}
PBConexionInternet->UserValue += 5;
if(LRed->Font->Color == clRed)//Si no tengo Tarjeta de RED Conectada
CB2->Checked = false;
Application->ProcessMessages();
}
//---------------------------------------------------------------------------
|
Fotos de variables y los resultados
variables posibles:
opción 1:
opción 2:
opción 3:
opción 4:
opción 5:
opción 6:
opción 7:
opción 8:
opción 9:
opción 10:
opción 11:
opción 12:
 _________________ Muchos hombres no se equivocan jamás porque no se proponen nada razonable. |
|
| Volver arriba |
|
 |
escafandra Master

Registrado: 29 Nov 2007Mensajes: 625Ubicación: Madrid - España
|
Publicado: Mie 30 Sep, 2015 3:50 pm Asunto: |
|
|
Gracias por los créditos, JesúsGandia
No discutimos sobre el tema de las notificaciones. Tu esperas 5 segundos asumiendo que en ese tiempo el sistema conseguirá una conexión wifi o su desconexión. Pero es aventurado asumir ese periodo, ya que se puede alargar o ser mucho más corto. M$ tiene previsto esto con las notificaciones, para lo que se dispone de la API WlanRegisterNotification. Esa API nos registra para que nuestro código reciba notificaciones de los eventos ocurridos con la Wifi via una función Callback. Te expongo un ejemplo básico:
| Código: |
// función callback general
void WINAPI WLAN_Notification_(PWLAN_NOTIFICATION_DATA data, PVOID context)
{
if(context)
((TForm1*)context)->WLAN_Notification(data, context);
}
// Registrando las notificaciones
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
DWORD dwVersion;
if(ERROR_SUCCESS == WlanOpenHandle(1, NULL, &dwVersion, &hClient))
WlanRegisterNotification(hClient, WLAN_NOTIFICATION_SOURCE_ACM, true, WLAN_Notification_, this, NULL, NULL);
}
// Recibiendo las notificaciones en mi formulario y actuando en consecuencia:
void __fastcall TForm1::WLAN_Notification(PWLAN_NOTIFICATION_DATA data, PVOID context)
{
if(data){
if(data->NotificationSource == WLAN_NOTIFICATION_SOURCE_ACM){
if(data->NotificationCode == 10){ //wlan_notification_acm_connection_complete // Connected
// Si hubo un error en la conexión
if(WLAN_REASON_CODE_SUCCESS != ((PWLAN_CONNECTION_NOTIFICATION_DATA)(data->pData))->wlanReasonCode){
// La clave pudo ser errónea
.....Mi código de actuación...
}
// Conexión exitosa
else{
.....Mi código de actuación...
}
}
// Se desconectó la Wifi
else if(data->NotificationCode == 21){ // wlan_notification_acm_disconnected // Disconnected
.....Mi código de actuación...
}
}
}
}
|
De esta forma sabes cuando se completó una conexión / desconexión y actúas según necesidades.
Saludos. |
|
| Volver arriba |
|
 |
JesúsGandia Master


Registrado: 17 Jul 2004Mensajes: 403Ubicación: Gandia, Valencia
|
Publicado: Jue 01 Oct, 2015 12:27 pm Asunto: |
|
|
escafandra, no me compila:
error en la LINEA:
| Código: |
WlanRegisterNotification(hClient, WLAN_NOTIFICATION_SOURCE_ACM, true, WLAN_Notification_, this, NULL, NULL);
|
| Código: |
// Recibiendo las notificaciones en mi formulario y actuando en consecuencia:
void __fastcall TfrmComprobacion::WLAN_Notification(PWLAN_NOTIFICATION_DATA data, PVOID context)
{
if(data)
{
if(data->NotificationSource == WLAN_NOTIFICATION_SOURCE_ACM)
{
if(data->NotificationCode == wlan_notification_acm_connection_complete)//Connected
{
if(WLAN_REASON_CODE_SUCCESS != ((PWLAN_CONNECTION_NOTIFICATION_DATA)(data->pData))->wlanReasonCode)// Si hubo un error en la conexión
{
ShowMessage("NO PUDO CONECTAR");//La clave pudo ser errónea
}
else//Conexión exitosa
{
ShowMessage("NO PUDO CONECTÓ SIN PROBLEMAS");
}
}
}
else//Se desconectó la Wifi
if(data->NotificationCode == wlan_notification_acm_disconnected)
{
ShowMessage("NO PUDO CONECTÓ SIN PROBLEMAS");// Disconnected
}
}
}
//---------------------------------------------------------------------------
// función callback general
void __stdcall WINAPI WLAN_Notification_(PWLAN_NOTIFICATION_DATA data, PVOID context)
{
if(context)
((TfrmComprobacion*)context)->WLAN_Notification(data, context);
}
//---------------------------------------------------------------------------
|
.h
| Código: |
private: // User declarations
void __fastcall ComprobarInternet(void);
bool __fastcall ::OnOffWiFi(bool OnOff);
typedef struct _WLAN_NOTIFICATION_DATA
{
DWORD NotificationSource;
DWORD NotificationCode;
GUID InterfaceGuid;
DWORD dwDataSize;
PVOID pData;
} WLAN_NOTIFICATION_DATA, *PWLAN_NOTIFICATION_DATA;
void __stdcall WINAPI WLAN_Notification_(PWLAN_NOTIFICATION_DATA data, PVOID context);
void __fastcall ::WLAN_Notification(PWLAN_NOTIFICATION_DATA data, PVOID context);
|
ERROR:
| Cita: |
[BCC32 Error] UnidadComprobacion.cpp(1271): E2034 Cannot convert 'void (__stdcall * (_closure )(TfrmComprobacion::_WLAN_NOTIFICATION_DATA *,void *))(TfrmComprobacion::_WLAN_NOTIFICATION_DATA *,void *)' to 'void (__stdcall *)(_L2_NOTIFICATION_DATA *,void *)'
[BCC32 Error] UnidadComprobacion.cpp(1271): E2342 Type mismatch in parameter 'funcCallback' (wanted 'void (__stdcall *)(_L2_NOTIFICATION_DATA *,void *)', got 'void')
[BCC32 Error] UnidadComprobacion.cpp(1396): E2247 '_fastcall TfrmComprobacion::WLAN_Notification(TfrmComprobacion::_WLAN_NOTIFICATION_DATA *,void *)' is not accessible
Failed
Elapsed time: 00:00:00.5
|
_________________ Muchos hombres no se equivocan jamás porque no se proponen nada razonable. |
|
| Volver arriba |
|
 |
JesúsGandia Master


Registrado: 17 Jul 2004Mensajes: 403Ubicación: Gandia, Valencia
|
Publicado: Jue 01 Oct, 2015 1:14 pm Asunto: |
|
|
Si comento la línea anterior para que no me de error:
| Código: |
// función callback general
void __stdcall WINAPI WLAN_Notification_(PWLAN_NOTIFICATION_DATA data, PVOID context)
{
if(context)
((TfrmComprobacion*)context)->WLAN_Notification(data, context);
}
//--------------------------------------------------------------------------- |
| Cita: |
[BCC32 Error] UnidadComprobacion.cpp(1396): E2247 '_fastcall TfrmComprobacion::WLAN_Notification(TfrmComprobacion::_WLAN_NOTIFICATION_DATA *,void *)' is not accessible
Failed
Elapsed time: 00:00:00.4
| [/code] _________________ Muchos hombres no se equivocan jamás porque no se proponen nada razonable. |
|
| Volver arriba |
|
 |
escafandra Master

Registrado: 29 Nov 2007Mensajes: 625Ubicación: Madrid - España
|
Publicado: Jue 01 Oct, 2015 1:57 pm Asunto: |
|
|
| Cita: | | [BCC32 Error] UnidadComprobacion.cpp(1271): E2034 Cannot convert 'void (__stdcall * (_closure )(TfrmComprobacion::_WLAN_NOTIFICATION_DATA *,void *))(TfrmComprobacion::_WLAN_NOTIFICATION_DATA *,void *)' to 'void (__stdcall *)(_L2_NOTIFICATION_DATA *,void *)' |
La función Callback general no puede ser miembro de tu formulario, o si lo es, debe ser una función estática, en otro caso el compilador dará el error que comentas. Eso es debido a que un puntero a función precisa implicitamente de la existencia de un objeto de la clase y puntero this, por lo tanto el compilador no admite un puntero a una función miembro que no sea estática, como función callback para registrar las notificaciones.
Si te fijas, a la API WlanRegisterNotification se le pasa la función callback general y el puntero this. Cuando Wlanapi llame a nuestra función callbak general, ésta se encargará de llamar a la función equivalente de nuestro formulario conociendo el puntero this de éste.
Saludos. |
|
| Volver arriba |
|
 |
JesúsGandia Master


Registrado: 17 Jul 2004Mensajes: 403Ubicación: Gandia, Valencia
|
Publicado: Jue 01 Oct, 2015 4:25 pm Asunto: |
|
|
Perdona mi torpeza, pero algo estoy haciendo mal.
| Código: |
// Recibiendo las notificaciones en mi formulario y actuando en consecuencia:
void __fastcall TfrmComprobacion::WLAN_Notification(PWLAN_NOTIFICATION_DATA data, PVOID context)
{
if(data)
{
if(data->NotificationSource == WLAN_NOTIFICATION_SOURCE_ACM)
{
if(data->NotificationCode == wlan_notification_acm_connection_complete)//Connected
{
if(WLAN_REASON_CODE_SUCCESS != ((PWLAN_CONNECTION_NOTIFICATION_DATA)(data->pData))->wlanReasonCode)// Si hubo un error en la conexión
{
ShowMessage("NO PUDO CONECTAR");//La clave pudo ser errónea
}
else//Conexión exitosa
{
ShowMessage("NO PUDO CONECTÓ SIN PROBLEMAS");
}
}
}
else//Se desconectó la Wifi
if(data->NotificationCode == wlan_notification_acm_disconnected)
{
ShowMessage("NO PUDO CONECTÓ SIN PROBLEMAS");// Disconnected
}
}
}
//---------------------------------------------------------------------------
// función callback general
static void __stdcall WINAPI WLAN_Notification_(PWLAN_NOTIFICATION_DATA data, PVOID context)
{
if(context)
((TfrmComprobacion*)context)->WLAN_Notification(data, context);
}
//---------------------------------------------------------------------------
|
En el UnidadComprobacion.h:
| Código: |
private: // User declarations
void __fastcall ComprobarInternet(void);
bool __fastcall ::OnOffWiFi(bool OnOff);
typedef struct _WLAN_NOTIFICATION_DATA
{
DWORD NotificationSource;
DWORD NotificationCode;
GUID InterfaceGuid;
DWORD dwDataSize;
PVOID pData;
} WLAN_NOTIFICATION_DATA, *PWLAN_NOTIFICATION_DATA;
static void __stdcall WINAPI WLAN_Notification_(PWLAN_NOTIFICATION_DATA data, PVOID context);
void __fastcall ::WLAN_Notification(PWLAN_NOTIFICATION_DATA data, PVOID context); |
Iual estoy declarando alguna función en el lugar no adecuado.
y el error que me da:
| Cita: |
[BCC32 Error] UnidadComprobacion.cpp(1396): E2247 '_fastcall TfrmComprobacion::WLAN_Notification(TfrmComprobacion::_WLAN_NOTIFICATION_DATA *,void *)' is not accessible
Failed
Elapsed time: 00:00:00.4 |
_________________ Muchos hombres no se equivocan jamás porque no se proponen nada razonable. |
|
| Volver arriba |
|
 |
escafandra Master

Registrado: 29 Nov 2007Mensajes: 625Ubicación: Madrid - España
|
Publicado: Jue 01 Oct, 2015 5:04 pm Asunto: |
|
|
Ya que optas por una función callback general estática para tu clase, su implementación debe ser así:
| Código: |
private: // User declarations
void __fastcall ComprobarInternet(void);
bool __fastcall OnOffWiFi(bool OnOff);
typedef struct _WLAN_NOTIFICATION_DATA
{
DWORD NotificationSource;
DWORD NotificationCode;
GUID InterfaceGuid;
DWORD dwDataSize;
PVOID pData;
} WLAN_NOTIFICATION_DATA, *PWLAN_NOTIFICATION_DATA;
static void WINAPI WLAN_Notification_(PWLAN_NOTIFICATION_DATA data, PVOID context);
void __fastcall WLAN_Notification(PWLAN_NOTIFICATION_DATA data, PVOID context);
|
| Código: |
void WINAPI TfrmComprobacion::WLAN_Notification_(PWLAN_NOTIFICATION_DATA data, PVOID context)
{
if(context)
((TForm1*)context)->WLAN_Notification(data, context);
}
|
Es decir debe ser precedida por el nombre de la clase. Este tipo de funciones solo puede usar miembros también estáticos.
La otra opción es que la función callback general no pertenezca a ninguna clase, también compilaría y funcionaría bien. Dado que la función general hace un typecast al tipo tu formulario mediante el puntero this pasado, es mas correcto que sea una función miembro estática de la clase TfrmComprobacion.
PD: WINAPI y __stdcall es lo mismo.
Saludos. |
|
| Volver arriba |
|
 |
JesúsGandia Master


Registrado: 17 Jul 2004Mensajes: 403Ubicación: Gandia, Valencia
|
Publicado: Jue 01 Oct, 2015 11:01 pm Asunto: |
|
|
Ya he conseguido que compile, pro debo de ser un memo, porque no me comunica nada la función "WLAN_Notification".
GRACIAS POR TU PACIENCIA.
Asi queda el código:
Form = frmComprobacion
UnidadComprobacion.cpp
| Código: |
//Función para comprobar si existe una conexión Wi-Fi (Hasta 3) CERO Desconecta y UNO Conecta
//Es necesario (#include "Wlanapi.h") y linkar la libreria Wlanapi.lib con el proyecto
bool __fastcall TfrmComprobacion::OnOffWiFi(bool OnOff)
{
struct WLANConnected{WCHAR strProfileName[256]; GUID InterfaceGuid;};//Estructura para guardar los 3 nombres SSID
static WLANConnected Interfaces[3] = {0};
HANDLE hClient;
DWORD dwVersion;
PWLAN_INTERFACE_INFO_LIST pIfList = NULL;
PWLAN_INTERFACE_INFO pIfInfo = NULL;//Para conocer el estado de la conexión
PGUID pInterfaceGuid;
PWLAN_CONNECTION_PARAMETERS pWLCP;
PWLAN_AVAILABLE_NETWORK_LIST pNetworkList;//Parametros para guardar los nombres de las SSID
bool Result = false;
if(ERROR_SUCCESS == WlanOpenHandle(1, NULL, &dwVersion, &hClient))
{
if(ERROR_SUCCESS == WlanEnumInterfaces(hClient, NULL, &pIfList))
{
WlanRegisterNotification(hClient, WLAN_NOTIFICATION_SOURCE_ALL, true, (WLAN_NOTIFICATION_CALLBACK)WLAN_Notification_, this, NULL, NULL);
for(unsigned int i = 0; i < pIfList->dwNumberOfItems; i++)
{
pInterfaceGuid = &pIfList->InterfaceInfo[pIfList->dwIndex].InterfaceGuid;
if(OnOff)
{
for(int j = 0; j < 3; j++)//Check de hata 3 adaptadores Wi-Fi
{
if(Interfaces[j].InterfaceGuid == *pInterfaceGuid)
{
pWLCP = (PWLAN_CONNECTION_PARAMETERS)WlanAllocateMemory(sizeof(WLAN_CONNECTION_PARAMETERS));
pWLCP->strProfile = Interfaces[j].strProfileName;
pWLCP->wlanConnectionMode = wlan_connection_mode_profile;;
pWLCP->pDot11Ssid = NULL; //pDot11_DDSI;
pWLCP->pDesiredBssidList = NULL;
pWLCP->dot11BssType = dot11_BSS_type_infrastructure;
pWLCP->dwFlags = 0;//0xF;
Result |= (ERROR_SUCCESS == WlanConnect(hClient, pInterfaceGuid, pWLCP, NULL));
WlanFreeMemory(pWLCP);
pIfInfo = (WLAN_INTERFACE_INFO *) &pIfList->InterfaceInfo[i];
switch(pIfInfo->isState)
{
case wlan_interface_state_not_ready:
LWiFi->Caption = "No está listo"; break;
case wlan_interface_state_connected:
LWiFi->Font->Color = clLime;
LWiFi->Caption = "Conexión Establecida"; break;
case wlan_interface_state_ad_hoc_network_formed:
LWiFi->Caption = "Probando configuración automática"; break;
case wlan_interface_state_disconnecting:
LWiFi->Caption = "Desconectando"; break;
case wlan_interface_state_disconnected:
LWiFi->Caption = "Desactivada y/o Desconectada"; break;
case wlan_interface_state_associating:
LWiFi->Caption = "Asociandose a la Red"; break;
case wlan_interface_state_discovering:
LWiFi->Caption = "Probando configuración de Red"; break;
case wlan_interface_state_authenticating:
LWiFi->Caption = "Procesando autenticación";break;
default:
LWiFi->Caption = "Estado desconocido"; break;
}
Application->ProcessMessages();
}
}
}
else
if(ERROR_SUCCESS == WlanGetAvailableNetworkList(hClient, pInterfaceGuid, 1, NULL, &pNetworkList))
{
for(unsigned int i = 0; i < pNetworkList->dwNumberOfItems; i++)
{
if(pNetworkList->Network[i].dwFlags & WLAN_AVAILABLE_NETWORK_CONNECTED)
{
lstrcpynW(Interfaces[i].strProfileName, pNetworkList->Network[i].strProfileName, 256);
Interfaces[i].InterfaceGuid = *pInterfaceGuid;
Result |= (ERROR_SUCCESS == WlanDisconnect(hClient, pInterfaceGuid, NULL));
pIfInfo = (WLAN_INTERFACE_INFO *) &pIfList->InterfaceInfo[i];
switch(pIfInfo->isState)
{
case wlan_interface_state_not_ready:
LWiFi->Caption = "No está listo"; break;
case wlan_interface_state_connected:
LWiFi->Font->Color = clLime;
LWiFi->Caption = "Conexión Establecida"; break;
case wlan_interface_state_ad_hoc_network_formed:
LWiFi->Caption = "Probando configuración automática"; break;
case wlan_interface_state_disconnecting:
LWiFi->Caption = "Desconectando"; break;
case wlan_interface_state_disconnected:
LWiFi->Caption = "Desactivada y/o Desconectada"; break;
case wlan_interface_state_associating:
LWiFi->Caption = "Asociandose a la Red"; break;
case wlan_interface_state_discovering:
LWiFi->Caption = "Probando configuración de Red"; break;
case wlan_interface_state_authenticating:
LWiFi->Caption = "Procesando autenticación";break;
default:
LWiFi->Caption = "Estado desconocido"; break;
}
Application->ProcessMessages();
}
}
WlanFreeMemory(pNetworkList);
}
}
WlanFreeMemory(pIfList);
}
WlanCloseHandle(hClient, NULL);
}
return Result;
}
//---------------------------------------------------------------------------
// Recibiendo las notificaciones en mi formulario y actuando en consecuencia:
void __fastcall TfrmComprobacion::WLAN_Notification(PWLAN_NOTIFICATION_DATA data, PVOID context)
{
if(data)
{
if(data->NotificationSource == WLAN_NOTIFICATION_SOURCE_ACM)
{
if(data->NotificationCode == wlan_notification_acm_connection_complete)//Connected
{
if(WLAN_REASON_CODE_SUCCESS != ((PWLAN_CONNECTION_NOTIFICATION_DATA)(data->pData))->wlanReasonCode)// Si hubo un error en la conexión
{
ShowMessage("NO PUDO CONECTAR");//La clave pudo ser errónea
}
else//Conexión exitosa
{
ShowMessage("CONECTÓ SIN PROBLEMAS");
}
}
}
else//Se desconectó la Wifi
if(data->NotificationCode == wlan_notification_acm_disconnected)
{
ShowMessage("SE DESCONECTO");// Disconnected
}
}
}
//---------------------------------------------------------------------------
// función callback general
void WINAPI TfrmComprobacion::WLAN_Notification_(PWLAN_NOTIFICATION_DATA data, PVOID context)
{
if(context)
((TfrmComprobacion*)context)->WLAN_Notification(data , context);// ->WLAN_Notification(&data, context);
}
//---------------------------------------------------------------------------
|
UnidadComprobacion.h
| Código: |
class TfrmComprobacion : public TForm
{
__published: // IDE-managed Components
TLMDProgress *PBDatos;
TTimer *Reloj;
TTimer *Reloj2;
TPanel *Panel1;
TLabel *LComprobacion;
TLabel *Label1;
TLabel *LProcesando;
TStaticText *STProcesadas;
TLabel *LActualizadas;
TStaticText *STActualizadas;
TStaticText *LTiempo;
TIdFTP *IdFTP;
TBevel *Bevel1;
TLabel *Label3;
TLabel *Label5;
TStaticText *LRed;
TStaticText *LAccesoInternet;
TLMDProgress *PBConexionInternet;
TLabel *LExaminandoInternet;
TLMDButton *BtnSalir;
TPanel *P_Servicios;
TLMDGroupBox *GBServicios;
TLMDCheckBox *CB9;
TLMDCheckBox *CB3;
TLMDCheckBox *CB4;
TLMDCheckBox *CB8;
TLMDCheckBox *CB7;
TLMDCheckBox *CB5;
TLMDCheckBox *CB6;
TLMDCheckBox *CB2;
TLMDCheckBox *CB1;
TLMDSimpleLabel *Logo;
TLabel *Label2;
TStaticText *LWiFi;
TLMDCheckBox *CB10;
TLMDCheckBox *CB11;
void __fastcall RelojTimer(TObject *Sender);
void __fastcall FormShow(TObject *Sender);
void __fastcall FormCreate(TObject *Sender);
void __fastcall ComprobarImpresoras(void);
void __fastcall FormClose(TObject *Sender, TCloseAction &Action);
void __fastcall IdFTPWork(TObject *ASender, TWorkMode AWorkMode, __int64 AWorkCount);
void __fastcall Reloj2Timer(TObject *Sender);
private: // User declarations
void __fastcall ComprobarInternet(void);
bool __fastcall ::OnOffWiFi(bool OnOff);
typedef struct _WLAN_NOTIFICATION_DATA
{
DWORD NotificationSource;
DWORD NotificationCode;
GUID InterfaceGuid;
DWORD dwDataSize;
PVOID pData;
} *PWLAN_NOTIFICATION_DATA;
static void WINAPI WLAN_Notification_(PWLAN_NOTIFICATION_DATA data, PVOID context);
void __fastcall WLAN_Notification(PWLAN_NOTIFICATION_DATA data, PVOID context);
public: // User declarations
__fastcall TfrmComprobacion(TComponent* Owner);
String FormularioAnterior;
};
//---------------------------------------------------------------------------
extern PACKAGE TfrmComprobacion *frmComprobacion;
//---------------------------------------------------------------------------
#endif
|
_________________ Muchos hombres no se equivocan jamás porque no se proponen nada razonable. |
|
| Volver arriba |
|
 |
escafandra Master

Registrado: 29 Nov 2007Mensajes: 625Ubicación: Madrid - España
|
Publicado: Jue 01 Oct, 2015 11:51 pm Asunto: |
|
|
| JesúsGandia escribió: | | Ya he conseguido que compile, pro debo de ser un memo, porque no me comunica nada la función "WLAN_Notification". |
¿Has registrado las notificaciones?
| Código: | // Registrando las notificaciones
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
DWORD dwVersion;
if(ERROR_SUCCESS == WlanOpenHandle(1, NULL, &dwVersion, &hClient))
WlanRegisterNotification(hClient, WLAN_NOTIFICATION_SOURCE_ACM, true, WLAN_Notification_, this, NULL, NULL);
}
|
Saludos. |
|
| Volver arriba |
|
 |
JesúsGandia Master


Registrado: 17 Jul 2004Mensajes: 403Ubicación: Gandia, Valencia
|
Publicado: Vie 02 Oct, 2015 5:27 pm Asunto: |
|
|
Ya lo hice y me muestra avisos, pero solo si está conectado la Wi-Fi... Y no es lo que busco, ya que tengo que poner un Bucle while hasta que me de el resultado busco.
Pero intuyo que solo me notifica el estado de la Wi-Fi si encuentra una interfaz... y yo lo que hago, es apagar o encender el dispositivo... y no verificar si la conexión tubo éxito o no con el servidor wi-fi
Se que es aventurado dar un tiempo de 5 segundos para conectar o desconectar, pero esta prueba la hago si detecto un dispositivo Wi-Fi y éste está conectado, de lo contrario no hago nada ya que asumo que el cliente no tiene Internet con este Dispositivo.
Al final he puesto el código en la parte TForm(Owner) y comunica ciertos eventos, pero no de la forma que yo necesito, por lo que he decidido dejar el código tal cual pongo al principio de este post.
Lo he probado con 5 PC y con otros tantos clientes en circunstancias diversas y con PC lentos y rápidos y el resultado siempre es correcto contemplando esos 5 segundos de tiempo ya que los parámetros de SSID, claves etc, ya están preconfigurados en el PC antes de mis pruebas. En realidad las conexiónes y desconexiones las hace en 1 segundo, pero para no equivocarme le puse 5 segundos. Incluso poniéndole 10 segundos, considero que es un tiempo razonable (20 segundos) que el programa consuma en el inicio para verificar sus valores de REDES. Ten en cuenta que si el programa no detecta Wi-Fi en el cliente no se pone en marcha el tiempo de espera ya que saltaría el código.
escafandra, muchas gracias por tu ayuda. _________________ Muchos hombres no se equivocan jamás porque no se proponen nada razonable. |
|
| Volver arriba |
|
 |
escafandra Master

Registrado: 29 Nov 2007Mensajes: 625Ubicación: Madrid - España
|
Publicado: Vie 02 Oct, 2015 6:00 pm Asunto: |
|
|
Efectivamente si no hay dispositivo wifi no va a haber notificaciones. En caso contrario notificará tanto cuando desconectas las redes, como cuando las conectas. Con el código que te di para desconectar guardando las conexiones previas y conectarlas después, no apagas nunca el interface wifi, sólo desconectas redes y las notificaciones seguirán activas en el PC independientemente de que esté conectado, o no, a una red wifi.
Saludos. |
|
| Volver arriba |
|
 |
|
|
No puedes publicar temas nuevos en este foro No puedes responder a temas en este foro No puedes editar tus mensajes en este foro No puedes borrar tus mensajes en este foro No puedes votar en las encuestas de este foro
|
© 2002–2026 Club Builder · Funciona con phpBB.
|