Foros del Web » Programación para mayores de 30 ;) » C/C++ »

[SOLUCIONADO] Temporizadores con parámetros

Estas en el tema de Temporizadores con parámetros en el foro de C/C++ en Foros del Web. Hola que tal bueno pues tengo un problema con los temporizadores realmente tengo como 1 mes en c++ pero no es problema ya que vengo ...
  #1 (permalink)  
Antiguo 14/10/2013, 11:20
 
Fecha de Ingreso: julio-2011
Mensajes: 8
Antigüedad: 12 años, 9 meses
Puntos: 0
Exclamación Temporizadores con parámetros

Hola que tal bueno pues tengo un problema con los temporizadores realmente tengo como 1 mes en c++ pero no es problema ya que vengo de otros lenguajes...

Mi problema es que yo puedo hacer un temporizador para ejecutar mi función ejemplo

Código PHP:
HWND hwndBans;

UINT_PTR Bans;

void UnBan();

void cualquierfuncion()
{
     
Bans SetTimer(hwndBans05000, (TIMERPROCUnBan); // 5 Seg
}

void UnBan()
{
     ......

Bien ese código esta bien y me funciona a los 5 segundos pero intento hacer esto

Código PHP:

#define MAX_BANS 50

HWND hwndBans;

UINT_PTR Bans[MAX_BANS];

int UnBan();

void cualquierfuncion()
{
     
// Iterator for...
     
{
            
Bans[i] = SetTimer(hwndBans05000, (TIMERPROCUnBan(i)); // 5 Seg
     
}
}

int UnBan(int id)
{
     ......

Debería ejecutarse igual a los 5 Seg siendo que ahora tiene un parametro tipo integer.

Lo que hace es ejecutarse inmediatamente como si el tiempo fuera de 0 osea instantáneo por lo que creo que esa no es la manera correcta de llamar una función con parámetros desde SetTimer. Si alguien sabe como hacer un temporizador para llamar una función con parámetros le agradezco.
  #2 (permalink)  
Antiguo 14/10/2013, 11:41
Avatar de vangodp  
Fecha de Ingreso: octubre-2013
Mensajes: 934
Antigüedad: 10 años, 7 meses
Puntos: 38
Respuesta: Temporizadores con parámetros

prueba por referencia...

void UnBan(int &id)
{
......
}
  #3 (permalink)  
Antiguo 14/10/2013, 12:00
 
Fecha de Ingreso: julio-2011
Mensajes: 8
Antigüedad: 12 años, 9 meses
Puntos: 0
Respuesta: Temporizadores con parámetros

Hola gracias por la pronta respuesta pero no funcionó.

Y Una de las cosas que si lo coloco tipo void

en el

Bans[i] = SetTimer(hwndBans, 0, 5000, (TIMERPROC) UnBan(i));

Me da error:

Error 1 error C2440: 'conversión de tipo' : no se puede realizar la conversión de 'void' a 'TIMERPROC'

Eso pasa si la función es tipo void y a (TIMERPROC) UnBan(i) le coloque el (i) o los paréntesis o sea lo que sea que este dentro.. entonces no se ps :S
  #4 (permalink)  
Antiguo 14/10/2013, 12:13
 
Fecha de Ingreso: agosto-2012
Mensajes: 601
Antigüedad: 11 años, 8 meses
Puntos: 83
Respuesta: Temporizadores con parámetros

No puedes hacerlo asi porque UnBan() es una llamada a la funcion, es decir que la ejecuta al momento de asignar el puntero a la funcion de callback.

Puedes resolver con una lista de datos:

Código C:
Ver original
  1. struct TIMERDATA {
  2.     unsigned int idTimer;
  3.     unsigned int hTimer;
  4.     int data;
  5. };

Ahora tienes dos opciones, o bien usas una lista estatica de structs o bien las generas de forma dinamica, en ambos casos es lo de menos. Una vez tengas decidido como declarar los structs solo has de rellenar cada uno con los datos que quieras.

Suponiendo que vas a hacer una lista estatica puedes quitar el campo idTimer del struct porque el propio id será el orden del struct al que asignas el manejador de timer dentro de la lista:

Código C:
Ver original
  1. //esto tiene que ser global, que no caduque al terminar la funcion de crear timers
  2. struct TIMERDATA timerList[3];
  3.  
  4. //dentro de la funcion de crear timers
  5. for(q = 0; q < 3; q++) {
  6.     timerList[q].data = q+10;//un dato que me invento
  7.     timerList[q].hTimer = SetTimer(hwndBans, q, 5000, UnBan);
  8. }

Fijate en el truco: en tu codigo todos los timers tienen un identificador 0, con lo que no puedes diferenciarlos a menos que llames a diferentes callbacks. En este caso asigno como identificador del timer el orden del struct que contiene su manejador.

Ahora declaras el callback, pero antes echa un vistazo a tu manual de referencia de las funciones TIMERPROC para ver los argumentos: en tu codigo solo tienes un argumento cuando esa funcion soporta 4 y cada uno tiene su utilidad.

Código C:
Ver original
  1. void CALLBACK UnBan(HWND hwnd, unsigned int msg, unsigned id, unsigned long st) {
  2.     ...
  3. }

Los argumentos son: el 'hwnd' será el hwnd con que creaste el timer, en este caso todos fueron hwndBans; el 'msg' siempre será WM_TIMER (en otros casos puede variar, pero en el callback de un SetTimer siempre es el mismo); el 'id' es el identificador con que creaste el timer, es decir que es el orden del struct dentro de la lista donde guardaste el manejador del handler; y 'st' es el retorno de GetTickCount al momento de llamar al callback (el nº de ms desde que arrancó windows).

Supongo que ya te has dado cuenta de como recuperar los datos: el identificador te sirve como indice de la lista de datos de timer; la unica comprovacion de error es que el identificador sea menor que el nº de elementos de la lista de structs:

Código C:
Ver original
  1. struct TIMERDATA *ptr;
  2.  
  3. if((ptr = (id < 3)? &timerList[id] : 0)) {
  4.     //ya lo tienes
  5. }

Una ultima cosa que seguramente ya sabes, pero te la comento igual (es lo que te comente al principio): ojo con los scope de los datos que se van a manejar desde los callbacks, y ojo tambien con trabajar desde un callback sobre una misma direccion de memoria. Para evitar perder los datos debes declararlos como globales o como memoria dinamica, y en caso necesario para evitar conflictos al trabajar sobre una misma variable puedes usar secciones criticas (todas las funciones para el manejo de variables y secciones criticas las tienes en el manual de referenacia o tambien en la msdn).

Saludos
vosk
  #5 (permalink)  
Antiguo 15/10/2013, 08:38
 
Fecha de Ingreso: julio-2011
Mensajes: 8
Antigüedad: 12 años, 9 meses
Puntos: 0
Respuesta: Temporizadores con parámetros

Bueno men no se pero no me funciona o no logro dar con el dato a ver lo puse tal cual me lo das y la id que devuelve es algo brutal que si 29000 - 30000 mientras que si i = 1 deberia devolver 1 etc...

Código PHP:
void CALLBACK UnBan(HWND hwndunsigned int msgunsigned idunsigned long st)
{
    
printf("EXECUTED: id %i",id);
    
ptr = (id MAX_BANS)? &timerList[id] : 0// Es obvio que ptr es = 0;

No logro dar con el dato yo solo quiero hacer un temporizador que se ejecute por x tiempo y me devuelva el dato del for por ejemplo...

Código PHP:
for....
{
    
timerList[i].hTimer SetTimer(hwndBansi3000SQL_UnBan); // si i=1 y despues i=7; como hago para que ese 1 y despues el 7 (Que son diferentes tiempos) muestre en la función..

No es posible que me devuelva el valor de i?
  #6 (permalink)  
Antiguo 15/10/2013, 12:48
 
Fecha de Ingreso: agosto-2012
Mensajes: 601
Antigüedad: 11 años, 8 meses
Puntos: 83
Respuesta: Temporizadores con parámetros

Tienes algo mal en el codigo que omites. Te pongo un procedimiento principal aislado que funciona correctamente (compila como aplicacion de consola aun cuando es aplicacion gui, solo para ver los printf):

Código C:
Ver original
  1. struct TIMERDATA {
  2.     unsigned int hTimer;
  3.     int data;
  4. };
  5. struct TIMERDATA timerList[3];
  6.  
  7.  
  8.  
  9. void CALLBACK UnBan(HWND hwnd, unsigned int msg, unsigned id, unsigned long st) {
  10.         struct TIMERDATA *ptr;
  11.  
  12.         if((ptr = (id < 3)? &timerList[id] : 0)) {
  13.             printf("ID %d, DATA %d\n", id, ptr->data);
  14.             ptr->data += 1;//modifico para comprovar que funciona
  15.         }
  16. }
  17.  
  18.  
  19. LRESULT CALLBACK procedimientoPrincipal(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
  20.     switch(msg) {
  21.         case WM_CREATE: {
  22.             int q;
  23.  
  24.             for(q = 0; q < 3; q++) {
  25.                 timerList[q].data = q+10;
  26.                 timerList[q].hTimer = SetTimer(hwnd, q, 2000, UnBan);
  27.  
  28.                 Sleep(500);//delay para que no salten todos a la vez, no es necesario
  29.             }
  30.         }
  31.         break;
  32.         case WM_CLOSE: {
  33.             DestroyWindow(hwnd);
  34.         }
  35.         break;
  36.  
  37.         case WM_DESTROY: {
  38.             PostQuitMessage(0);
  39.         }
  40.         break;
  41.  
  42.         default: return DefWindowProc(hwnd, msg, wParam, lParam);
  43.     }
  44.  
  45.     return 0;
  46. }


Comprueba que esto funciona y como funciona, luego implementa en tu aplicacion y tiene que funcionar igual.

Saludos
vosk
  #7 (permalink)  
Antiguo 15/10/2013, 12:51
 
Fecha de Ingreso: agosto-2012
Mensajes: 601
Antigüedad: 11 años, 8 meses
Puntos: 83
Respuesta: Temporizadores con parámetros

Una cosa que me olvidaba: supongo que tu aplicacion está en modo gui; en modo consola los timers no funcionan de forma directa, pero puedes implementes un procesamiento de mensajes y solucionarlo; en cualquier caso si no indicas un hwnd valido la propia SetTimer omitirá tambien el identificador del timer.

Saludos
vosk
  #8 (permalink)  
Antiguo 15/10/2013, 13:36
 
Fecha de Ingreso: julio-2011
Mensajes: 8
Antigüedad: 12 años, 9 meses
Puntos: 0
Respuesta: Temporizadores con parámetros

Amigo de verdad te agradesco por la ayuda pero la verdad es que no funciona osea lo que haces con el codigo es dar muchas vueltas para caer en el mismo punto yo te digo que el problema es la id que me la devuelve con un numero excesivo osea segun tu codigo


Código PHP:
void CALLBACK UnBan(HWND hwndunsigned int msgunsigned idunsigned long st)
{
         
struct TIMERDATA *ptr// Aqui utilizas algo de mas seria mas facil hacer timerList[id].data me daria el mismo dato
 
        
if((ptr = (id 3)? &timerList[id] : 0)) { // Aqui compruebas que no se salga la id y esta bien
            
printf("ID %d, DATA %d\n"idptr->data);
            
ptr->data += 1;//modifico para comprovar que funciona
        
}


Pero como te digo se supone que timerList[id].data -> en id debería ser de 0 a 2 cierto? entonces funcionaria pero a mi no me da la id que yo le coloco.

Código PHP:
int q;
 
            for(
03q++) {
                
timerList[q].data q+10;
                
timerList[q].hTimer SetTimer(hwndq2000UnBan); // El 2do parametro es la ID que seria 0,1 y 2 que es la id que deberia devolver 
 
                
Sleep(500);//delay para que no salten todos a la vez, no es necesario
            

Pero a mi en vez de devolver 0 = 19900, 1 = 29941, 2 = 18348 (Solo puse números al azar que es lo que me devuelve de ID).

Como te digo como lo ponga la id que me devuelve es in-detectable...
  #9 (permalink)  
Antiguo 15/10/2013, 14:28
 
Fecha de Ingreso: julio-2011
Mensajes: 8
Antigüedad: 12 años, 9 meses
Puntos: 0
Respuesta: Temporizadores con parámetros

Bueno n creo que esto influya pero estoy trabajando con una *.dll
  #10 (permalink)  
Antiguo 15/10/2013, 15:14
 
Fecha de Ingreso: agosto-2012
Mensajes: 601
Antigüedad: 11 años, 8 meses
Puntos: 83
Respuesta: Temporizadores con parámetros

Tampoco yo creo que influya el trabajar con una dll, si tengo un momento lo probaré a ver que no sea eso. Por lo demas me parece que esta es la unica forma (hay varias versiones pero se basan en lo mismo: guardar la lista dinamica, guardar la lista en la cbWndExtra del WNDCLASSEX con el que vas a trabajar y recuperar el handler de la ventana a traves de hwnd que recibes en el callback, etc).

En caso de que el echo de trabajar con una dll si influya comprueba lo siguiente:

Comprueba el valor de retorno de todos los SetTimer: 0 para error, >0 para success. Si retorna >0 será un identificador del timer interno (el que se indica como nIDEvent en SetTimer será un identificador de usuario, no tienen porque ser iguales).

Comprueba que los valores retornados no sean los que obtienes como identificador interno del timer (los que retorna la funcion SetTimer). En caso de que sean el mismo valor se tendria que modificar el trabajo, para recuperarlo recorrer la lista y recuperar la struct donde coinciden el id del timer con el hTimer de la struct (ya sea a lo cutre por fuerza bruta, o usando algun tipo de listas de acceso rapido). La idea de la estructura es para guardar mas datos sobre el timer y poder automatizar el proceso; en el ejemplo que te puse hTimer no coincide con nIDEvent, pero necesito nIDEvent como indice del elemento en la lista, y tambien hTimer para matar el proceso en caso necesario.

Una otra cosa: en esta aplicacion estos timers son los unicos que manejas? Y la funcion callback se ejecuta unicamente desde los timers? Si no es asi esto significaria que no recibes los eventos de los timers esperados.

Por cierto, lo que me comentas de usar un puntero donde recuperar los datos es para facilitar la lectura de codigo: elimina la ambiguacion porque en el calback el 'id' no significa indice de elemento sino identificador del timer aun cuando en la practica y unicamente en este caso sean lo mismo.

En principio no se me ocurre nada mejor, siento no ser de mas ayuda.

Saludos
vosk
  #11 (permalink)  
Antiguo 15/10/2013, 16:18
 
Fecha de Ingreso: agosto-2012
Mensajes: 601
Antigüedad: 11 años, 8 meses
Puntos: 83
Respuesta: Temporizadores con parámetros

Como gesto de buena voluntad :)) te copio todo un proyecto con una dll que funciona correctamente; es decir que no influye el echo de estar en dll; incluso la dll la he echo en cpp y la aplicacion en c, donde la funcion de crear timers esta en la dll y el callback en la principal, mas interrelacion imposible y como podras ver funciona correctamente.

Código C++:
Ver original
  1. //dllmain.h
  2. #ifndef __MAIN_H__
  3. #define __MAIN_H__
  4.  
  5. #include <windows.h>
  6.  
  7. #ifdef BUILD_DLL
  8.     #define DLL_EXPORT __declspec(dllexport)
  9. #else
  10.     #define DLL_EXPORT __declspec(dllimport)
  11. #endif
  12.  
  13.  
  14. #ifdef __cplusplus
  15. extern "C"
  16. {
  17. #endif
  18.  
  19. struct TIMERDATA {
  20.     unsigned int hTimer;
  21.     int data;
  22. };
  23.  
  24.  
  25. void DLL_EXPORT crearTimers(HWND , struct TIMERDATA *, int , void CALLBACK (*cb)(HWND , unsigned int , unsigned int , unsigned long ));
  26.  
  27. #ifdef __cplusplus
  28. }
  29. #endif
  30.  
  31. #endif


Código C++:
Ver original
  1. //dllmain.cpp
  2. #include "dllmain.h"
  3.  
  4.  
  5. void DLL_EXPORT crearTimers(HWND hwnd, struct TIMERDATA *ptr_timerList, int numTimers, void CALLBACK (*cb)(HWND a, unsigned int b, unsigned int c, unsigned long d)) {
  6.     int q;
  7.  
  8.     for(q = 0; q < numTimers; q++) {
  9.         ptr_timerList[q].data = q+10;
  10.         ptr_timerList[q].hTimer = SetTimer(hwnd, q, 3000, cb);
  11.     }
  12. }
  13.  
  14.  
  15. extern "C" DLL_EXPORT BOOL APIENTRY DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) {
  16.     switch (fdwReason) {
  17.         case DLL_PROCESS_ATTACH:
  18.         break;
  19.         case DLL_PROCESS_DETACH:
  20.         break;
  21.         case DLL_THREAD_ATTACH:
  22.         break;
  23.         case DLL_THREAD_DETACH:
  24.         break;
  25.     }
  26.     return TRUE;
  27. }


Código C:
Ver original
  1. //aplicacion principal main.c
  2. #include <windows.h>
  3.  
  4. struct TIMERDATA {
  5.     unsigned int hTimer;
  6.     int data;
  7. };
  8. struct TIMERDATA timerList[3];
  9.  
  10.  
  11. typedef void (WINAPI *dllFuncion)(HWND , struct TIMERDATA *, int , void CALLBACK (*cb)(HWND , unsigned int , unsigned int , unsigned long ));
  12. dllFuncion crearTimers;
  13.  
  14.  
  15. void CALLBACK UnBan(HWND hwnd, unsigned int msg, unsigned int id, unsigned long st) {
  16.     struct TIMERDATA *ptr;
  17.  
  18.     if((ptr = (id < 3)? &timerList[id] : 0)) {
  19.         printf("ID %d, DATA %d\n", id, ptr->data);
  20.         ptr->data += 1;
  21.     }
  22. }
  23.  
  24.  
  25. LRESULT CALLBACK procedimientoPrincipal(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
  26.     switch(msg) {
  27.         case WM_CREATE: {
  28.             HINSTANCE hLib;
  29.             char modulo[256];
  30.  
  31.             if((hLib = LoadLibrary("dlltest.dll"))) {
  32.                 GetModuleFileName((HMODULE)hLib, (LPTSTR)modulo, sizeof(modulo));
  33.                 if((crearTimers = (dllFuncion)GetProcAddress((HMODULE)hLib, "crearTimers"))) {
  34.                     crearTimers(hwnd, timerList, 3, &UnBan);
  35.                 }
  36.                 else {
  37.                     MessageBox(hwnd, "Error GetProcAddress", "", MB_OK);
  38.                 }
  39.  
  40.                 FreeLibrary((HMODULE)hLib);
  41.             }
  42.             else {
  43.                 MessageBox(hwnd, "Error LoadLibrary", "", MB_OK);
  44.             }
  45.         }
  46.         break;
  47.  
  48.         case WM_CLOSE: {
  49.             DestroyWindow(hwnd);
  50.         }
  51.         break;
  52.  
  53.         case WM_DESTROY: {
  54.             PostQuitMessage(0);
  55.         }
  56.         break;
  57.  
  58.         default: return DefWindowProc(hwnd, msg, wParam, lParam);
  59.     }
  60.  
  61.     return 0;
  62. }

Compila la dll, copia el *.dll resultante en el proyecto de la aplicacion, crea una winmain para la aplicacion, compila y ejecuta. En este caso he importado manualmente las funciones del dll, por eso no hace falta incluir la cabecera ni linkar la libreria (aun en caso que el compilador te la cree).

Prueba esto y haz que funcione (funciona perfecto), luego implementa en tu aplicacion. Si cuando implementas en tu aplicacion no funciona es que tienes algo mal; si no funciona el ejemplo es que tambien estas haciendo algo mal. Editado en code::blocks, compilado con el mingw que viene por defecto, y ejecutado en windows7.

Suerte
Saludos
vosk
  #12 (permalink)  
Antiguo 16/10/2013, 07:59
 
Fecha de Ingreso: julio-2011
Mensajes: 8
Antigüedad: 12 años, 9 meses
Puntos: 0
Respuesta: Temporizadores con parámetros

Bueno de momento decidí irme por otro camino y cuando tenga tiempo realizo esto que estoy seguro que funcionará. Te agradesco mucho tu ayuda :D
  #13 (permalink)  
Antiguo 11/12/2014, 11:01
 
Fecha de Ingreso: agosto-2012
Ubicación: Colombia
Mensajes: 11
Antigüedad: 11 años, 8 meses
Puntos: 1
Respuesta: Temporizadores con parámetros

Hola el temporizador, básicamente es un un reloj digital o analógico que tiene un interruptor llamado relé. Estos relés actúan como los cambios de aguja de las vías, y son magnéticos (si se aplica una corriente se conecta o desconecta en función del tipo de relé, activo o pasivo. Los contactos pueden ser de cobre o recubiertos de algún metal noble.
Saludos!!!

http://astore.ekamm.com/es/394-temporizadores
  #14 (permalink)  
Antiguo 11/12/2014, 12:56
 
Fecha de Ingreso: octubre-2014
Ubicación: Madrid
Mensajes: 1.212
Antigüedad: 9 años, 7 meses
Puntos: 204
Respuesta: Temporizadores con parámetros

Cita:
Iniciado por yazminwse Ver Mensaje
Hola el temporizador, básicamente es un un reloj digital o analógico que tiene un interruptor llamado relé. Estos relés actúan como los cambios de aguja de las vías, y son magnéticos (si se aplica una corriente se conecta o desconecta en función del tipo de relé, activo o pasivo. Los contactos pueden ser de cobre o recubiertos de algún metal noble.
Saludos!!!

http://astore.ekamm.com/es/394-temporizadores
Tu que te has fumado?? Que tendrá que ver un temporizador mecánico con uno software??

No sera que te aburrías?

Etiquetas: funcion, int
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 12:34.