2014-10-29 120 views
-1

在我的win32應用程序中,我使用主線程中的稀疏信息(所有項目,但基本上只包含一個標籤)填充列表視圖。之後,我想開始從光盤讀取圖像和文本文件並更新相應的項目。這應該在單獨的線程(std::thread)中完成,因爲從圖像生成縮略圖並分析整個文本文件需要相當長的時間。 我已經嘗試直接從附加線程更新列表視圖的圖像列表,但是當我嘗試通過ListView_GetImageList()檢索指向圖像列表的指針時,應用程序崩潰。 所以我想以某種方式將新數據傳遞迴主線程並調用更新是個好主意。在這種情況下有沒有建議的方法可以做到這一點?如何從另一個線程更新列表視圖

更新: 這是我迄今爲止使用ScottMcP-MVP建議的方法的代碼。它調用的SendMessage()後引起無限循環:

#define WM_UPDATE_THUMBNAIL (WM_APP + 1) 

void loadThumbnail(HWND hwndMain, size_t index, std::string file) 
{ 
    HBITMAP thumbnail = GenerateThumbnail(file, THUMBNAIL_WIDTH, THUMBNAIL_HEIGHT); 
    SendMessage(hwndMain, WM_UPDATE_THUMBNAIL, (WPARAM)thumbnail, (LPARAM)index); 
} 

bool UpdateListView(HWND hwndMain) 
{ 
    HWND listview = GetDlgItem(hwndMain, IDC_BROWSE_LIST); 
    if (!listview) return false; 

    // clear previous data 
    ListView_DeleteAllItems(listview); 
    ImageList_Destroy(ListView_GetImageList(listview, LVSIL_NORMAL)); 

    // create a new image list 
    HIMAGELIST imageList = ImageList_Create(THUMBNAIL_WIDTH, THUMBNAIL_HEIGHT, ILC_COLOR24, nItems, 1); 
    ListView_SetImageList(listview, imageList, LVSIL_NORMAL); 

    // add all items with label only 
    for (size_t iItem = 0; iItem < items.size(); ++iItem) { 
     LVITEM lvItem; 
     lvItem.iSubItem = 0; 
     lvItem.state = 0; 
     lvItem.iItem = (int)iItem; 
     lvItem.mask = LVIF_TEXT; 
     lvItem.pszText = items[iItem].label; 
     lvItem.cchTextMax = 256; 
     ListView_InsertItem(listview, &lvItem); 
     std::thread t(loadThumbnail, m_hWnd, iItem, items[iItem].thumbnailFile); 
    } 
    return true; 
} 

INT_PTR CALLBACK DialogProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) 
{ 
    switch (message) { 
     // ... 
     case WM_UPDATE_THUMBNAIL: { 
      // this block is never reached 
      break; 
     } 
    } 
} 
+3

[SendMessage](http://msdn.microsoft.com/en-gb/library/windows/desktop/ms644950%28v=vs.85%29.aspx)。從UI線程中只做UI的東西是最安全的。使用'SendMessage'可以讓你做到這一點。此外,它有助於讓[MCVE](http://stackoverflow.com/help/mcve)顯示您嘗試過的內容。 – icabod 2014-10-29 12:49:27

+1

您需要兩種成分來解決此問題:'1'使用[虛擬列表視圖](http://msdn.microsoft.com/en-us/library/windows/desktop/bb774735.aspx#Virtual_ListView_Style)。這可確保您的列表視圖控件立即顯示,而無需等待數據到達。 '2'從你的工作線程發佈一條自定義消息到擁有列表視圖控件的線程,並從那裏使各個客戶區失效。 – IInspectable 2014-10-29 15:29:22

回答

1

定義自定義的Windows消息,並在消息的WPARAM或LPARAM發送新數據的地址:

#define WM_MY_MSG (WM_APP + 2) // In a shared .h file 

NewData nd; // In the worker thread 
SendMessage(hwndMain, WM_MY_MSG, (WPARAM)&nd, NULL); 

您需要初始化hwndMain的工作線程,它應該是listview的父窗口的HWND。該父窗口處理消息並將數據複製到控件。

+0

不知何故,我用這種方法得到了無限循環。我只定義了一個調用'SendMessage(hwnd,WM_UPDATE_THUMBNAIL,(WPARAM)0,(LPARAM)0)'的函數'loadFile(HWND hwnd)',並從主線程創建了一個如下所示的新線程:'std :: thread t(loadFile,m_hWnd);' – Satara 2014-10-29 15:09:23

+0

目標是將數據發送到主線程,但你沒有這樣做。爲什麼通過兩個零?你可以編輯你的問題來顯示足夠的代碼,也許我們可以看到你做錯了什麼。通過工作線程傳遞數據和主線程將數據放入控件中,沒有理由使其成爲無限循環。 – 2014-10-29 15:27:23

+0

對不起,這兩個零都只是爲了測試。我只是通過一些代碼來擴展我的帖子。 – Satara 2014-10-29 16:00:39