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

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>
            欧美一区二区久久久| 激情欧美一区| 欧美日本精品| 日韩视频免费在线观看| 亚洲欧美日韩在线不卡| 久久精品一区| 99精品欧美一区二区三区 | 美女999久久久精品视频| 亚洲精品之草原avav久久| 亚洲欧美一区二区三区久久 | 蜜桃av综合| 性亚洲最疯狂xxxx高清| 欧美三级午夜理伦三级中文幕| 亚洲精品久久久久久下一站| 国际精品欧美精品| 免费观看不卡av| 欧美成人一区二区三区在线观看| 午夜精彩国产免费不卡不顿大片| 久久久久久网址| 中文av一区特黄| 亚洲免费一在线| 亚洲日本乱码在线观看| 免费观看成人www动漫视频| 欧美成人亚洲| 亚洲视频在线观看| 国产精品电影在线观看| 欧美视频精品在线| 久久综合国产精品| 亚洲在线电影| 亚洲一区免费网站| 美日韩精品视频免费看| 欧美在线高清视频| 国产精品久久久久久久久动漫| 美女视频黄 久久| 久久久久国产精品www| 久久久久.com| 久久久久国产一区二区三区| 国产欧美三级| 日韩视频在线播放| 欧美激情视频一区二区三区免费 | 欧美亚洲视频一区二区| 一区二区三区你懂的| 亚洲欧洲精品一区二区三区波多野1战4 | 欧美成在线视频| 母乳一区在线观看| 夜夜精品视频| 欧美高清在线播放| 亚洲国产综合在线| 久久精品99国产精品酒店日本| 欧美黄色网络| av成人免费| 亚洲精品免费网站| 欧美乱大交xxxxx| 亚洲人成网站色ww在线| 欧美aaa级| 欧美大片免费久久精品三p| 亚洲国产国产亚洲一二三| 久久综合久久88| 久久亚洲欧美| avtt综合网| 一区二区日韩| 国产偷国产偷亚洲高清97cao| 亚洲一区二区三区在线播放| 亚洲乱码国产乱码精品精天堂| 欧美国产日韩亚洲一区| 亚洲一区二区不卡免费| 亚洲女女女同性video| 国产亚洲精品久久飘花| 欧美成人免费一级人片100| 欧美成人日本| 亚洲欧美日韩一区二区在线| 欧美激情综合色| 国产精品扒开腿做爽爽爽软件| 亚洲欧美日韩精品在线| 亚洲国产福利在线| 国产精品久久久久久久久果冻传媒| 久久久久久午夜| 国产精品美女久久久免费| 亚洲一区一卡| 欧美成人精品h版在线观看| 欧美日韩国产123| 蜜桃av一区二区| av不卡在线观看| 国产视频不卡| 国产精品99久久久久久久vr| 亚洲第一精品影视| 欧美一区二区三区免费视| 亚洲视频 欧洲视频| 亚洲私人影院| 小黄鸭精品密入口导航| 欧美日韩福利视频| 亚洲欧洲在线观看| 91久久精品www人人做人人爽| 欧美专区福利在线| 久久久久久久久久久成人| 国产精品视频网址| 日韩视频在线免费| 亚洲欧美视频一区| 国产精品尤物福利片在线观看| 日韩视频在线你懂得| 亚洲欧美日韩国产中文在线| 国产精品qvod| 卡一卡二国产精品| 亚洲日本va午夜在线电影| 国产精品99久久久久久久女警 | 亚洲国产精品一区二区www| 久久青青草原一区二区| 亚洲精品欧美一区二区三区| 亚洲欧美韩国| 一区视频在线| 国产精品福利片| 亚洲天堂免费观看| 欧美成人免费观看| 欧美一级日韩一级| 亚洲国产乱码最新视频| 欧美网站大全在线观看| 久久久福利视频| 99视频在线精品国自产拍免费观看| 亚洲永久视频| 亚洲免费一级电影| 亚洲国产成人久久综合| 欧美专区福利在线| 国产精品99久久久久久www| 精品999在线播放| 国产中文一区二区| 欧美日韩在线观看一区二区三区| 午夜在线播放视频欧美| 99国产精品久久久久久久成人热 | 国产精品免费福利| 欧美精品色网| 欧美午夜精彩| 国产精品视频久久久| 欧美香蕉大胸在线视频观看| 欧美日韩天堂| 欧美日韩情趣电影| 欧美了一区在线观看| 欧美国产成人精品| 欧美日韩免费观看一区三区| 夜夜狂射影院欧美极品| 一区二区三区成人| 在线视频精品一| 亚洲免费伊人电影在线观看av| 一二三区精品福利视频| 日韩一级大片| 欧美在线看片| 欧美成人亚洲| 国产视频在线观看一区二区三区| 国产揄拍国内精品对白| 亚洲国产精品一区二区www在线| 亚洲日本理论电影| 午夜欧美不卡精品aaaaa| 久久夜色精品| 亚洲在线成人精品| 欧美aa国产视频| 国产一区二区成人久久免费影院| 国产在线拍偷自揄拍精品| 久久精品国产v日韩v亚洲| 久久久91精品| 国产欧美精品| 亚洲欧美日韩一区在线观看| 亚洲靠逼com| 欧美激情第二页| 久久精品一本久久99精品| 国产精品美女xx| 在线视频亚洲欧美| 亚洲国产精品一区二区第四页av | 亚洲欧美日本日韩| 欧美日韩在线精品| 亚洲精品日韩在线| 另类av一区二区| 性欧美大战久久久久久久久| 欧美日韩在线免费观看| 99国产精品一区| 日韩午夜在线电影| 欧美中文字幕精品| 1024日韩| 99视频日韩| 国产一区二区三区的电影| 久久国产加勒比精品无码| 亚洲一区视频在线| 激情综合自拍| 亚洲激情在线视频| 欧美午夜欧美| 久久精品欧洲| 欧美国产日韩精品免费观看| 亚洲视频电影图片偷拍一区| 一区二区欧美亚洲| 国内精品久久久久久久影视蜜臀 | 午夜视频一区| 精品电影在线观看| 99精品国产热久久91蜜凸| 欧美性猛交视频| 麻豆成人91精品二区三区| 欧美激情精品久久久久久久变态| 一本色道久久综合亚洲精品婷婷| 亚洲高清视频在线| 国产亚洲精品综合一区91| 欧美一级片一区| 欧美日韩三级在线| 欧美成人亚洲成人|