lm68140318 发表于 2023-8-5 15:15:10

清除重绘


UINT func1(LPVOID pParam)   //线程函数
{
       
        BOOL b = ::InvalidateRect(hWnd, &rect, TRUE);//使客户区矩形区域的图形变得无效
        BOOL b1 = UpdateWindow(hWnd);//更新指定窗口的客户区
       

        int t = 1;//第一个点不能画直线
        short* g = (short*)pParam;
        for (int i = 0; i < zong / sizeof(short); i++) {
                if (t == 1) {
                        //移到起始点
                        ::MoveToEx(hdc, i, *(g+i), NULL);
                        t = 0;
                }
                else {
                        LineTo(hdc, i, *(g + i));//绘制直线
                }
               

        }

       
        return 0;
}


afx_msg LRESULT CMFCyinpinDlg::OnMM_WIM_DATA(WPARAM wParam, LPARAM lParam)
{
        WAVEHDR* pWaveHdr = (WAVEHDR*)lParam;
        memcpy(g_samples, pWaveHdr->lpData, pWaveHdr->dwBytesRecorded);//复制音频数据
        zong = pWaveHdr->dwBytesRecorded;
        CWinThread* pp = AfxBeginThread(func1, (short*)(g_samples), 0, 0, 0, NULL);//创建工作线程
               
        waveInAddBuffer(hWaveIn, pWaveHdr, sizeof(WAVEHDR));// 继续录制下一段音频数据
               
        return 0;
}




我的问题:在OnMM_WIM_DATA消息函数中获得麦克风音频 数据 后,创建线程绘出波形图

每次需要清除重新绘制,
可是BOOL b = ::InvalidateRect(hWnd, &rect, TRUE);//使客户区矩形区域的图形变得无效
        BOOL b1 = UpdateWindow(hWnd);//更新指定窗口的客户区
这两条 指令无效,没有清除原图像??







isdkz 发表于 2023-8-5 15:15:27

问题原因是在OnMM_WIM_DATA消息函数中,调用InvalidateRect和UpdateWindow函数无法清除原图像。这是因为这两个函数是用于窗口重绘的,而不是用于清除图像的。

要清除原图像,可以使用FillRect函数填充矩形区域。以下是修改后的代码:

afx_msg LRESULT CMFCyinpinDlg::OnMM_WIM_DATA(WPARAM wParam, LPARAM lParam)
{
    WAVEHDR* pWaveHdr = (WAVEHDR*)lParam;
    memcpy(g_samples, pWaveHdr->lpData, pWaveHdr->dwBytesRecorded); //复制音频数据
    zong = pWaveHdr->dwBytesRecorded;
   
    // 清除原图像
    RECT clientRect;
    GetClientRect(&clientRect);
    HDC hdc = GetDC();
    FillRect(hdc, &clientRect, (HBRUSH)GetStockObject(WHITE_BRUSH));
    ReleaseDC(hdc);
   
    CWinThread* pp = AfxBeginThread(func1, (short*)(g_samples), 0, 0, 0, NULL); //创建工作线程
   
    waveInAddBuffer(hWaveIn, pWaveHdr, sizeof(WAVEHDR)); // 继续录制下一段音频数据
   
    return 0;
}


在该代码中,首先通过GetClientRect函数获取客户区的矩形区域,然后使用GetDC函数获取设备上下文句柄,接着使用FillRect函数填充矩形区域为白色,最后使用ReleaseDC函数释放设备上下文句柄。

这样就能够清除原图像并重新绘制波形图了。

学习编程中的Ben 发表于 2023-8-5 15:17:50

问题分析:

根据你提供的代码,使用 ::InvalidateRect(hWnd, &rect, TRUE) 和 UpdateWindow(hWnd) 函数来清除并更新窗口,但是它们没有起到清除原图像的作用。

解决方案:
1. 确保 hWnd 是正确的窗口句柄,并且 rect 是要刷新的矩形区域。可以通过打印 hWnd 和 rect 的值来进行确认。

2. ::InvalidateRect(hWnd, &rect, TRUE) 函数会将指定的矩形区域标记为无效,并请求系统重绘该区域。但它并不会立即清除原图像,而是等待窗口重绘消息的到来。确保在正确的时机调用 InvalidateRect,比如在 OnMM_WIM_DATA 函数中。

3. UpdateWindow(hWnd) 函数用于立即发送重绘消息,但它只会触发一次重绘,而不会清除原图像。如果你想要清除原图像,可以在 OnPaint 函数中使用绘图操作覆盖之前的内容。

下面是修改后的代码示例:

afx_msg void CMFCyinpinDlg::OnPaint()
{
    CPaintDC dc(this);

    // 清除原图像的方法之一是使用背景色进行填充
    CRect rect;
    GetClientRect(rect);
    dc.FillSolidRect(rect, RGB(255, 255, 255)); // 使用白色填充背景

    // 在这里进行绘图操作,可以根据需要绘制波形图或其他图形

    CDialogEx::OnPaint();
}

afx_msg LRESULT CMFCyinpinDlg::OnMM_WIM_DATA(WPARAM wParam, LPARAM lParam)
{
    WAVEHDR* pWaveHdr = (WAVEHDR*)lParam;
    memcpy(g_samples, pWaveHdr->lpData, pWaveHdr->dwBytesRecorded);
    zong = pWaveHdr->dwBytesRecorded;

    CWinThread* pp = AfxBeginThread(func1, (short*)(g_samples), 0, 0, 0, NULL);

    waveInAddBuffer(hWaveIn, pWaveHdr, sizeof(WAVEHDR));

    Invalidate(); // 使整个窗口变得无效,触发重绘操作
    UpdateWindow(); // 立即发送重绘消息

    return 0;
}

在修改后的代码中,我们在 OnPaint 函数中使用 FillSolidRect 函数来填充背景色,实现清除原图像的效果。并且,在 OnMM_WIM_DATA 函数中调用了 Invalidate 来使整个窗口无效,并立即发送重绘消息使用 UpdateWindow 函数。这样就能够清除并更新窗口,正确显示波形图了。

如果回答对你有帮助,请给我一个最佳答案!{:10_254:}{:10_254:}{:10_254:}

学习编程中的Ben 发表于 2023-8-5 15:19:42

给个最佳答案呗!求你了!!!{:10_254:}
页: [1]
查看完整版本: 清除重绘