gpt4 book ai didi

c++ - 使用 ScrollWindowEx 在 Cwnd 中滚动后控件消失

转载 作者:行者123 更新时间:2023-11-30 03:46:17 29 4
gpt4 key购买 nike

我在 Cwnd 中实现了一个 CScrollBar,但是在滚动之后窗口上的控件消失了。我听说我可以通过某种方式使用 DeferWindowPos,但我不知道该怎么做。有什么想法吗?

CPanel::CPanel()
{
CreateEx(WS_EX_CONTROLPARENT, _T("Static"), NULL, WS_CHILD | WS_TABSTOP | WS_BORDER, m_clRect, pwndParent, IDC_PANEL_FORM);
ScrollBarInit();
}

创建滚动条

void CPanel::ScrollBarInit()
{

//Before this i calculate size of scrollbar and size of scrollarea
m_pclScrollBar = new CScrollBar();
m_pclScrollBar->Create(WS_CHILD | WS_VISIBLE | SBS_VERT | SBS_RIGHTALIGN, clRectScrollbar, this, IDC_SCROLLBAR_FORM);
m_pclScrollBar->SetScrollRange(VSCROLL_RANGE_MIN, VSCROLL_RANGE_MAX);
//After this I add scrollbar info

}

处理消息

void CPanel::OnVScroll(UINT iSBCode, UINT iPos, CScrollBar* pclScrollBar)
{
switch(pclScrollBar->GetDlgCtrlID())
{
case IDC_SCROLLBAR_FORM:
ScrollBarScroll(iSBCode, iPos, pclScrollBar);
break;
}
}

滚动

void CPanel::ScrollBarScroll(UINT iSBCode, UINT iPos, CScrollBar *pclScrollBar)
{
int iScrollPositionPrevious;
int iScrollPosition;
int iScrollPositionOriginal;

iScrollPositionOriginal = m_pclScrollBar->GetScrollPos();
iScrollPosition = iScrollPositionOriginal;

if(m_pclScrollBar != NULL)
{
SCROLLINFO info = {sizeof( SCROLLINFO ), SIF_ALL};
pclScrollBar->GetScrollInfo(&info, SB_CTL);

pclScrollBar->GetScrollRange(&info.nMin, &info.nMax);
info.nPos = pclScrollBar->GetScrollPos();

iScrollPositionPrevious = info.nPos;

switch(iSBCode)
{
case SB_TOP: // Scroll to top
iScrollPosition = VSCROLL_RANGE_MIN;
break;

case SB_BOTTOM: // Scroll to bottom
iScrollPosition = VSCROLL_RANGE_MAX;
break;

case SB_ENDSCROLL: // End scroll
break;

case SB_LINEUP: // Scroll one line up
if(iScrollPosition - VSCROLL_LINE >= VSCROLL_RANGE_MIN)
iScrollPosition -= VSCROLL_LINE;
else
iScrollPosition = VSCROLL_RANGE_MIN;
break;

case SB_LINEDOWN: // Scroll one line down
if(iScrollPosition + VSCROLL_LINE <= VSCROLL_RANGE_MAX)
iScrollPosition += VSCROLL_LINE;
else
iScrollPosition = VSCROLL_RANGE_MAX;
break;

case SB_PAGEUP: // Scroll one page up
{
// Get the page size
SCROLLINFO scrollInfo;
m_pclScrollBar->GetScrollInfo(&scrollInfo, SIF_ALL);

if(iScrollPosition > VSCROLL_RANGE_MIN)
iScrollPosition = max(VSCROLL_RANGE_MIN, iScrollPosition - VSCROLL_PAGE);
break;
}

case SB_PAGEDOWN: // Scroll one page down
{
// Get the page size
SCROLLINFO scrollInfo;
m_pclScrollBar->GetScrollInfo(&scrollInfo, SIF_ALL);

if(iScrollPosition < VSCROLL_RANGE_MAX)
iScrollPosition = min(VSCROLL_RANGE_MAX, iScrollPosition + VSCROLL_PAGE);
break;
}

case SB_THUMBPOSITION: // Scroll to the absolute position. The current position is provided in nPos
case SB_THUMBTRACK: // Drag scroll box to specified position. The current position is provided in nPos
iScrollPosition = iPos;
break;

default:
break;
}

if(iScrollPositionOriginal != iScrollPosition)
{
m_pclScrollBar->SetScrollPos(iScrollPosition);

CRect clientArea;
GetClientRect(clientArea);

CRect scrollbarArea;
m_pclScrollBar->GetWindowRect(scrollbarArea);

CRect scrollArea(clientArea);
scrollArea.DeflateRect(0, 0, scrollbarArea.Width(), 0);
ScrollWindowEx(0, iScrollPositionOriginal - iScrollPosition, scrollArea, NULL,
NULL, NULL, SW_SCROLLCHILDREN | SW_INVALIDATE | SW_ERASE);
}
}
}

最佳答案

使用 CWnd::ScrollWindowEx 移动子窗口使用 SW_SCROLLCHILDREN 标志是有问题的:

If the SW_SCROLLCHILDREN flag is specified, Windows will not properly update the screen if part of a child window is scrolled. The part of the scrolled child window that lies outside the source rectangle will not be erased and will not be redrawn properly in its new destination. Use the DeferWindowPos Windows function to move child windows that do not lie completely within the lpRectScroll rectangle.

解决方案是手动移动子窗口。 DeferWindowPos与调用 SetWindowPos 效果相同对于多个窗口,但经过优化以在单个调用中执行布局。这有助于减少视觉伪影,即控件似乎相对于彼此移动,直到一切都解决。

DeferWindowPos 需要一个保存新窗口属性的结构。它是通过调用 BeginDeferWindowPos 创建的,然后通过调用 DeferWindowPos 为每个窗口更新,最后发送给系统以使用 EndDeferWindowPos 执行重新定位。 .以下代码假设一个数组包含数组中所有子控件的 CWnd*cxcy 保存水平和垂直偏移。它旨在替换对 ScrollWindowEx 的调用:

CWnd* controls[] = { m_pEdit, m_pButton, ... };

HDWP hDwp = ::BeginDeferWindowPos( ARRAYSIZE( controls ) );

for ( size_t index = 0; index < ARRAYSIZE( controls ); ++index ) {
// Find the current window position
CRect wndRect;
controls[index]->GetWindowRect( wndRect );
// DeferWindowPos requires client coordinates, so we need to convert from screen coords
ScreenToClient( wndRect );
// Set the control's new position
hDwp = ::DeferWindowPos( hDwp, *controls[index], NULL,
wndRect.left + cx, wndRect.top + cy, 0, 0,
SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOSIZE |
SWP_NOZORDER );
}

// All new control positions have been recorded. Now perform the operation
::EndDeferWindowPos( hDwp );

关于c++ - 使用 ScrollWindowEx 在 Cwnd 中滚动后控件消失,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34154470/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com