FTP | CCD | Buscar | Trucos | Trabajo | Foros |
|
Registrarse | FAQ | Miembros | Calendario | Guía de estilo | Temas de Hoy |
|
Herramientas | Buscar en Tema | Desplegado |
#1
|
||||
|
||||
dichoso separador decimal
Hola a todos.
He rescatado este mensaje del historico de los foros unicamente con el proposito de "cerrarlo" y aclarar el tema del todo. En el hilo original preguntaba lo siguiente: Cita:
Cita:
Código:
initialization ThousandSeparator := ','; DecimalSeparator := '.'; Esta última es la aclaración que queria hacer Gracias andres |
#2
|
|||
|
|||
Pues, con tu permiso, Lepe, voy a reabrir el hilo.
A raíz de aquel mensaje tuyo, me quedé pensando si la razón de querer mostrar al usuario los números con "punto" para separación decimal tenía que ver con que el usuario de tu programa era algún residente extranjero que quería ver las cantidades "como en su país", pero por otra parte aclarabas que no querías tener que cambiarle la configuración regional a nivel de SO, lo cual me extrañó. Pensándolo un poco me he acordado de que con la llegada del Euro se ha popularizado el uso de los decimales, y muchos usuarios, sobre todo contables, demandan poder usar el punto del teclado numérico como lo que es, un separador decimal, pero si nuestro control DBAware sólo admite "comas", eso no es posible. Si éste es tu caso, la solución de cambiar el DecimalSeparator deja como efecto secundario el que las cantidades se muestren de forma distinta a lo habitual (es decir, a la americana), aunque consiga dar validez a dicho punto. De las varias soluciones que pensé para solucionarlo, la que me parece más acertada es la de interceptar la pulsación del punto decimal y transformarlo en una coma. Crear nuevos componentes heredados de los DBAware para controlar esto es "demasiao", más aún cuando habría que redefinir DBGrids, DBEdits ... etc, y no se me ocurre una forma mejor. Así que aquí va lo que tengo implementado: Código:
procedure TForm1.ApplicationEvents1Message(var Msg: tagMSG; var Handled: Boolean); begin if MapearPuntoAComa AND (Msg.message = WM_KEYDOWN) AND (Msg.wParam = VK_DECIMAL) AND (DecimalSeparator = ',') then begin Msg.message := WM_CHAR; // cambiamos el tipo de mensaje Msg.wParam := 44; // si omitimos la línea anterior, aquí sería Msg.wParam := 188; Handled := FALSE; end; end; Con esto, si tenemos la variable global MapearPuntoAComa a TRUE y se pulsa el . del teclado numérico, transformamos ese mensaje en uno que envía una coma, y asunto resuelto. En este caso he cambiado el tipo de mensaje de WM_KEYDOWN a WM_CHAR, la razón es que así le puedo asignar la coma directamente (ASCII 44). Si dejara el mensaje como WM_KEYDOWN, debería asignar el código ASCII 188, que es la tecla que genera la coma, pero esto sólo valdría para los "teclados españoles". Si alguien tiene alguna sugerencia sobre este tema, o lo ha resuelto de otro modo, bienvenida sea otra solución, seguro que a casi todos se os ha planteado esta cuestión.
__________________
Guía de Estilo |
#3
|
||||
|
||||
Cita:
Cita:
Pues, con su permiso, Andres, voy a usar el nuevo método |
#4
|
||||
|
||||
Muy interesante la solución de Andrés, yo hasta el momento lo resolvía interceptando la pulsación
de la tecla en el control correspondiente lo cual me llevaba a propagar el código ad infinitum, tantos controles afectados tantos eventos a programar o en su caso llamadas a una función centralizada. Como el applicationsEvents se dispara a cada momento, la variable semáforo propuesta por Andrés, entiendo que habría que abrirla solamente en los formularios en los cuales se fuese a dar ese tratamiento de cambio de punto por coma del teclado numérico. Y si estais de acuerdo en lo dicho entonces yo propondría el siguiente leve cambio en el código: Código:
procedure TForm1.ApplicationEvents1Message(var Msg: tagMSG; var Handled: Boolean); begin if MapearPuntoAComa then//Sino está activado salir cuanto antes. begin if (Msg.message = WM_KEYDOWN) AND (Msg.wParam = VK_DECIMAL) AND (DecimalSeparator = ',') then begin ShowMessage('Aquí estamos Andrés.'); Msg.message := WM_CHAR; // cambiamos el tipo de mensaje Msg.wParam := 44; // si omitimos la línea anterior, aquí sería Msg.wParam := 188; Handled := FALSE; end; end; end; Un Saludo.
__________________
Guía de Estilo de los Foros Cita:
Última edición por marcoszorrilla fecha: 19-04-2004 a las 16:01:48. |
#5
|
|||
|
|||
Aclarar que el código que modificas, Marcos, hace lo mismo que el que puse si está desactivada la directiva de comprobación booleana (ahora no recuerdo la letra de la directiva, su nombre es Complete Boolean Evaluation, es la que se encarga de abortar las comprobaciones cuando el resultado ya está claro, por eso MapearPuntoAComa está puesto en primer lugar, de forma que si es FALSE, sale del IF, es porque suelo tener dicha directiva para actuar de esa manera). Para evitar dependencias de directivas, conviene hacer lo que planteas, o bien poner la directiva delante de dicho código.
Pero, con tu permiso, Marcos, hay algo que me preocupa a nivel personal, y es que me estoy imaginando a vuestros clientes ladrando por el teléfono, con frases despectivas hacia mí, del tipo: "¿Quién k*ñ* es este Andrés que aparece cada vez que quiero meter una cantidad con decimales?" Lo digo por el ShowMessage ése, creo que resta eficiencia al asunto
__________________
Guía de Estilo Última edición por andres1569 fecha: 19-04-2004 a las 19:46:24. |
#6
|
||||
|
||||
De acuerdo Andrés, lo puse en la primera entrada, es decir debajo de MapearPuntoAcoma, para comprobar como es lógico que el evento se produce compulsivamente, por lo tanto es lógico desactivar la variable global también al salir de los formularios que la necesitan porque sino la continua evaluación puede restar velocidad a la aplicación.
En este caso como bien dices el cambio propuesto no tendría objeto ya que pusiste en primer lugar esa comprobación con lo cual al no cumplirse no evaluaría el resto. Un Saludo.
__________________
Guía de Estilo de los Foros Cita:
|
#7
|
||||
|
||||
Hola.
Yo lo tenía más fácil ya que en mis aplicaciones, en lugar de tener TDbEdits tengo unos componentes propios heredados del mismo (tienen un par de características propias, como que con el ENTER saltan al siguiente control, etc. ...). Así que añadí una nueva propiedad a mi TIdEditAvancat, llamada PuntsPerComes. Si la activo, cada vez que el usuario pulsa un punto en el control, es reemplazado por una coma. Código:
procedure TIdEditAvancat.KeyPress(var key: char); begin if FIntroPerTabulador then begin if key = #13 then begin key := #0; PostMessage( GetParentForm(Self).Handle, WM_NEXTDLGCTL,0,0 ); end; end; if FPuntsPerComes then if Key = '.' then Key := ','; if key <> #0 then inherited KeyPress(key); end; Saludos.
__________________
Marc Guillot (Hi ha 10 tipus de persones, els que saben binari i els que no). Última edición por guillotmarc fecha: 19-04-2004 a las 21:41:37. |
#8
|
||||
|
||||
Cita:
Un Saludo.
__________________
Guía de Estilo de los Foros Cita:
|
#9
|
||||
|
||||
Hola.
Cita:
Saludos.
__________________
Marc Guillot (Hi ha 10 tipus de persones, els que saben binari i els que no). |
|
|
|