Estoy tratando de sincronizar el desplazamiento de dos componentes TDBGrid en una aplicación de formularios VCL, tengo dificultades para interceptar el WndProc de cada componente de cuadrícula sin algunos problemas de pila. He intentado enviar mensajes WM_VSCROLL bajo eventos de desplazamiento, pero esto todavía resulta en una operación incorrecta. Tiene que funcionar para hacer clic en la barra de desplazamiento, así como para resaltar una celda, o un botón para subir o bajar el mouse. La idea es tener dos cuadrículas una junto a la otra mostrando una especie de diálogo de coincidencia.Desplazamiento sincronizado Componentes Delphi
Probamos
SendMessage(gridX.Handle, WM_VSCROLL, SB_LINEDOWN, 0);
también
procedure TForm1.GridXCustomWndProc(var Msg: TMessage);
begin
Msg.Result := CallWindowProc(POldWndProc, gridX.Handle, Msg.Msg, Msg.wParam, Msg.lParam);
if (Msg.Msg = WM_VSCROLL) then
begin
gridY.SetActiveRow(gridX.GetActiveRow);
gridY.Perform(Msg.Msg, Msg.wParam, Msg.lParam);
SetScrollPos(gridY.Handle, SB_VERT, HIWORD(Msg.wParam), True);
end;
end;
Y
procedure TForm1.GridxCustomWndProc(var Msg: TMessage);
begin
if (Msg.Msg = WM_VSCROLL) then
begin
gridY.SetActiveRow(gridX.GetActiveRow);
gridY.Perform(Msg.Msg, Msg.wParam, Msg.lParam);
SetScrollPos(gridY.Handle, SB_VERT, HIWORD(Msg.wParam), True);
end;
inherited WndProc(Msg);
end;
El primero es solo una solución temporal, el segundo da como resultado lecturas de memoria no válidas y el tercero da como resultado un desbordamiento de pila. Entonces, ninguna de estas soluciones parece funcionar para mí. ¡Me encantaría obtener información sobre cómo lograr esta tarea! Gracias por adelantado.
ACTUALIZACIÓN: Solución
private
[...]
GridXWndProc, GridXSaveWndProc: Pointer;
GridYWndProc, GridYSaveWndProc: Pointer;
procedure GridXCustomWndProc(var Msg: TMessage);
procedure GridYCustomWndProc(var Msg: TMessage);
procedure TForm1.FormCreate(Sender: TObject);
begin
GridXWndProc := classes.MakeObjectInstance(GridXCustomWndProc);
GridXSaveWndProc := Pointer(GetWindowLong(GridX.Handle, GWL_WNDPROC));
SetWindowLong(GridX.Handle, GWL_WNDPROC, LongInt(GridXWndProc));
GridYWndProc := classes.MakeObjectInstance(GridYCustomWndProc);
GridYSaveWndProc := Pointer(GetWindowLong(GridY.Handle, GWL_WNDPROC));
SetWindowLong(GridY.Handle, GWL_WNDPROC, LongInt(GridYWndProc));
end;
procedure TForm1.GridXCustomWndProc(var Msg: TMessage);
begin
Msg.Result := CallWindowProc(GridXSaveWndProc, GridX.Handle, Msg.Msg, Msg.WParam, Msg.LParam);
case Msg.Msg of
WM_KEYDOWN:
begin
case TWMKey(Msg).CharCode of VK_UP, VK_DOWN, VK_PRIOR, VK_NEXT:
GridY.Perform(Msg.Msg, Msg.WParam, Msg.LParam);
end;
end;
WM_VSCROLL:
GridY.Perform(Msg.Msg, Msg.WParam, Msg.LParam);
WM_HSCROLL:
GridY.Perform(Msg.Msg, Msg.WParam, Msg.LParam);
WM_MOUSEWHEEL:
begin
ActiveControl := GridY;
GridY.Perform(Msg.Msg, Msg.WParam, Msg.LParam);
end;
WM_DESTROY:
begin
SetWindowLong(GridX.Handle, GWL_WNDPROC, Longint(GridXSaveWndProc));
Classes.FreeObjectInstance(GridXWndProc);
end;
end;
end;
procedure TForm1.GridXMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
GridY.SetActiveRow(GridX.GetActiveRow);
end;
procedure TForm1.GridYCustomWndProc(var Msg: TMessage);
begin
Msg.Result := CallWindowProc(GridYSaveWndProc, GridY.Handle, Msg.Msg, Msg.WParam, Msg.LParam);
case Msg.Msg of
WM_KEYDOWN:
begin
case TWMKey(Msg).CharCode of VK_UP, VK_DOWN, VK_PRIOR, VK_NEXT:
GridX.Perform(Msg.Msg, Msg.WParam, Msg.LParam);
end;
end;
WM_VSCROLL:
GridX.Perform(Msg.Msg, Msg.WParam, Msg.LParam);
WM_HSCROLL:
GridX.Perform(Msg.Msg, Msg.WParam, Msg.LParam);
WM_MOUSEWHEEL:
begin
ActiveControl := GridX;
GridX.Perform(Msg.Msg, Msg.WParam, Msg.LParam);
end;
WM_DESTROY:
begin
SetWindowLong(GridY.Handle, GWL_WNDPROC, Longint(GridYSaveWndProc));
Classes.FreeObjectInstance(GridYWndProc);
end;
end;
end;
procedure TForm1.GridYMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
GridX.SetActiveRow(GridY.GetActiveRow);
end;
Gracias a - Sertac Akyuz para la solución. Cuando se integran en una aplicación de formularios de VCL utilizando cuadrículas, se mimetizarán mutuamente al desplazarse y resaltarán el registro seleccionado.
Obtengo errores de desbordamiento de pila cuando trato de usar 'WndProc heredado (Msg)' Además, cuando tengo el código como lo he mostrado obtengo lecturas inválidas de memoria y otros errores de tiempo de ejecución. ¿No estoy seguro de si esta es la única forma de llevar a cabo la tarea? – wfoster
¿Qué 'WndProc heredado' ?, le dio una parte del código que reemplaza al' WindowProc' de una grilla. ¿Dónde anulas el 'WndProc'? Por favor edite la pregunta para mostrar el código relevante. –
Mis disculpas, véanse las ediciones – wfoster