最近在做WinCE平台的应用程序的开发,采用SDK编程,对窗口中有滚动条的时候处理上有一些问题,主要是刷新、重绘页面的问题,特别向大虾们请教:1. 当启动程序运行时,窗口中还没有任何的内容,我希望窗口上不出现滚动条。这是问题一。2. 触发某一个事件以后(比如按下某个按键等等),窗口页面中就会出现相关的内容,这些内容包含了自定义的Text控件(文本控件),Button控件(按钮控件),Input控件(输入控件)等等(这些控件都是自己定义和实现的,和MFC上的那些不太一样)。当窗口页面上的内容很多,当前窗口显示不下的时候,就出现滚动条。(这个需要计算页面中所有控件,比较他们的坐标,从而得到最大的宽度和高度以后,设置滚动条,虽然可以,但是页面上控件比较多,有些麻烦。)这个是问题二。3. 就是拖动水平或者是垂直滚动条时,刷新重绘的问题。这个是问题三。
对于问题1,预先定义一个大的高度,初始运行显示滚动条,但是灰色的,没有滚动块的。
            
对于问题2,开始觉得可以再创建一个子控件窗口,将子控件窗口嵌入到主窗口中,将控件的绘制全部放在子窗口中进行,这样对于问题3,就比较简单了,就是先计算出滚动的距离,然后重新在主窗口中绘制子窗口。对于这个还有一个想法,就是类似MFC中的那个改变窗口源点的坐标SetWindowOrg,SetWindowOrgEx,SetViewportOrg等等之类的函数,这样在刷新的时候就不用一个个的改变页面中所有控件的坐标了,这个最简单,但是SDK中不知道如何实现的。对于问题3,取决于问题2的方法。
各位高手,你们有什么好的方法,或者是比较很容易实现的方法或者是例子,请指点一下,谢谢!!!

解决方案 »

  1.   

    最近刚刚做了个SDK SCROLL WND的封装类.我说说我的实现方法吧.1.SCROLL BAR的显示与否,调用ShowScrollBar
    ::ShowScrollBar(GetHandle(), SB_HORZ, TRUE);
    2.如果需要显示SCROLLBAR,在ShowScrollBar之后,需要设置SCROLLBAR的滚动参数SetScrollInfo si.nMin = 0;
    si.nMax = (nViewWidth - rcClient.right) / m_nScrollLineDP + m_nScrollPageDP;
    si.nPos = 0;
    si.nPage = m_nScrollPageDP;
    ::SetScrollInfo(GetHandle(), SB_HORZ, &si, TRUE);3.现在SCROLLBAR有了,并且也能滚动了.然后在滚动消息中,更新画面:
     因为我封装的时候,考虑到了画面的缩放.所以在SCROLLBAR的滚动消息中,
     A.重新计算视角偏移参数 GetViewInfo 这个函数主要计算出SetWindowOrgEx中的坐标
     B.调用UpdateWindow更新背景,我在WM_ERASEBKGND消息中,设置DC的逻辑坐标与设备坐标,并且设置WindowOrg.
    MESSAGE_HANDLER(WM_HSCROLL, OnHScroll)LRESULT CKScrollWnd::OnHScroll(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
    {
    //HDC hdc;
    int nPos;
    SCROLLINFO si; // Get all the vertial scroll bar information
    si.cbSize = sizeof(si);
    si.fMask  = SIF_ALL;
    // Save the position for comparison later on
    ::GetScrollInfo(GetHandle(), SB_HORZ, &si);
    nPos = si.nPos;
    switch (LOWORD(wParam))
    {
    // user clicked left arrow
    case SB_LINELEFT: 
    si.nPos -= si.nPage;
    break;
    // user clicked right arrow
    case SB_LINERIGHT: 
    si.nPos += m_bScrollLinePage ? si.nPage : 1;
    break;
    // user clicked the scroll bar shaft left of the scroll box
    case SB_PAGELEFT:
    si.nPos -= m_bScrollLinePage ? si.nPage : 1;
    break;
    // user clicked the scroll bar shaft right of the scroll box
    case SB_PAGERIGHT:
    si.nPos += si.nPage;
    break;
    // user dragged the scroll box
    case SB_THUMBTRACK:
    si.nPos = si.nTrackPos;
    break;
    default:
    break;
    }
    // Set the position and then retrieve it.  Due to adjustments
    // by Windows it may not be the same as the value set.
    si.fMask = SIF_POS;
    if (si.nPos >= si.nMax - (INT)si.nPage)
    {
    si.nPos = si.nMax;
    }
    ::SetScrollInfo(GetHandle(), SB_HORZ, &si, TRUE);
    ::GetScrollInfo(GetHandle(), SB_HORZ, &si); // If the position has changed, scroll the window 
    if (si.nPos != nPos)
    {
    //::ScrollWindow(GetHandle(), m_nScrollDP * (nPos - si.nPos), 0, NULL, NULL);
    GetViewInfo(&m_sizeDP, &m_sizeLP, &m_ptWindowOrg);
    ::InvalidateRect(GetHandle(), NULL, TRUE);
    ::UpdateWindow(GetHandle());
    }
    return 0;
    }
    4.现在SCROLLBAR滚动了,并且通知窗口刷新.这时候就可以设置DC的WindowOrg,并且重新绘制.BOOL CKScrollWnd::OnErasebkgnd(HDC hdc)
    {
    .
    .
    .
    SetScrollDCMapSize(hTargetDC); return TRUE;
    }BOOL CKScrollWnd::OnPaint(HDC hdc)
    {
    .
    .Draw 
    . return TRUE;
    }
    void CKScrollWnd::SetScrollDCMapSize(HDC hdc)
    {
    if (!hdc)
    {
    return;
    }
    ::SetMapMode(hdc, MM_ANISOTROPIC);
    ::SetWindowExtEx(hdc, m_sizeLP.cx, m_sizeLP.cy, NULL);
    ::SetViewportExtEx(hdc, m_sizeDP.cx, m_sizeDP.cy, NULL);
    ::SetWindowOrgEx(hdc, 
    m_ptWindowOrg.x, 
    m_ptWindowOrg.y, NULL);
    }
    因为通过SetWindowOrg实现,其他地方使用逻辑坐标绘图,所以不需要做其他处理.该怎么画还怎么画.
      

  2.   

    晕......审题不仔细啊!LZ是WINCE...我写的是非CE的类,LZ直接无视我的回复好了....
      

  3.   

    wince下的好多函数和window sdk里的都不一样吧,他有自己一套的sdk