简体   繁体   English

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

[英]MSDN (Owner Drawn) Listbox control freeze after scrolling

I'm working on an Owner-Drawn Listbox Control that i managed to create and populate without errors. 我正在使用一个所有者绘制的列表框控件,该控件可以成功创建和填充,并且没有错误。

Here's my problem : When i scroll it, the listbox and its parent window becomes unresponsive after scrolling for a few seconds.(with PgDown) 这是我的问题: 滚动几秒钟后,列表框及其父窗口变得无响应。(使用PgDown)

Note that : 注意 :

  • There's a lot of items in it (more than 4k) 里面有很多物品(超过4k)

  • The messages are still being processed, i can monitor them on the console and they are being sent and received. 消息仍在处理中,我可以在控制台上监视它们,并且它们正在被发送和接收。 Only difference is, WM_DRAWITEM is no longer sent... 唯一的不同是,不再发送WM_DRAWITEM ...

  • The items of the listbox are added via LB_ADDSTRING 列表框的项目是通过LB_ADDSTRING添加的

What i tried : 我试过的

  • Using the PeekMessage function instead of the GetMessage 使用PeekMessage函数而不是GetMessage

-> Program crashes after the list is filled ->列表填充后程序崩溃

  • Redrawing the windows after the problem occurs (via a WM_LDOUBLECLICK event for example) 问题发生后重新绘制窗口(例如,通过WM_LDOUBLECLICK事件)

-> No effets ->没有效果

Code snippets : 代码段:

  • Window Procedure 窗口程序

     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; } 
  • Message Loop 讯息循环


    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;
  • Window creation 窗口创建

    WNDCLASSEX wc; 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); 

It looks like there's a timer somewhere, and if a keyboard touch stays too long down, it somehow messes everything up... 看起来好像在某个地方有一个计时器,如果键盘触摸的时间太长,就会以某种方式弄乱一切……

Has someone encountered a problem like this before or could help me understand what is going on ? 有人以前遇到过这样的问题吗,或者可以帮助我了解发生了什么?

You have a significant GDI resource leak in your code. 您的代码中有大量的GDI资源泄漏。

At the top of your WndProc function you're creating three brushes, and you never delete them. WndProc函数的顶部,您正在创建三个笔刷,并且永远不会删除它们。 These brushes are created every time your window processes a message. 每次窗口处理消息时都会创建这些画笔。

You should only create the brushes when you actually need them for painting, and call DeleteObject to release them when you're done with them. 您只应在实际需要绘画时才创建画笔,并在完成使用后调用DeleteObject释放它们。

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

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