我用的两个rich edit怎么共享一个滚动条,也就是一个滚动条如何控制两个editor滑动,或者一个滚动条如何在滚动同时让另外一个滚动条也滚动呢?

解决方案 »

  1.   

    在操作滚动条时RichEdit控件会收到WM_HSCROLL或WM_VSCROLL消息。自定控件消息处理函数,处理这个消息。 自定控件消息处理函数(控件子类化)// 默认消息处理函数地址
    WNDPROC DefControlProc;// 新消息处理函数
    INT_PTR CALLBACK MyControlProc(HWND hwnd,UINT message, WPARAM wParam, LPARAM lParam)
    {
    switch(message)
    {
    case WM_LBUTTONDOWN:
    ::MessageBox(NULL, "click!", "", MB_OK);
    }
    //调用控件原来的消息处理函数
    return CallWindowProc(DefControlProc, hwnd, message, wParam, lParam);
    }// 建立窗口后,更改消息处理函数
    case WM_CREATE:
    {
    // 嵌入新的消息处理函数
    DefControlProc = (WNDPROC)SetWindowLongPtr(hControlWnd, GWLP_WNDPROC, (LONG_PTR)MyControlProc);
    assert(DefControlProc != NULL);
    }
    建立一个全局变量,表示两滚动条是否已同步。
    当一个RichEdit控件收到滚动消息时,检查是否已同步。
    如果已同步,则直接把此消息交给默认消息处理函数处理;
    如果未同步,则向另一个RichEdit控件发送滚动消息,并设置已同步,再把此消息交给默认消息处理函数处理。
      

  2.   

    我的richedit的消息处理函数是EN_HSCROLL,和WM_HSCROLL有区别吗?我也添加了ENM_SCROLL,为啥滚动条没响应呢?
    还有楼上说的同步是通过同步滚动条的位置吗?谢谢啊
      

  3.   

    我自己用得没有任何问题,我把关键代码帖出来你看看
    HWND g_hEditOutputL; // 输出Edit控件L句柄
    HWND g_hEditOutputR; // 输出Edit控件R句柄WNDPROC DefControlProcL;
    WNDPROC DefControlProcR;
    volatile int bSyned = false;
    // 在主窗口建立时
    // 嵌入新的消息处理函数
    DefControlProcL = (WNDPROC)SetWindowLongPtr(g_hEditOutputL, GWLP_WNDPROC, (LONG_PTR)MyControlProcL);
    assert(DefControlProcL != NULL);
    DefControlProcR = (WNDPROC)SetWindowLongPtr(g_hEditOutputR, GWLP_WNDPROC, (LONG_PTR)MyControlProcR);
    assert(DefControlProcR != NULL);
    ///////////////////////////////////////////////////////////////////////////////
    // 新消息处理函数
    INT_PTR CALLBACK MyControlProcL(HWND hwnd,UINT message, WPARAM wParam, LPARAM lParam)
    {
        switch(message)
        {
        case WM_VSCROLL:
    {
    if (!bSyned)
    {
    PostMessage(g_hEditOutputR, WM_VSCROLL, wParam, lParam);
    bSyned = true;
    }
    else
    {
    bSyned = false;
    }
            break;
    }
        }
        //调用控件原来的消息处理函数
        return CallWindowProc(DefControlProcL, hwnd, message, wParam, lParam);
    }///////////////////////////////////////////////////////////////////////////////
    // 新消息处理函数
    INT_PTR CALLBACK MyControlProcR(HWND hwnd,UINT message, WPARAM wParam, LPARAM lParam)
    {
        switch(message)
        {
        case WM_VSCROLL:
    {
    if (!bSyned)
    {
    PostMessage(g_hEditOutputL, WM_VSCROLL, wParam, lParam);
    bSyned = true;
    }
    else
    {
    bSyned = false;
    }
            break;
    }
        }
        //调用控件原来的消息处理函数
        return CallWindowProc(DefControlProcR, hwnd, message, wParam, lParam);
    }
      

  4.   

    这个倒没试,用的是普通edit control。
      

  5.   

    这个处理函数直接添加到Dlg文件就可以了吗?
      

  6.   

    你在哪个文件里建立RichEdit控件(或者该控件的主窗口),就添加到哪个文件中。
      

  7.   

    刚才用RichEdit2.0试了,也用得很好。
      

  8.   

    我ASSERT那里报错啊,是把 
    DefControlProcL = (WNDPROC)SetWindowLongPtr(g_hEditOutputL, GWLP_WNDPROC, (LONG_PTR)MyControlProcL);
    assert(DefControlProcL != NULL);
    DefControlProcR = (WNDPROC)SetWindowLongPtr(g_hEditOutputR, GWLP_WNDPROC, (LONG_PTR)MyControlProcR);
    assert(DefControlProcR != NULL);
    加到OnInitDialog()吗?
      

  9.   

    fenghou1st 能不能说的再清楚点啊,我以前都没有自己重写过消息处理函数,这几部分东西分别加到哪里?
      

  10.   


    如果你是手动创建RichEdit控件的,就加到手动创建之后,使用控件之前。如果是自动创建的,就加到RichEdit控件所在窗口的初始化消息中。
    一般情况下就是加到OnInitDialog()中。
      

  11.   

    郁闷啊,还是assert(DefControlProcL != NULL)产生Assertion,
    我完整代码是这样的#include "stdafx.h"
    #include "test.h"
    #include "testDlg.h"
    #include <assert.h>#ifdef _DEBUG
    #define new DEBUG_NEW
    #endifvolatile int bSyned = false;HWND g_hEditOutputL;                                    // 输出Edit控件L句柄
    HWND g_hEditOutputR;                                    // 输出Edit控件R句柄WNDPROC DefControlProcL;
    WNDPROC DefControlProcR;INT_PTR CALLBACK MyControlProcL(HWND hwnd,UINT message, WPARAM wParam, LPARAM lParam)
    {
        switch(message)
        {
        case WM_VSCROLL:
            {
            if (!bSyned)
                {
                PostMessage(g_hEditOutputR, WM_VSCROLL, wParam, lParam);
                bSyned = true;
                }
            else
                {
                bSyned = false;
                }
            break;
            }
        }
        //调用控件原来的消息处理函数
        return CallWindowProc(DefControlProcL, hwnd, message, wParam, lParam);
    }///////////////////////////////////////////////////////////////////////////////
    // 新消息处理函数
    INT_PTR CALLBACK MyControlProcR(HWND hwnd,UINT message, WPARAM wParam, LPARAM lParam)
    {
        switch(message)
        {
        case WM_VSCROLL:
            {
            if (!bSyned)
                {
                PostMessage(g_hEditOutputL, WM_VSCROLL, wParam, lParam);
                bSyned = true;
                }
            else
                {
                bSyned = false;
                }
            break;
            }
        }
        //调用控件原来的消息处理函数
        return CallWindowProc(DefControlProcR, hwnd, message, wParam, lParam);
    }
    // CAboutDlg dialog used for App Aboutclass CAboutDlg : public CDialog
    {
    public:
          CAboutDlg();// Dialog Data
          enum { IDD = IDD_ABOUTBOX };      protected:
          virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support// Implementation
    protected:
          DECLARE_MESSAGE_MAP()
    };CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
    {
          
    }void CAboutDlg::DoDataExchange(CDataExchange* pDX)
    {
          CDialog::DoDataExchange(pDX);
    }BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
    END_MESSAGE_MAP()
    // CtestDlg dialog
    CtestDlg::CtestDlg(CWnd* pParent /*=NULL*/)
          : CDialog(CtestDlg::IDD, pParent)
    {
          m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
    }void CtestDlg::DoDataExchange(CDataExchange* pDX)
    {
          CDialog::DoDataExchange(pDX);
          DDX_Control(pDX, IDC_RICHEDIT21, RichEdit);
          //RichEdit.SetEventMask(ENM_SCROLL);
    }BEGIN_MESSAGE_MAP(CtestDlg, CDialog)
          ON_WM_SYSCOMMAND()
          ON_WM_PAINT()
          ON_WM_QUERYDRAGICON()
          //}}AFX_MSG_MAP
          
    END_MESSAGE_MAP()
    // CtestDlg message handlersBOOL CtestDlg::OnInitDialog()
    {     
          //RichEdit.SetEventMask(ENM_SCROLL);
          CDialog::OnInitDialog();      DefControlProcL = (WNDPROC)SetWindowLongPtr(g_hEditOutputL, GWLP_WNDPROC, (LONG_PTR)MyControlProcL);
        assert(DefControlProcL != NULL);
        DefControlProcR = (WNDPROC)SetWindowLongPtr(g_hEditOutputR, GWLP_WNDPROC, (LONG_PTR)MyControlProcR);
        assert(DefControlProcR != NULL);
          
          // Add "About..." menu item to system menu.      // IDM_ABOUTBOX must be in the system command range.
          ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
          ASSERT(IDM_ABOUTBOX < 0xF000);      CMenu* pSysMenu = GetSystemMenu(FALSE);
          if (pSysMenu != NULL)
          {
                CString strAboutMenu;
                strAboutMenu.LoadString(IDS_ABOUTBOX);
                if (!strAboutMenu.IsEmpty())
                {
                      pSysMenu->AppendMenu(MF_SEPARATOR);
                      pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
                }
          }
          // Set the icon for this dialog.  The framework does this automatically
          //  when the application's main window is not a dialog
          SetIcon(m_hIcon, TRUE);             // Set big icon
          SetIcon(m_hIcon, FALSE);            // Set small icon
          //RichEdit.SetEventMask(ENM_CHANGE|ENM_SCROLL);
          // TODO: Add extra initialization here
          CString blank=_T("\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n");
          CRichEditCtrl *MyRich;
          MyRich=(CRichEditCtrl*)GetDlgItem(IDC_RICHEDIT21);
          MyRich->ReplaceSel(blank);
          MyRich=(CRichEditCtrl*)GetDlgItem(IDC_RICHEDIT22);
          MyRich->ReplaceSel(blank);         return TRUE;  // return TRUE  unless you set the focus to a control
    }void CtestDlg::OnSysCommand(UINT nID, LPARAM lParam)
    {
          if ((nID & 0xFFF0) == IDM_ABOUTBOX)
          {
                CAboutDlg dlgAbout;
                dlgAbout.DoModal();
          }
          else
          {
                CDialog::OnSysCommand(nID, lParam);
          }
    }// If you add a minimize button to your dialog, you will need the code below
    //  to draw the icon.  For MFC applications using the document/view model,
    //  this is automatically done for you by the framework.void CtestDlg::OnPaint()
    {
          if (IsIconic())
          {
                CPaintDC dc(this); // device context for painting            SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);            // Center icon in client rectangle
                int cxIcon = GetSystemMetrics(SM_CXICON);
                int cyIcon = GetSystemMetrics(SM_CYICON);
                CRect rect;
                GetClientRect(&rect);
                int x = (rect.Width() - cxIcon + 1) / 2;
                int y = (rect.Height() - cyIcon + 1) / 2;            // Draw the icon
                dc.DrawIcon(x, y, m_hIcon);
          }
          else
          {
                CDialog::OnPaint();
          }
    }// The system calls this function to obtain the cursor to display while the user drags
    //  the minimized window.
    HCURSOR CtestDlg::OnQueryDragIcon()
    {
          return static_cast<HCURSOR>(m_hIcon);
    }
      

  12.   

    我没用MFC,不能帮你找出问题了。
    我的工程:RichEdit.zip - 5KB
      

  13.   

    你是自己加的RichEdit,你有自己的主窗口消息处理函数,所以能得到你自定义的消息,我的怎么都收不到滚动条的消息,哎我再研究研究,如果你能用MFC生成的话,帮我看看。郁闷的
      

  14.   

    搞定了,皆大欢喜,谢谢fenghou1st!给分了!