Próbuję zsynchronizować przewijanie dwóch komponentów TDBGrid w aplikacji VCL Forms, mam problemy z przechwytywaniem WndProc każdego komponentu siatki bez problemów z stosami. Próbowałem wysyłać wiadomości WM_VSCROLL pod przewijanymi zdarzeniami, ale nadal powoduje to nieprawidłowe działanie. Musi działać, aby kliknąć pasek przewijania, a także podświetlić komórkę lub przycisk myszy w górę lub w dół. Cała idea polega na tym, aby dwie siatki obok siebie wyświetlały rodzaj pasującego okna dialogowego.Zsynchronizowane składniki przewijania Delphi
Tried
SendMessage(gridX.Handle, WM_VSCROLL, SB_LINEDOWN, 0);
także
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;
I
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;
Pierwsza jest tylko rozwiązaniem tymczasowym, druga powoduje nieprawidłowe odczytanie pamięci, a trzecia powoduje przepełnienie stosu. Dlatego żadne z tych rozwiązań nie działa dla mnie. Chciałbym trochę informacji na temat tego, jak wykonać to zadanie! Z góry dziękuję.
AKTUALIZACJA: Rozwiązanie
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;
Dzięki - Sertac Akyuz do rozwiązania. Po zintegrowaniu z aplikacjami formularzy VCL za pomocą siatek, będą się wzajemnie zwijać podczas przewijania i zaznaczania wybranego rekordu.
Otrzymuję błędy przepełnienia stosu podczas próby użycia 'odziedziczonego WndProc (Msg)' Również gdy mam kod, jak pokazano, otrzymuję niepoprawne odczyty pamięci i innych błędów środowiska wykonawczego. Nie jesteś pewien, czy to jedyny sposób na wykonanie tego zadania? – wfoster
Co to jest "odziedziczony WndProc'?", Podałeś część kodu, która zastępuje 'WindowProc' siatki. Gdzie zastępujesz "WndProc"? Edytuj pytanie, aby wyświetlić odpowiedni kod. –
Moje przeprosiny, zobacz zmiany – wfoster