Buenas a todos!
Espero que la pandemia os esté tratando bien!
Os pongo un poco en antecedentes, para leer un código de barras a través de un lector yo lo hago vía Messages en VCL, el problema es al migrar esta aplicación a FireMonkey (cosas del cliente), soy incapaz de replicar el funcionamiento.
Os pongo un poco de código y os explico, yo en el Main de la aplicación VCL (no dejo abrir la aplicación más de una vez) en el .OnMessage tengo este código, que no hace más que comprobar dos tipos de mensajes, WM_KEYDOWN para apertura de un cajón portamonedas y cambiar el '.' por ',' y comprobar si lo que se pasa es una WM_CHAR entonces ahí procesar el código de barras:
Código:
procedure TfrMain.AppOnMessage( var Msg: TMsg; var Handled: Boolean);
begin
if (Msg.message = WM_KEYDOWN) then
begin
oMsg.hwnd := Msg.hwnd;
oMsg.message:= Msg.message;
oMsg.wParam := Msg.wParam;
oMsg.lParam := Msg.lParam;
oMsg.time := Msg.time;
oMsg.pt := Msg.pt;
if (Msg.wParam = VK_F9) then
begin
Handled := True; // le indicamos a windows que lo procesamos
// nosotros y no queremos que llege a la aplicación
if Assigned(OdaDisplay) then
begin
try
OdaDisplay.ClearDisplay;
OdaDisplay.OpenBoxNew;
except
end;
end;
end
else if Msg.wParam = VK_DECIMAL then
begin
PostMessage( Msg.Hwnd, wm_Char, Ord(','), 0 );
Handled := True;
end
else
ProcesarMensajeKeyDown( Msg, Handled );
end
else if (Msg.message = WM_CHAR) then
ProcesarMensajeChar( Msg,
Handled, tTimerCodBar,
ParmPerfil.PrefijoLectorCodBar,
ParmPerfil.SufijoLectorCodBar,
ParmPerfil.ForzarUpperCase );
end;
El procedimiento ProcesarMensajeChar no hace otra cosa que procesa (valga la redundancia) lo que le llega y hace un PostMessage con un mensaje personalizado que controlo para saber que lo que está llegando es un código de barras:
Código:
procedure ProcesarMensajeChar( var Msg: TMsg;
var Handled: Boolean;
tTimer : TTimer;
iPrefijo : Integer;
iSufijo : Integer;
bForzarUC: Boolean );
var
iBarType : TBarType;
sCaracter : Char;
hOwner : Hwnd;
iCodigo : Integer;
sBuffer : string;
i : Integer;
oEdit : TEdit;
begin
if (Msg.message = WM_CHAR) then
begin
Handled := False;
sCaracter := Chr(Msg.wParam);
if (iSufijo > 0) or (iPrefijo > 0) then
begin
if DebugCodBarKeyChar and not DebugCodBarKeyDown then
begin
if sCaracter <> #0 then
BufferCodBar := sCaracter+Format( '%d', [Msg.wParam] )+' ';
if Assigned(Screen.ActiveForm) then
PostMessage( Screen.ActiveForm.Handle, um_CodBar, 0, Longint( BufferCodBar ) );
Handled := True;
end;
if not Handled and LeyendoCodBar then
begin
if sCaracter = Chr(iSufijo) then
begin
sBuffer := '';
for i := 1 to Length(BufferCodBar) do
begin
if BufferCodBar[i] = #13 then
Continue;
sBuffer := sBuffer + BufferCodBar[i];
end;
LeyendoCodBar := False;
tTimer.Enabled := False;
// a veces es nil
if Assigned(Screen.ActiveForm) then
begin
BufferCodBar := TrimRight(sBuffer);
PostMessage( Screen.ActiveForm.Handle, um_CodBar, 0, Longint( BufferCodBar ) );
end;
end
else
begin
BufferCodBar := BufferCodBar + sCaracter;
if Length(BufferCodBar) = 50 then
begin
LeyendoCodBar := False;
tTimer.Enabled := False;
if Assigned(Screen.ActiveForm) then
SendKeys( PChar(BufferCodBar), True ); // bWait
BufferCodBar := '';
end;
end;
Handled := True;
end
else if (sCaracter = Chr(iPrefijo)) then
begin
if LeyendoCodBar then
begin
if (BufferCodBar > '') and
Assigned(Screen.ActiveForm) then
SendKeys(PChar(BufferCodBar), True ); // bWait
end;
BufferCodBar := '';
LeyendoCodBar := True;
Handled := True;
tTimer.Enabled := True; // no en desarrollo
// el sufijo es capturado por el control si esta seleccionado
if (Screen.ActiveControl is TCustomEdit) then
TCustomEdit(Screen.ActiveControl).SelLength := 0
else if Screen.ActiveControl is TCustomGrid then
SetSelectNullGrid( TCustomGrid(Screen.ActiveControl) );
end
else if bForzarUC then
begin
if Assigned(Screen.ActiveControl) then
begin
if (Screen.ActiveControl is TEdit) then
begin
oEdit := TEdit(Screen.ActiveControl);
if oEdit.CharCase = ecNormal then
begin
sBuffer := AnsiUpperCase(sCaracter);
Msg.wParam := Ord(sBuffer[1]);
end;
end
else if not (Screen.ActiveControl is TCustomMemo) and
not (Screen.ActiveControl is TCustomDCMemo) and
not (Screen.ActiveControl is TCustomEasyEdit) then
begin
sBuffer := AnsiUpperCase(sCaracter);
Msg.wParam := Ord(sBuffer[1]);
end
end;
end;
end;
end;
end;
Con esto consigo que en mis formularios solo tenga que añadir un procedimiento que esté a la espera de un mensaje tipo um_CodBar y ahí proceso la información específica para él.
Ahora ya en FireMonkey me resulta imposible controlar ni siquiera los mensajes que devuelve Windows...
He rebuscado y lo que he encontrado es el TMessageManager, con esto puedo hacer SendMessages y leerlo pero no controlo el dónde lo tengo que hacer cuando leo un código de barras.
La otra posibilidad es ir controlando objeto por objeto en el KeyDown por si lo introducido es un código de barras, porque solo nos interesan que en dos o tres objetos se pueda hacer una lectura.
Con lo fácil que era lo otro :'(
Gracias de antemano!
Saludos,
Quique.