MSDN(所有者绘制)滚动后冻结列表框控件

时间:2016-11-26 23:38:23

标签: c winapi scroll listbox msdn

我正在开发一个所有者绘制的列表框控件,我设法创建并填充而没有错误。

这是我的问题: 当我滚动它时,列表框及其父窗口在滚动几秒后变得无法响应。(使用PgDown)

请注意:

  • 其中有很多项目(超过4k)

  • 邮件仍在处理中,我可以在控制台上监控它们,然后发送和接收邮件。 唯一的区别是,不再发送WM_DRAWITEM ...

  • 列表框的项目通过LB_ADDSTRING

  • 添加

我尝试了什么:

  • 使用PeekMessage函数代替GetMessage

- >列表填写后程序崩溃

  • 问题发生后重新绘制窗口(例如,通过WM_LDOUBLECLICK事件)

- >没有效果

代码段:

  • 窗口过程

    LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
        {
            HBRUSH Brush;
            HBRUSH BLANK_BRUSH;
            HBRUSH BLUE_BRUSH;
            Brush = CreateSolidBrush(RGB(163, 255, 249));
            BLANK_BRUSH = CreateSolidBrush(RGB(255,255, 255));
            BLUE_BRUSH = CreateSolidBrush(RGB(0,0, 255));
            int tabs[13]={140,256,261,287,318,353,422,460,500,530,550,570,610};
            switch(msg)
            {
                HDC hdc ;
                PAINTSTRUCT ps ;
                PMEASUREITEMSTRUCT pmis;
                LPDRAWITEMSTRUCT Item;
                RECT rect ;
                rect.top=-50;
                rect.bottom=0;
                RECT rect2 ;
                rect.top=10;
                case WM_MEASUREITEM:
                    pmis = (PMEASUREITEMSTRUCT) lParam;
                    pmis->itemHeight = 17;
                    return TRUE;
                break;
                case WM_DRAWITEM:
                        Item = (LPDRAWITEMSTRUCT)lParam;
                        if (Item->itemState & ODS_FOCUS)
                        {
                            SetTextColor(Item->hDC, RGB(255,255,255));
                            SetBkColor(Item->hDC, RGB(0, 0, 255));
                            FillRect(Item->hDC, &Item->rcItem, (HBRUSH)BLUE_BRUSH);
                        }
                        else
                        {
                            SetTextColor(Item->hDC, RGB(0,0,0));
                            SetBkColor(Item->hDC, RGB(255, 255, 255));
                            FillRect(Item->hDC, &Item->rcItem, (HBRUSH)BLANK_BRUSH);
                        }
                        int len = SendMessage(Item->hwndItem , LB_GETTEXTLEN, (WPARAM)Item->itemID, 0);
                            if (len > 0)
                            {
                                LPCTSTR lpBuff = malloc((len+1)*sizeof(TCHAR));
                                len = SendMessage(Item->hwndItem , LB_GETTEXT, (WPARAM)Item->itemID, (LPARAM)lpBuff);
                                if (len > 0) {
                                    TabbedTextOut(Item->hDC,Item->rcItem.left, Item->rcItem.top,(LPARAM)lpBuff,len,13,&tabs,140);
                                }
                            }
                        return TRUE;
                break;
                case WM_CLOSE:
                    DestroyWindow(hwnd);
                break;
                case WM_PAINT:
                  hdc = BeginPaint (hwnd, &ps) ;
                  GetClientRect(hwnd, &rect);
                  SetBkColor(hdc, RGB(230,50,2));
                  SetBkMode(hdc,TRANSPARENT);
                  FillRect(hdc,&ps.rcPaint,Brush);
                  DrawText(hdc, TEXT("Liste des messages décodés: "), -1, &rect, DT_CENTER );
                  DrawText(hdc, TEXT("Numéro d'engin (4xxxy): "), -1, &rect, DT_LEFT );
                  EndPaint (hwnd, &ps);
                  return 0 ;
                case WM_DESTROY:
                    PostQuitMessage(0);
                break;
                case WM_ERASEBKGND:
                    return TRUE;
                break;
                default:
                    return DefWindowProc(hwnd, msg, wParam, lParam);
            }
           return 0;
    }
  • 消息循环


    BOOL bRet;
           while (1)
            {
                bRet = GetMessage(&Msg, NULL, 0, 0);
                if (bRet > 0)
                {
                    TranslateMessage(&Msg);
                    DispatchMessage(&Msg);
                }
                else if (bRet == 0){
                    break;
                }
                else
                {
                    printf("error\n");
                    return -1;
                }
            }
            return Msg.wParam;
  • 创建窗口

    WNDCLASSEX wc;

    wc.cbSize        = sizeof(WNDCLASSEX);
    wc.style         = 0;
    wc.lpfnWndProc   = WndProc;
    wc.cbClsExtra    = 0;
    wc.cbWndExtra    = 0;
    wc.hInstance     = hInstance;
    wc.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
    wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
    wc.lpszMenuName  = NULL;
    wc.lpszClassName = g_szClassName;
    wc.hIconSm       = LoadIcon(NULL, IDI_APPLICATION);
    
    RegisterClassEx(&wc);
    
    hwnd = CreateWindowEx(WS_EX_CLIENTEDGE,g_szClassName,"List of messages",WS_OVERLAPPEDWINDOW,0, 0, 1500, 1000,NULL, NULL, hInstance, NULL);
    ShowWindow(hwnd, nCmdShow);
    UpdateWindow(hwnd);
    
    if(hwnd == NULL)
    {
        return 0;
    }
        hwnd2 = CreateWindowEx(0,"LISTBOX" ,"Data",WS_CHILD |WS_HSCROLL |WS_VSCROLL |WS_BORDER|WS_THICKFRAME | LBS_USETABSTOPS | LBS_OWNERDRAWFIXED | LBS_NOTIFY | LBS_HASSTRINGS,15,70,1450,450,hwnd,(HMENU) NULL,hInstance,NULL);
    

看起来某个地方有一个计时器,如果键盘触摸时间过长,它会以某种方式混乱......

有人之前遇到过这样的问题,或者可以帮我理解发生了什么事吗?

1 个答案:

答案 0 :(得分:3)

您的代码中存在重大的GDI资源泄漏。

WndProc功能的顶部,您正在创建三个画笔,而您永远不会删除它们。每次窗口处理消息时都会创建这些画笔。

您只应在实际需要它们进行绘画时创建画笔,并在完成它们时调用DeleteObject释放它们。