加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

同步滚动组件Delphi

发布时间:2020-12-15 04:18:06 所属栏目:大数据 来源:网络整理
导读:我试图在VCL Forms应用程序中同步滚动两个TDBGrid组件,我很难拦截每个网格组件的WndProc而没有一些堆栈问题.我尝试在滚动事件下发送WM_VSCROLL消息,但这仍然导致不正确的操作.它需要用于单击滚动条,以及突出显示单元格或向上或向下鼠标按钮.整个想法是让两个
我试图在VCL Forms应用程序中同步滚动两个TDBGrid组件,我很难拦截每个网格组件的WndProc而没有一些堆栈问题.我尝试在滚动事件下发送WM_VSCROLL消息,但这仍然导致不正确的操作.它需要用于单击滚动条,以及突出显示单元格或向上或向下鼠标按钮.整个想法是让两个网格彼此相邻,显示一种匹配对话框.

试着

SendMessage( gridX.Handle,WM_VSCROLL,SB_LINEDOWN,0 );

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.lParam );
      SetScrollPos( gridY.Handle,SB_VERT,HIWORD( Msg.wParam ),True );
   end;
end;

procedure TForm1.GridxCustomWndProc( var Msg: TMessage );
begin
   if ( Msg.Msg = WM_VSCROLL ) then 
   begin
      gridY.SetActiveRow( gridX.GetActiveRow );
      gridY.Perform( Msg.Msg,True );
   end;
   inherited WndProc( Msg );
end;

First只是一个临时解决方案,第二个导致无效的内存读取,第三个导致堆栈溢出.所以这些解决方案似乎都不适用于我.我喜欢关于如何完成这项任务的一些意见!提前致谢.

更新:解决方案

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,LongInt( GridYWndProc ) );
end;

procedure TForm1.GridXCustomWndProc( var Msg: TMessage );
begin
   Msg.Result := CallWindowProc( GridXSaveWndProc,GridX.Handle,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.LParam );
         end;
      end;
      WM_VSCROLL:
         GridY.Perform( Msg.Msg,Msg.LParam );
      WM_HSCROLL:
         GridY.Perform( Msg.Msg,Msg.LParam );
      WM_MOUSEWHEEL:
      begin
         ActiveControl := GridY;
         GridY.Perform( Msg.Msg,Msg.LParam );
      end;
      WM_DESTROY:
      begin
         SetWindowLong( GridX.Handle,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,VK_NEXT:
            GridX.Perform( Msg.Msg,Msg.LParam );
         end;
      end;
      WM_VSCROLL:
         GridX.Perform( Msg.Msg,Msg.LParam );
      WM_HSCROLL:
         GridX.Perform( Msg.Msg,Msg.LParam );
      WM_MOUSEWHEEL:
      begin
         ActiveControl := GridX;
         GridX.Perform( Msg.Msg,Msg.LParam );
      end;
      WM_DESTROY:
      begin
         SetWindowLong( GridY.Handle,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;

感谢 – Sertac Akyuz的解决方案.当使用网格集成到VCL表单应用程序中时,它们将在滚动时相互模仿,并突出显示所选记录.

解决方法

您可能正在为两个网格实现消息覆盖. GridX滚动GridY,然后滚动GridX,反过来…… SO.您可以通过使用标志围绕块来保护表面滚动代码.
type
  TForm1 = class(TForm)
    [..] 
  private
    FNoScrollGridX,FNoScrollGridY: Boolean;
    [..]

procedure TForm1.GridXCustomWndProc( var Msg: TMessage );
begin
  Msg.Result := CallWindowProc(POldWndProc,Msg.lParam );

  if ( Msg.Msg = WM_VSCROLL ) then 
  begin
    if not FNoScrollGridX then
    begin
      FNoScrollGridX := True
      gridY.SetActiveRow( gridX.GetActiveRow );
      gridY.Perform( Msg.Msg,Msg.lParam );
//      SetScrollPos( gridY.Handle,True );
    end;
    FNoScrollGridX := False;
  end;
end;

GridY的类似代码.顺便说一下,你不需要SetScrollPos.

编辑:

TForm1 = class(TForm)
  [..]
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,LongInt(GridXWndProc));

  GridYWndProc := classes.MakeObjectInstance(GridYCustomWndProc);
  GridYSaveWndProc := Pointer(GetWindowLong(GridY.Handle,GWL_WNDPROC));
  SetWindowLong(GridY.Handle,LongInt(GridYWndProc));
end;

procedure TForm1.GridXCustomWndProc(var Msg: TMessage);
begin
  Msg.Result := CallWindowProc(GridXSaveWndProc,Msg.LParam);

  case Msg.Msg of
    WM_KEYDOWN:
      begin
        case TWMKey(Msg).CharCode of
          VK_UP,VK_NEXT:
            GridY.Perform(Msg.Msg,Msg.LParam);
        end;
      end;
    WM_VSCROLL: GridY.Perform(Msg.Msg,Msg.LParam);
    WM_MOUSEWHEEL:
      begin
        ActiveControl := GridY;
        GridY.Perform(Msg.Msg,Msg.LParam);
      end;
    WM_DESTROY:
      begin
        SetWindowLong(GridX.Handle,Longint(GridXSaveWndProc));
        Classes.FreeObjectInstance(GridXWndProc);
      end;
  end;
end;

procedure TForm1.GridYCustomWndProc(var Msg: TMessage);
begin
  Msg.Result := CallWindowProc(GridYSaveWndProc,VK_NEXT:
            GridX.Perform(Msg.Msg,Msg.LParam);
        end;
      end;
    WM_VSCROLL: GridX.Perform(Msg.Msg,Msg.LParam);
    WM_MOUSEWHEEL:
      begin
        ActiveControl := GridX;
        GridY.Perform(Msg.Msg,Msg.LParam);
      end;
    WM_DESTROY:
      begin
        SetWindowLong(GridY.Handle,Longint(GridYSaveWndProc));
        Classes.FreeObjectInstance(GridYWndProc);
      end;
  end;
end;

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读