Estimado Carlos:
He preparado una prueba de diagn贸stico sobre tu ejemplo original del primer post. Conserva FOLDER, controles, posiciones y orden. No es un arreglo: busca separar el foco real de su indicador visual, sin volver a pedirte SetForegroundWindow/SetFocus ni el mensaje 295/196610 que ya no funcionaron.
El c贸digo no env铆a flechas, no cambia el foco ni el estado de interfaz y no abre MsgInfo. Consulta cada 100 ms el control con foco y WM_QUERYUISTATE del di谩logo y sus descendientes. Guarda una muestra cuando cambia y un latido por segundo en un archivo de tu carpeta temporal.
Comprobaci贸n realizada
El original y esta variante compilan y enlazan sin errores ni avisos con Harbour/FWH64 y mingw64/clang. En Wine 11.19 comprobamos creaci贸n del log, cambios de foco al recorrer con TAB, segunda vuelta y cierre normal con STOP al final. La prueba us贸 TAB sint茅tico; no reprodujo la diferencia entre doble clic y Enter. All铆 ui=0: eso NO descarta lo que ocurre en tu Windows. No est谩 probado en Windows real, xHarbour ni tu compilador.
C贸mo compararlo en tu Windows
- Comprueba primero el original sin registro, para confirmar que sigue el s铆ntoma.
- Compila este PRG completo con tu build habitual de FWH/Harbour, sin a帽adir el workaround de flechas ni MsgInfo.
- Abre el mismo EXE con doble clic. Recorre los controles con TAB, dejando aproximadamente un segundo en cada uno, y da una segunda vuelta. Anota d贸nde ves o no el punteado y cierra con Ok.
- Abre el mismo EXE seleccion谩ndolo y pulsandoEnter. Repite el recorrido y cierre.
- Abre la carpeta temporal con Win+R, escribe %TEMP% y busca los dos archivos carlos_focus_*.log. El nombre incluye PID y tiempo para separarlos. Indica cu谩l corresponde a cada modo de arranque. Si la compilaci贸n falla con tu kit, basta el error exacto y qu茅 Harbour/compilador usas; no hace falta cambiar tu aplicaci贸n.
Qu茅 registra y qu茅 no
focus identifica el HWND que tiene el foco; cada fila permite relacionarlo con su clase e ID. En ui, el bit 1 significa indicador de foco oculto y el bit 2 aceleradores ocultos; pueden combinarse con otros bits. No registra el texto de los campos ni las teclas pulsadas.
Es muestreo, no una traza de cada TAB: puede perder estados intermedios y el propio registro altera el tiempo de ejecuci贸n. Si al instrumentarlo desaparece el s铆ntoma, d铆noslo: no lo tomaremos como una correcci贸n. Con los dos resultados podremos decidir qu茅 medir despu茅s sin trasladar una flecha simulada a todos los di谩logos.
#include "FiveWin.ch"
function Main()
local oDlg, oFld, oRad, cVal := PadR("CARLOS", 20 ), lVal := .T., nVal:=3, nItem := 2
local cVal2, cVal3
cVal2 := cVal3 := Space(20)
DEFINE DIALOG oDlg SIZE 400, 400
// folder
@ 3, 1 FOLDER oFld PROMPTS "&1-One", "&2-Two", "&3-Three" SIZE 190, 120 OF oDlg
//page 1
@ 1, 1 GET cVal PICTURE "@!" SIZE 80, 10 OF oFld:aDialogs[ 1 ]
@ 2, 1 COMBOBOX nVal ITEMS {"UNO","DOS","TRES"} SIZE 80, 15 OF oFld:aDialogs[ 1 ]
@ 3, 1 CHECKBOX lVal PROMPT "Test" SIZE 80, 15 OF oFld:aDialogs[ 1 ]
@ 1, 100 RADIO oRad VAR nItem SIZE 120, 10 OF oFld:aDialogs[ 1 ] ITEMS "&4-Cuatro", "&5-Cinco", "&6-Seis" PIXEL
@ 9.5, 14 BUTTON "Ok" OF oDlg ACTION oDlg:End()
//page 2
@ 1, 1 GET cVal2 PICTURE "@!" SIZE 80, 10 OF oFld:aDialogs[ 2 ]
//page 3
@ 1, 1 GET cVal3 PICTURE "@!" SIZE 80, 10 OF oFld:aDialogs[ 3 ]
ACTIVATE DIALOG oDlg CENTERED ON INIT CVF_Start( oDlg:hWnd )
CVF_Stop()
return nil
/* Private diagnostic, not a fix. Controls and geometry above stay unchanged.
Polling cannot record every intermediate UI transition and changes timing.
No synthetic input, focus changes, UI-state changes, or message boxes. */
#pragma BEGINDUMP
#include <windows.h>
#include <stdio.h>
#include <string.h>
#include "hbapi.h"
#ifndef WM_QUERYUISTATE
#define WM_QUERYUISTATE 0x0129
#endif
static HWND cvf_root;
static FILE * cvf_log;
static UINT_PTR cvf_timer;
static DWORD cvf_start;
static char cvf_prev[32768];
static char cvf_now[32768];
static size_t cvf_used;
static DWORD cvf_lastwrite;
static void cvf_window( HWND h )
{
char cls[128], row[512];
int n;
if( ! IsWindow( h ) ) return;
cls[0] = 0;
GetClassNameA( h, cls, sizeof(cls) );
n = snprintf( row, sizeof(row),
" hwnd=%p parent=%p id=%d class=%s ui=%lu visible=%d enabled=%d\n",
(void *) h, (void *) GetParent(h), GetDlgCtrlID(h), cls,
(unsigned long) SendMessage(h,WM_QUERYUISTATE,0,0),
IsWindowVisible(h), IsWindowEnabled(h) );
if( n > 0 && (size_t)n < sizeof(row) && cvf_used + n + 1 < sizeof(cvf_now) )
{
memcpy(cvf_now+cvf_used,row,n); cvf_used += n; cvf_now[cvf_used]=0;
}
}
static BOOL CALLBACK cvf_enum( HWND h, LPARAM unused )
{
(void) unused; cvf_window(h); return TRUE;
}
static void cvf_sample( void )
{
DWORD tick;
if( !cvf_log || !IsWindow(cvf_root) ) return;
tick = GetTickCount();
cvf_used = (size_t)snprintf(cvf_now,sizeof(cvf_now),
"focus=%p foreground=%p root=%p\n", (void *)GetFocus(),
(void *)GetForegroundWindow(),(void *)cvf_root);
cvf_window(cvf_root);
EnumChildWindows(cvf_root,cvf_enum,0);
if( strcmp(cvf_now,cvf_prev) != 0 || tick-cvf_lastwrite >= 1000 )
{
fprintf(cvf_log,"t_ms=%lu\n%s\n",(unsigned long)(tick-cvf_start),cvf_now);
fflush(cvf_log); strcpy(cvf_prev,cvf_now); cvf_lastwrite=tick;
}
}
static VOID CALLBACK cvf_tick( HWND h, UINT m, UINT_PTR id, DWORD tick )
{
(void)h;(void)m;(void)id;(void)tick; cvf_sample();
}
HB_FUNC( CVF_STOP )
{
if(cvf_timer) { KillTimer(NULL,cvf_timer); cvf_timer=0; }
if(cvf_log) { fprintf(cvf_log,"STOP\n"); fclose(cvf_log);cvf_log=NULL; }
cvf_root=NULL;
}
HB_FUNC( CVF_START )
{
char dir[MAX_PATH], path[MAX_PATH]; DWORD n;
cvf_root=(HWND)(HB_PTRUINT)hb_parnint(1);
cvf_prev[0]=0;cvf_start=GetTickCount();cvf_lastwrite=cvf_start;
n=GetTempPathA(sizeof(dir),dir);
if(!n || n>=sizeof(dir)) { hb_retl(FALSE); return; }
if(snprintf(path,sizeof(path),"%scarlos_focus_%lu_%lu.log",dir,
(unsigned long)GetCurrentProcessId(),(unsigned long)cvf_start)>=(int)sizeof(path))
{ hb_retl(FALSE);return; }
cvf_log=fopen(path,"wb");
if(!cvf_log) { hb_retl(FALSE);return; }
fprintf(cvf_log,"Carlos p286618 diagnostic v1\n"
"Polling100ms, changes + heartbeat1s; not an event trace.\n"
"ui bit1=HIDEFOCUS bit2=HIDEACCEL bit4=ACTIVE.\n"
"No text values are collected. Instrumentation changes timing.\n");
cvf_sample();
cvf_timer=SetTimer(NULL,0,100,cvf_tick);
if(!cvf_timer) { fprintf(cvf_log,"ERROR SetTimer\n");fclose(cvf_log);cvf_log=NULL;hb_retl(FALSE);return; }
hb_retl(TRUE);
}
#pragma ENDDUMP
Referencia del mensaje de consulta: https://learn.microsoft.com/en-us/windows/win32/menurc/wm-queryuistate
Saludos,
FiveTech AI