青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

S.l.e!ep.¢%

像打了激速一樣,以四倍的速度運轉,開心的工作
簡單、開放、平等的公司文化;尊重個性、自由與個人價值;
posts - 1098, comments - 335, trackbacks - 0, articles - 1
  C++博客 :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理

預備性閱讀
在閱讀本文之前,建議先對列表視圖控件和系統外殼有一個基本的了解。建議閱讀以下SDK文章

Shell FAQ
List-View Controls Overview
Using List-View Controls
Customizing a Control's Appearance Using Custom Draw
創建應用程序
使用MFC應用程序向導創建一個SDI應用程序,在最后一步選擇視圖的基類為CListView。創建完成之后,在資源中去掉保存、編輯和打印等功能的菜單和工具欄按鈕(因為這些功能沒有實現)。

虛列表的創建
本文采用虛列表技術,使得顯示信息是在第一次顯示的時候才被獲取。為了創建虛列表,在創建之前需要指定列表的風格

BOOL CPicViewView::PreCreateWindow(CREATESTRUCT& cs)
{
??? cs.style&=~LVS_TYPEMASK;
??? cs.style|=LVS_ICON|LVS_OWNERDATA;
??? return CListView::PreCreateWindow(cs);
}
同時,因為列表項的Overlay圖標也是被動態獲取的,所以需要設置動態Overlay圖標

void CPicViewView::OnInitialUpdate()
{
??? CListView::OnInitialUpdate();
??? GetListCtrl().SetCallbackMask(LVIS_OVERLAYMASK);
}

緩存顯示信息
在列表需要顯示一個范圍的項目之前,列表會發送LVN_ODCACHEHINT通知,應用程序可以捕獲這個消息來緩存部分列表的顯示信息,以提高性能。

void CPicViewView::OnOdcachehint(NMHDR* pNMHDR, LRESULT* pResult)
{
??? NMLVCACHEHINT* pCacheHint = (NMLVCACHEHINT*)pNMHDR;
??? PrepCache(0,min(5,m_arpFolderItems.GetSize()));
??? PrepCache(pCacheHint->iFrom,pCacheHint->iTo);
??? PrepCache(max(0,m_arpFolderItems.GetSize()-5),m_arpFolderItems.GetSize());
??? *pResult = 0;
}
在列表需要顯示一個項目之前,列表會發送LVN_GETDISPINFO通知,應用程序可以捕獲這個消息來提供項目的顯示信息。如果顯示時需要顯示的列表項在緩存中,那么可以從緩存中獲取顯示信息。否則需要重新從文件獲得。

void CPicViewView::OnGetdispinfo(NMHDR* pNMHDR, LRESULT* pResult)
{
??? LV_DISPINFO* pDispInfo = (LV_DISPINFO*)pNMHDR;
??? if(pDispInfo->item.iItem==-1)return;
??? HRESULT hr=S_OK;
??? LPCITEMIDLIST pidlItem=m_arpFolderItems[pDispInfo->item.iItem];
??? CFolderItemInfo* pFolderItemInfo=FindItemInCache(pidlItem);
??? BOOL bCached=TRUE;
??? if(pFolderItemInfo==NULL){
??????? bCached=FALSE;
??????? pFolderItemInfo=new CFolderItemInfo;
??????? GetItemInfo(pidlItem,pFolderItemInfo);
??? }
??? if(pDispInfo->item.mask&LVIF_TEXT){
??????? lstrcpyn(pDispInfo->item.pszText,pFolderItemInfo->tszDisplayName,pDispInfo-?? >item.cchTextMax);
??? }
??? if(pDispInfo->item.mask&LVIF_IMAGE){
??????? pDispInfo->item.iImage=pFolderItemInfo->iIcon;
??? }
??? if(pDispInfo->item.mask&LVIF_STATE){
??????? pDispInfo->item.state=pFolderItemInfo->state;
??? }
??? if(!bCached)
??????? delete pFolderItemInfo;
??? *pResult = 0;
}


文件圖標的顯示
默認情況下,列表項的圖標就是其系統圖標。首先獲得系統圖像列表

int CPicViewView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
??? if (CListView::OnCreate(lpCreateStruct) == -1)
??????? return -1;
??? HRESULT hr = SHGetMalloc(&m_pMalloc); if(FAILED(hr)) return -1;
??? hr = SHGetDesktopFolder(&m_psfDesktop);if(FAILED(hr)) return -1;
??? SHFILEINFO shfi;
??? ZeroMemory(&shfi,sizeof(SHFILEINFO));
??? HIMAGELIST hi=(HIMAGELIST)SHGetFileInfo(NULL,0,&shfi,sizeof(SHFILEINFO),SHGFI_ICON |SHGFI_SYSICONINDEX|SHGFI_SMALLICON);
??? GetListCtrl().SetImageList(CImageList::FromHandle(hi),LVSIL_SMALL);
??? hi=(HIMAGELIST)SHGetFileInfo(NULL,0,&shfi,sizeof(SHFILEINFO),SHGFI_ICON |SHGFI_SYSICONINDEX|SHGFI_LARGEICON);
??? GetListCtrl().SetImageList(CImageList::FromHandle(hi),LVSIL_NORMAL);
??? return 0;
}

然后在獲取文件信息時,從文件獲得其圖標在系統圖像列表中的索引。

如果列表項是圖像文件,并且從文件成功載入圖像,那么使用自畫功能以替換默認的圖標。

void CPicViewView::OnCustomDraw(NMHDR* pNMHDR, LRESULT* pResult)
{
??? LPNMLVCUSTOMDRAW lpNMCustomDraw = (LPNMLVCUSTOMDRAW) pNMHDR;
??? switch(lpNMCustomDraw ->nmcd.dwDrawStage) {
??????? case CDDS_PREPAINT : *pResult=CDRF_NOTIFYITEMDRAW;return;
??????? case CDDS_ITEMPREPAINT:*pResult=CDRF_NOTIFYPOSTPAINT;return;
??????? case CDDS_ITEMPOSTPAINT:
??????? {
??????????? int iItem=lpNMCustomDraw ->nmcd.dwItemSpec;
??????????? if(iItem==-1){
??????????????? *pResult=CDRF_DODEFAULT;return;
??????????? }
??????????? CFolderItemInfo* pItemInfo=FindItemInCache(m_arpFolderItems[iItem]);
??????????? if(pItemInfo==NULL||pItemInfo->bFailLoadPic||pItemInfo->pic.m_pPict==NULL){
??????????????? *pResult=CDRF_DODEFAULT;return;
??????????? }
??????????? CRect rectIcon;
??????????? GetListCtrl().GetItemRect(iItem,&rectIcon,LVIR_ICON);
??????????? CDC* pDC=CDC::FromHandle(lpNMCustomDraw->nmcd.hdc);
??????????? pItemInfo->pic.Render(pDC,rectIcon,rectIcon);
??????? }
??????? *pResult=CDRF_NEWFONT;return;
??? }
??? * pResult=0;
}

上面的代碼是使用獲取的文件顯示信息中的圖像,在列表項圖標的區域畫圖。

獲取顯示信息
為了緩存列表項的顯示信息,或者顯示列表項,需要獲取列表項的文字、圖標、Overlay圖標和縮略圖等信息。這里使用了ILCombine來把緩存中的相對PIDL轉化為完整的Pidl,再據此獲得文件的完整路徑,然后調用OleLoadPicturePath函數載入圖像。

void CPicViewView::GetItemInfo(LPCITEMIDLIST pidl,CFolderItemInfo* pItemInfo)
{
??? HRESULT hr = theApp.SHGetDisplayNameOf(pidl,pItemInfo->tszDisplayName);
??? IShellIcon* pShellIcon=NULL;
??? hr=m_psfFolder->QueryInterface(IID_IShellIcon,(LPVOID*)&pShellIcon);
??? if (SUCCEEDED(hr)&&pShellIcon){
??????? pShellIcon->GetIconOf(pidl,0,&pItemInfo->iIcon);
??????? pShellIcon->Release();
??? }
??? IShellIconOverlay* pShellIconOverlay =NULL;
??? hr=m_psfFolder->QueryInterface(IID_IShellIconOverlay,(LPVOID*)&pShellIconOverlay);
??? if (SUCCEEDED(hr)&&pShellIconOverlay){
??????? int nOverlay=0;
??????? pShellIconOverlay->GetOverlayIndex(pidl,&nOverlay);
??????? pItemInfo->state=INDEXTOOVERLAYMASK (nOverlay);
??????? pShellIconOverlay->Release();
??? }
??? LPITEMIDLIST pidlItemFull=ILCombine(m_pidlFolder,pidl);
??????? if(pidlItemFull){
??????????? if(SHGetPathFromIDList(pidlItemFull,pItemInfo->tszPath)){
??????????????? USES_CONVERSION;
??????????????? hr=OleLoadPicturePath(
??????????????????? T2OLE(pItemInfo->tszPath)
??????????????????? ,NULL,0,RGB(255,255,255)
??????????????????? ,IID_IPicture,(LPVOID*)&pItemInfo->pic.m_pPict);
??????????? if(FAILED(hr)){
??????????????????? pItemInfo->bFailLoadPic=TRUE;
??????????????????? TRACE("OleLoadPicturePath failed %s\r\n",pItemInfo->tszPath);
??????????????? }
??????????? }
??????? }
??????? m_pMalloc->Free(pidlItemFull);
??? }
}

緩存目錄的數據
在更改目錄時,需要重建目錄內容的緩存。這包括目錄的pidl和IShellFolder接口指針,目錄內容的相對pidl,以及列表項的顯示信息(基于性能上的考慮,列表項的顯示信息是在接收到LVN_ODCACHEHINT通知的時候緩存的)。

LPITEMIDLIST m_pidlFolder;
IShellFolder * m_psfFolder;
CTypedPtrArray<CPtrArray,LPITEMIDLIST> m_arpFolderItems;
CTypedPtrMap<CMapPtrToPtr,LPITEMIDLIST,CFolderItemInfo*> m_mapCache;
?

void CPicViewView::EnterFolder(LPCITEMIDLIST pidl)
{
??? USES_CONVERSION;
??? m_pidlFolder=ILClone(pidl);
??? if(m_pidlFolder){
??????? LPENUMIDLIST ppenum = NULL;
??????? LPITEMIDLIST pidlItems = NULL;
??????? ULONG celtFetched;
??????? HRESULT hr;
??????? hr = m_psfDesktop->BindToObject(m_pidlFolder, NULL, IID_IShellFolder, (LPVOID *) &m_psfFolder);
??????? if(SUCCEEDED(hr)){
??????????? hr = m_psfFolder->EnumObjects(NULL,SHCONTF_FOLDERS | SHCONTF_NONFOLDERS, &ppenum);
??????????? if(SUCCEEDED(hr)){
??????????????? while( hr = ppenum->Next(1,&pidlItems, &celtFetched) == S_OK && (celtFetched) == 1){
??????????????????? m_arpFolderItems.Add(pidlItems);
??????????????????? }
??????????? }
??????? }
??????? GetListCtrl().SetItemCount(m_arpFolderItems.GetSize());
??? }
}

?

打開文件夾
本應用程序顯示文件夾的內容而不是顯示文檔的內容,所以我重載了打開文件時的處理,顯示目錄選擇對話框而不是文件打開對話框。

void CPicViewApp::OnFileOpen()
{
??? TCHAR tszDisplayName[_MAX_PATH];
??? TCHAR tszPathSelected[_MAX_PATH];
??? LPITEMIDLIST pidlSelected=PidlBrowse(m_pMainWnd->GetSafeHwnd(),0,tszDisplayName);
??? if(pidlSelected){
??????? if(SHGetPathFromIDList(pidlSelected,tszPathSelected)){
??????????? CDocument* pDocument=OpenDocumentFile(tszPathSelected);
??????????? pDocument->SetTitle(tszDisplayName);
??????????? ILFree(pidlSelected);
??????? }
??? }
}

注意從外殼調用獲得的PIDL一般都需要調用ILFree或者IMalloc::Free釋放。一個例外是調用函數SHBindToParent獲得的相對pidl,因為它是輸入的參數完整pidl的一部分,所以不必另外釋放。

在新建或者打開“文件”時候,文檔需要通知視圖當前文件夾的更改,這是通過調用CDocument::UpdateAllViews和重載CView::OnUpdate實現的。視圖對這個通知的處理是清除上一個目錄的緩存數據,緩存新目錄的數據,以及更新文檔標題。
?

打開文件或者目錄
為了使用方便,雙擊列表項時可以在同一窗口打開子目錄,或者調用系統的默認處理程序打開文件。如果文件是快捷方式,那么打開快捷方式的目標。

void CPicViewView::OnDblclk(NMHDR* pNMHDR, LRESULT* pResult)
{
??? LPNMLISTVIEW lpnm=(LPNMLISTVIEW)pNMHDR;
??? if(lpnm->iItem==-1)return;
??? *pResult = 0;
??? HRESULT hr=S_OK;
??? LPCITEMIDLIST pidlItem=m_arpFolderItems[lpnm->iItem];
??? LPITEMIDLIST pidlItemFull=ILCombine(m_pidlFolder,pidlItem);
??? LPITEMIDLIST pidlItemTarget=NULL;
??? hr=theApp.SHGetTargetFolderIDList(pidlItemFull,&pidlItemTarget);
??? if(pidlItemTarget){
??????? if(theApp.ILIsFolder(pidlItemTarget)){
??????????? CFolderChange FolderChange;
??????????? FolderChange.m_pidlFolder=pidlItemTarget;
??????????? OnFolderChange(&FolderChange);
??????? }
??????? else{
??????????? SHELLEXECUTEINFO ShExecInfo;
??????????? ShExecInfo.cbSize = sizeof(SHELLEXECUTEINFO);
??????????? ShExecInfo.fMask = SEE_MASK_IDLIST;
??????????? ShExecInfo.hwnd = NULL;
??????????? ShExecInfo.lpVerb = NULL;
??????????? ShExecInfo.lpFile = NULL;
??????????? ShExecInfo.lpIDList= pidlItemTarget;
??????????? ShExecInfo.lpParameters = NULL;
??????????? ShExecInfo.lpDirectory = NULL;
??????????? ShExecInfo.nShow = SW_MAXIMIZE;
??????????? ShExecInfo.hInstApp = NULL;
??????????? ShellExecuteEx(&ShExecInfo);
??????? }
??????? m_pMalloc->Free(pidlItemTarget);
??????? m_pMalloc->Free(pidlItemFull);
??? }
}
?

性能的優化
為了更好的用戶體驗,可以使用自定義的圖標大小(這需要完全自行繪制列表項的圖標區域),用單獨的線程來載入圖像,或者使用調整到圖標大小的縮略圖緩沖(這樣每次繪制時不必拉伸圖像)。但是這超出了本文的范圍。有興趣的讀者可以自己試一下。

參考
需要更多信息的話,可以參考

Shell FAQ
List-View Controls Overview
Using List-View Controls
Customizing a Control's Appearance Using Custom Draw
本文來自焦點核(X)軟件安全技術網,原文地址:http://www.xfocusx.com

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            亚洲国产综合视频在线观看| 韩日欧美一区| 欧美成人午夜视频| 久久久视频精品| 欧美成人免费观看| 久久综合国产精品| 欧美日韩ab| 国产精品主播| 亚洲第一精品夜夜躁人人爽| 9久草视频在线视频精品| 午夜在线视频一区二区区别| 麻豆久久精品| 艳女tv在线观看国产一区| 性8sex亚洲区入口| 欧美日韩成人综合| 亚洲欧美日韩区| 亚洲电影免费在线| 欧美在线免费一级片| 欧美理论片在线观看| 国外成人免费视频| 欧美电影免费观看高清| 欧美日韩免费在线观看| 一区二区在线观看视频| 久久激情网站| 夜夜精品视频| 国产三级精品三级| 亚洲曰本av电影| 亚洲国产日韩欧美综合久久| 欧美日一区二区在线观看| 伊人色综合久久天天五月婷| 欧美在线观看一区二区| 亚洲天堂激情| 欧美精品激情在线| 亚洲欧洲日产国产综合网| 久久午夜电影| 午夜精品久久久久久久男人的天堂 | 国产精品日本精品| 日韩午夜在线观看视频| 美女网站在线免费欧美精品| 久久大综合网| 国产日韩在线亚洲字幕中文| 亚洲第一色中文字幕| 国产精品视频免费观看| 亚洲区免费影片| 免费久久99精品国产| 伊人狠狠色j香婷婷综合| 一本色道久久综合亚洲91| 欧美日韩ab片| 欧美高清视频| 精品成人a区在线观看| 亚洲影院色无极综合| 国产精品一区二区久久| 亚洲国产高清视频| 在线日韩中文字幕| 欧美伊久线香蕉线新在线| 亚洲午夜三级在线| 亚洲欧美日韩在线综合| 日韩一区二区高清| 噜噜爱69成人精品| 亚洲一区激情| 欧美日韩久久不卡| 亚洲国产日韩欧美在线99| 精品二区视频| 久久精品免费看| 亚洲狼人精品一区二区三区| 99精品久久| 一区二区三区四区五区视频| 午夜精品久久久久久久白皮肤| 亚洲一区观看| 国产精品美女久久| 美女精品在线| 亚洲成色www8888| 久久久久国产精品www| 一本久久青青| 欧美日韩精品久久| 日韩一区二区免费看| 国产一区二区三区在线观看视频| 欧美国产国产综合| 91久久久一线二线三线品牌| 久久综合五月天婷婷伊人| 欧美va亚洲va日韩∨a综合色| 欧美日韩精品久久久| 一本色道久久综合| 久久激情综合网| 激情久久综合| 欧美黑人在线观看| 久热精品视频在线观看| 136国产福利精品导航| 欧美大片专区| 麻豆精品网站| 亚洲乱码精品一二三四区日韩在线| 欧美不卡在线视频| 国产精品99久久久久久人 | 欧美成人免费全部| 一本一本久久a久久精品综合妖精 一本一本久久a久久精品综合麻豆 | 日韩午夜激情| 欧美一区国产二区| 亚洲国产天堂久久综合| 亚洲男人的天堂在线观看 | 国产精品久久久久久久久婷婷| 亚洲欧美日韩在线高清直播| 老司机免费视频一区二区| 亚洲精品男同| 美女成人午夜| 一区二区三区|亚洲午夜| 久久精品久久综合| 亚洲精品色婷婷福利天堂| 国产精品青草久久| 久久免费偷拍视频| 欧美成人精品不卡视频在线观看| 一区二区欧美激情| 国内精品久久久久影院色| 小嫩嫩精品导航| 最新精品在线| 99这里只有久久精品视频| 国产欧美日韩| 欧美一区二区视频97| 欧美一区二区播放| 亚洲美女中出| 在线成人h网| 国产麻豆综合| 欧美视频一区在线| 免费看亚洲片| 性欧美1819sex性高清| 中日韩午夜理伦电影免费| 亚洲第一狼人社区| 蜜臀99久久精品久久久久久软件| 亚洲在线观看| 一本一道久久综合狠狠老精东影业 | 国产精品一区二区久久精品 | 久久综合成人精品亚洲另类欧美| 亚洲免费影院| 一区二区三区鲁丝不卡| 亚洲激情电影在线| 亚洲盗摄视频| 亚洲丰满少妇videoshd| 猛干欧美女孩| 久久精品国产99精品国产亚洲性色 | 欧美日韩成人在线播放| 另类激情亚洲| 久久er99精品| 久久国产精品久久w女人spa| 午夜精品视频在线| 性久久久久久久| 欧美一区二区三区日韩视频| 午夜免费电影一区在线观看| 亚洲一区免费网站| 亚洲影音先锋| 亚洲欧美激情一区| 欧美一区二区三区四区视频| 香蕉成人久久| 欧美一站二站| 久久一日本道色综合久久| 老妇喷水一区二区三区| 欧美大片在线影院| 欧美日韩一区二区在线播放| 国产精品啊啊啊| 老巨人导航500精品| 蜜桃av一区二区三区| 欧美大香线蕉线伊人久久国产精品| 日韩亚洲国产精品| 久久综合色88| 欧美精品一区二区在线播放| 欧美精品v日韩精品v国产精品| 国产精品一卡| 99精品国产在热久久下载| 久久免费视频这里只有精品| 99xxxx成人网| 免费久久精品视频| 国产一区自拍视频| 亚洲一区三区视频在线观看| 亚洲国产乱码最新视频| 久久精品人人爽| 国产精品亚洲人在线观看| 99精品国产热久久91蜜凸| 免费日韩一区二区| 性欧美大战久久久久久久久| 欧美视频福利| 夜夜狂射影院欧美极品| 欧美电影打屁股sp| 久久久久久久激情视频| 国产日韩精品久久| 午夜一区不卡| 亚洲影院色无极综合| 国产精品对白刺激久久久| 欧美日韩久久精品| 99re66热这里只有精品4| 欧美不卡在线视频| 久久婷婷综合激情| 一区二区在线不卡| 欧美成人精品h版在线观看| 久久久久久久国产| 亚洲国产精品成人综合色在线婷婷| 亚洲区免费影片| 亚洲电影免费观看高清完整版在线观看 | 久久久之久亚州精品露出| 香蕉久久夜色精品国产使用方法| 国产精品专区h在线观看| 久久本道综合色狠狠五月| 欧美成人综合在线|