简体   繁体   English

C ++:RedrawWindow()闪烁

[英]c++: RedrawWindow() Flickering

As a developer who is building a Custome Splitter Wnd using custom class inherited from CWnd. 作为使用从CWnd继承的自定义类构建Custome Splitter Wnd的开发人员。 Initially, the screen has one window (custom class - CTile) which has two buttons(vertical - split, horizontal - split). 最初,屏幕具有一个窗口(自定义类-CTile),该窗口具有两个按钮(垂直-拆分,水平-拆分)。 When user clicks one of two buttons, the red split bar is appeared and two child window (CTile) is appeared. 当用户单击两个按钮之一时,将显示红色的拆分栏,并显示两个子窗口(CTile)。 As you know, while user drag the red split bar, the child window must be modified. 如您所知,在用户拖动红色拆分栏时,必须修改子窗口。 What I say here is that at this moment, the flickering is appeared. 我在这里说的是,这时出现了闪烁。 The parent wnd has only three elements(two child windows and one split bar), so I think that it never require content of drawing. 父级wnd只有三个元素(两个子窗口和一个拆分栏),因此我认为它永远不需要绘图内容。 I mean WM_PAINT message handler. 我的意思是WM_PAINT消息处理程序。 Here's my code. 这是我的代码。

this->cDiv = new CDivider(this->wth_tile / 2, 1);
this->cDiv->CreateDivider(this, this->hgt_tile);

//cDiv is split bar I used custom class which is inherited from CWnd.
//CreateDivider() is also my self-defined method.

this->first_child = new CTile();

// As I mentioned above, CTile is divided child window which is also inherited from CWnd.

POINT pt;
pt.x = 0;
pt.y = 0;
this->first_child->CreateTile(this, this->cDiv->sd_pos, this->hgt_tile, pt);

this->second_child = new CTile();


pt.x = this->cDiv->sd_pos + 5;
pt.y = 0;

this->second_child->CreateTile(this, this->cDiv->sd_pos, this->hgt_tile, pt);

This is make movable split bar wnd creation code.

And next is about modified child window size while drag the split bar.

void CDivider::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default

POINT pt;
HDC hdc;
RECT rect;

this->parentWnd->GetWindowRect(&rect);

//convert the mouse coordinates relative to the top-left of
//the window
ClientToScreen(&point);
pt = point;
pt.x -= rect.left;
pt.y -= rect.top;

if (this->sd_mode == 1)
{
    ::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_SIZEWE));
    if (GetCapture() == this && this->dragged)
    {
        this->sd_pos = pt.x;
        if (pt.x != oldPos.x && nFlags & MK_LBUTTON)
        {
            this->length = this->parentWnd->hgt_tile;
            this->MoveWindow(this->sd_pos, 0, 4, this->length);
            this->parentWnd->ResizeParent();
            this->parentWnd->Invalidate();
            this->parentWnd->UpdateWindow();
            TRACE("Resize Parent\n");
            /*this->parentWnd->first_child->Invalidate();
            this->parentWnd->second_child->Invalidate();*/
        }
    }

}
else if (this->sd_mode == 2)
{
    ::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_SIZENS));

    if (GetCapture() == this && this->dragged)
    {
        this->sd_pos = pt.y;
        if (pt.y != oldPos.y && nFlags & MK_LBUTTON)
        {
            this->Invalidate();
            this->length = this->parentWnd->wth_tile;
            this->MoveWindow(0, this->sd_pos, this->length, 4);

            this->parentWnd->ResizeParent();
            this->parentWnd->Invalidate();
            this->parentWnd->UpdateWindow();
            TRACE("Resize Parent\n");
            /*this->parentWnd->first_child->Invalidate();
            this->parentWnd->second_child->Invalidate();*/
        }
    }
}

CWnd::OnMouseMove(nFlags, point);

} }

Here, parentWnd is split bar's parent window - just parent initial window. 在这里,parentWnd是拆分栏的父窗口-只是父初始窗口。 first_child and second_child is child divided windows. first_child和second_child是子划分的窗口。 sd_mode means that split method - vertical & horizontal. sd_mode表示拆分方法-垂直和水平。

Why doesn't this code work? 为什么此代码不起作用?

The flickering happens because painting is in most normal windows a two phase operation. 之所以发生闪烁,是因为在大多数普通窗口中,绘画是两阶段操作。 1. The background is erased, 2. The window is repainted. 1.删​​除背景,2.重新绘制窗口。

So the problem is the child window that needs redrawing. 因此,问题在于需要重绘的子窗口。 There are a lot of articles about non flickering painting. 关于无闪烁绘画的文章很多。

Also you can optimize the redrawing in just invalidating just the parts of windows that are affected. 您还可以仅使受影响的窗口部分无效就可以优化重绘。 You force a redraw of the complete windows. 您强制重新绘制完整的窗口。 That isn't ideal. 那不是理想的。 In such a case a large portion of the window might flicker. 在这种情况下,很大一部分窗口可能会闪烁。

BTW: RedrawWindow with the specific flags are better than calling Invalidate/Update sequences and may be a tick faster. 顺便说一句:具有特定标志的RedrawWindow比调用Invalidate / Update序列更好,并且可能更快。

Also it may be better to use a method to draw Bars with an XOR-Paining during dragging. 同样,在拖动过程中使用XOR-Paining绘制条形的方法可能更好。 And update the window size when the LButtonUp-Event happens. 并在LButtonUp-Event发生时更新窗口大小。 The way CSplitterWnd is doing it... you have the source. CSplitterWnd的执行方式...您已掌握源代码。 Look into it. 了解更多。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM