• <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>

            S.l.e!ep.¢%

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

            摸擬 Windows 桌面

            Posted on 2009-09-07 20:31 S.l.e!ep.¢% 閱讀(949) 評論(0)  編輯 收藏 引用 所屬分類: VC

            用API獲取到圖標,然后畫在自己的窗體內

            模擬window桌面實現 收藏
            正在開發中的游戲有個全屏功能--可以在window桌面背景上運行,就像一些視頻播放器在桌面背景上播放一樣的,花了個上午整了個Demo放出來留個紀念。

            實現功能:顯示圖標,雙擊圖標執行相應的程序,右擊圖標彈出該圖標對應得菜單,點擊非圖標區則彈出桌面菜單。需要完整工程可以點此下載:DesktopWindow.rar。程序效果圖如下:

            ?

            ?在這個程序里,定義了一個XShellItem的數據結構,保持桌面圖標的iten id(ITEMIDLiST),圖標以及文字圖標。

            ??? struct XShellItem ...{
            ??????? ITEMIDLIST*???? itemId;

            ??????? int x;
            ??????? int y;
            ??????? int w;
            ??????? int h;

            ??????? int nameX;
            ??????? int nameY;
            ??????? int nameW;
            ??????? int nameH;

            ??????? BOOL hit;

            ??????? CStringW name;
            ??????? Bitmap*???? icon;
            ??????? Bitmap*???? nameIcon;

            ??????? XShellItem()
            ??????? :
            ??????? itemId(NULL),
            ??????? x(0),
            ??????? y(0),
            ??????? w(0),
            ??????? h(0),
            ??????? nameX(0),
            ??????? nameY(0),
            ??????? nameW(0),
            ??????? nameH(0),
            ??????? name(L""),
            ??????? hit(FALSE),
            ??????? icon(NULL),
            ??????? nameIcon(NULL) ...{
            ??????? }
            ??????? ~XShellItem() ...{
            ??????? }
            ??? };
            然后定義一個數組CAtlArray<XShellItem> itemArray;用來保存所有桌面圖標對象,在InitShellFolder()中對它進行初始化:

            ??? // 獲取桌面圖標的相關數據
            ??? BOOL InitShellFolder()
            ??? ...{
            ??????? HRESULT hRslt = SHGetDesktopFolder(&folder);
            ??????? if (FAILED(hRslt)) ...{
            ??????????? return FALSE;
            ??????? }

            ??????? CComPtr<IEnumIDList> ids;
            ??????? hRslt = folder->EnumObjects(0, SHCONTF_FOLDERS | SHCONTF_NONFOLDERS, &ids);
            ??????? if (FAILED(hRslt)) ...{
            ??????????? return FALSE;
            ??????? }

            ??????? CAtlList<XShellItem> items;
            ??????? for (;;) ...{
            ??????????? ITEMIDLIST*???? id = 0;
            ??????????? ULONG cIds = 0;

            ??????????? hRslt = ids->Next(1, &id, &cIds);
            ??????????? if (hRslt != S_OK) ...{
            ??????????????? break;
            ??????????? }

            ??????????? CStringW name;
            ??????????? STRRET str = ...{ 0};
            ??????????? hRslt = folder->GetDisplayNameOf(id, SHGDN_NORMAL | SHGDN_INFOLDER, &str);
            ??????????? if (SUCCEEDED(hRslt)) ...{
            ??????????????? LPWSTR pname = 0;
            ??????????????? StrRetToStrW(&str, id, &pname);
            ??????????????? name = pname;
            ??????????????? CoTaskMemFree(pname);
            ??????????? }

            ??????????? XShellItem item;

            ??????????? item.itemId = id;
            ??????????? item.name = name;
            ??????????? items.AddTail(item);
            ??????? }

            ??????? SIZE_T iItem = 0;
            ??????? SIZE_T cItems = items.GetCount();

            ??????? itemArray.SetCount(cItems);

            ??????? POSITION pos = items.GetHeadPosition();
            ??????? while (pos != 0) ...{
            ??????????? XShellItem&???? si = items.GetNext(pos);
            ??????????? itemArray[iItem] = si;
            ??????????? iItem++;
            ??????? }

            ??????? HDC hDC = CreateCompatibleDC(0);

            ??????? Graphics g(hDC);
            ??????? g.Clear(Color(0, 0, 0, 0));

            ??????? ICONMETRICS im = ...{ 0};
            ??????? im.cbSize = sizeof(im);
            ??????? SystemParametersInfo(SPI_GETICONMETRICS, sizeof(im), &im, 0);

            ??????? SolidBrush br_t(Color(255, 255, 255));
            ??????? Font font_i(hDC, &(im.lfFont));
            ??????? float fcy = font_i.GetHeight(&g) * 2 + 2;
            ??????? DeleteDC(hDC);

            ??????? Gdiplus::StringFormat sf(Gdiplus::StringFormat::GenericTypographic());
            ??????? sf.SetAlignment(Gdiplus::StringAlignmentCenter);
            ??????? sf.SetTrimming(Gdiplus::StringTrimmingEllipsisWord);

            ??????? iconSpacingWidth = im.iHorzSpacing + OFFSET_WIDTH;
            ??????? iconSpacingHeight = im.iVertSpacing + OFFSET_HEIGHT;

            ??????? int iconWidth = GetSystemMetrics(SM_CXICON);
            ??????? int iconHeight = GetSystemMetrics(SM_CYICON);

            ??????? for (SIZE_T i = 0; i < cItems; i++) ...{
            ??????????? XShellItem&???? item = itemArray[i];

            ??????????? // SHGetFileInfo
            ??????????? HICON hIcon = 0;
            ??????????? HIMAGELIST hImgList;
            ??????????? SHFILEINFO stSHFileInfo;
            ??????????? CImageList cImgList;

            ??????????? // 獲取圖標
            ??????????? hImgList = (HIMAGELIST)::SHGetFileInfo(
            ??????????????????? (LPCWSTR) item.itemId,
            ??????????????????? 0,
            ??????????????????? &stSHFileInfo,
            ??????????????????? sizeof(SHFILEINFO),
            ??????????????????? SHGFI_PIDL | SHGFI_ICON | SHGFI_LARGEICON | SHGFI_SYSICONINDEX);

            ??????????? // DIBSection 8bit
            ??????????? BITMAPINFO bmi;
            ??????????? BITMAPINFOHEADER&? bmih = bmi.bmiHeader;
            ??????????? bmih.biSize = sizeof(bmih);
            ??????????? bmih.biWidth = ICON_WIDTH;
            ??????????? bmih.biHeight = -ICON_HEIGHT;??? // BMP反轉
            ??????????? bmih.biPlanes = 1;
            ??????????? bmih.biBitCount = 32;
            ??????????? bmih.biCompression = BI_RGB;
            ??????????? bmih.biSizeImage = 0;
            ??????????? bmih.biXPelsPerMeter = 0;
            ??????????? bmih.biYPelsPerMeter = 0;
            ??????????? bmih.biClrUsed = 0;
            ??????????? bmih.biClrImportant = 0;

            ??????????? HDC memDC = CreateCompatibleDC(0);
            ??????????? void*? pDib = 0;
            ??????????? HBITMAP hBmp = CreateDIBSection(memDC, &bmi, DIB_RGB_COLORS, &pDib, 0, 0);
            ??????????? GdiFlush();

            ??????????? HGDIOBJ old = SelectObject(memDC, hBmp);

            ??????????? // ImageList_Draw WindowsXP
            ??????????? ImageList_SetBkColor(hImgList, 0x0);
            ??????????? ImageList_Draw(hImgList, stSHFileInfo.iIcon, memDC, 0, 0, ILD_NORMAL);
            ??????????? SelectObject(memDC, old);
            ??????????? DeleteDC(memDC);

            ??????????? cImgList.Attach(hImgList);
            ??????????? hIcon = cImgList.ExtractIcon(stSHFileInfo.iIcon);
            ??????????? cImgList.Detach();

            ??????????? if (hIcon != 0) ...{

            ??????????????? // Bitmap::FromHICON 0~255
            ??????????????? item.icon = Bitmap::FromHICON(hIcon);
            ??????????????? item.w = iconWidth;
            ??????????????? item.h = iconHeight;

            ??????????????? Gdiplus::RectF rc(float(2), float(2), float(iconSpacingWidth - 4), fcy);

            ??????????????? Gdiplus::Bitmap * nameIcon = new Bitmap(NAME_WIDTH, NAME_HEIGHT, &g);
            ??????????????? Gdiplus::Graphics * g2 = Gdiplus::Graphics::FromImage(nameIcon);
            ??????????????? g2->Clear(Gdiplus::Color(Gdiplus::ARGB(0)));

            ??????????????? g2->DrawString(item.name, item.name.GetLength(), &font_i, rc, &sf, &br_t);

            ??????????????? item.nameIcon = nameIcon;
            ??????????????? item.nameW = NAME_WIDTH;
            ??????????????? item.nameH = NAME_HEIGHT;

            ??????????????? delete g2;
            ??????????? }

            ??????????? DestroyIcon(hIcon);
            ??????????? DeleteObject(hBmp);
            ??????????? DestroyIcon(stSHFileInfo.hIcon);
            ??????? }

            ??????? return TRUE;
            ??? }
            注意這里面并沒有設置圖標對象的位置,因為當窗口改變大小的時候,相應地也要調整圖標的描繪位置,所以圖標位置是在SetShellItemPosition()中動態調整的.

            ??? // 根據窗口大小設置圖標位置
            ??? void SetShellItemPosition()
            ??? ...{
            ??????? int iconWidth = GetSystemMetrics(SM_CXICON);
            ??????? int iconHeight = GetSystemMetrics(SM_CYICON);
            ??????? static const int OFFSET_Y = 20;
            ??????? int x = 0;
            ??????? int y = OFFSET_Y;
            ??????? SIZE_T cItems = itemArray.GetCount();
            ??????? for (SIZE_T i = 0; i < cItems; i++) ...{
            ??????????? XShellItem&???? item = itemArray[i];
            ??????????? if (item.icon) ...{
            ??????????????? item.x = x + (iconSpacingWidth - iconWidth) / 2;
            ??????????????? item.y = y;
            ??????????? }

            ??????????? if (item.nameIcon) ...{
            ??????????????? item.nameX = x;
            ??????????????? item.nameY = y + iconHeight + 2;
            ??????????? }

            ??????????? WTL::CRect rect;
            ??????????? GetClientRect(&rect);
            ??????????? y += iconSpacingHeight;
            ??????????? if (y + iconSpacingHeight >= rect.bottom) ...{
            ??????????????? x += iconSpacingWidth;
            ??????????????? y = OFFSET_Y;
            ??????????? }
            ??????? }
            ??? }
            描繪圖標就很簡單了,呵呵,不貼了,下面來說說彈出圖標菜單,執行圖標對應的程序以及彈出桌面菜單。

            執行圖標對應的程序,需要以先前保持的圖標itemid作為參數,代碼如下:

            ??? void RunShellItem(ITEMIDLIST* pIID)
            ??? ...{
            ??????? SHELLEXECUTEINFO info;
            ??????? info.cbSize = sizeof(SHELLEXECUTEINFO);
            ??????? info.fMask = SEE_MASK_INVOKEIDLIST;
            ??????? info.hwnd = m_hWnd;
            ??????? info.lpVerb = NULL;
            ??????? info.lpFile = NULL;
            ??????? info.lpParameters = NULL;
            ??????? info.lpDirectory = NULL;
            ??????? info.nShow = SW_SHOWNORMAL;
            ??????? info.hInstApp = NULL;
            ??????? info.lpIDList = pIID;
            ??????? ShellExecuteEx(&info);
            ??? }
            彈出桌面菜單的代碼如下:

            ??? // 桌面菜單
            ??? void DesktopMenu()
            ??? ...{
            ??????? HWND program = FindWindowEx(0, 0, _T("Progman"), _T("Program Manager"));
            ??????? HWND view = FindWindowEx(program, 0, _T("SHELLDLL_DefView"), 0);

            ??????? //HWND list = FindWindowEx(view, 0, _T("SysListView32"), 0);
            ??????? ::SetForegroundWindow(view);

            ??????? POINT pt;
            ??????? GetCursorPos(&pt);

            ??????? LPARAM lp = pt.y << 16 | (pt.x - 32);
            ??????? ::PostMessage(view, WM_LBUTTONDOWN, 0, lp);
            ??????? ::PostMessage(view, WM_RBUTTONUP, 0, lp);
            ??? }
            彈出圖標菜單的代碼如下,這里定義了兩個全局的IContextMenu對象:
            static IContextMenu2*? g_pIContext2 = NULL;
            static IContextMenu3*? g_pIContext3 = NULL;

            以便在消息回調函數中使用。具體代碼如下:

            ??? // 圖標菜單
            ??? void RightMenu(ITEMIDLIST* pIID)
            ??? ...{
            ??????? HWND hwnd = m_hWnd;

            ??????? LPCONTEXTMENU pContextMenu = NULL;
            ??????? LPCONTEXTMENU pCtxMenuTemp = NULL;

            ??????? g_pIContext2 = NULL;
            ??????? g_pIContext3 = NULL;

            ??????? int menuType = 0;

            ??????? HRESULT hRslt = folder->GetUIObjectOf(
            ??????????????? hwnd,
            ??????????????? 1,
            ??????????????? (LPCITEMIDLIST*) &(pIID),
            ??????????????? IID_IContextMenu,
            ??????????????? 0,
            ??????????????? (void**) &pCtxMenuTemp);
            ??????? if (FAILED(hRslt)) ...{
            ??????????? return;
            ??????? }

            ??????? POINT pt;
            ??????? GetCursorPos(&pt);

            ??????? if (pCtxMenuTemp->QueryInterface(IID_IContextMenu3, (void**) &pContextMenu) == NOERROR) ...{
            ??????????? menuType = 3;
            ??????? }
            ??????? else if (pCtxMenuTemp->QueryInterface(IID_IContextMenu2, (void**) &pContextMenu) == NOERROR) ...{
            ??????????? menuType = 2;
            ??????? }

            ??????? if (pContextMenu) ...{
            ??????????? pCtxMenuTemp->Release();
            ??????? }
            ??????? else ...{
            ??????????? pContextMenu = pCtxMenuTemp;
            ??????????? menuType = 1;
            ??????? }

            ??????? if (menuType == 0) ...{
            ??????????? return;
            ??????? }

            ??????? HMENU hMenu = CreatePopupMenu();
            ??????? hRslt = pContextMenu->QueryContextMenu(hMenu, 0, 1, 0x7fff, CMF_NORMAL | CMF_EXPLORE);
            ??????? if (FAILED(hRslt)) ...{
            ??????????? return;
            ??????? }

            #ifndef _WIN64
            ??? #pragma warning(disable : 4244 4311)
            #endif

            ??????? // subclass window
            ??????? WNDPROC oldWndProc = NULL;
            ??????? if (menuType > 1) ...{

            ??????????? // only subclass if it is IID_IContextMenu2 or IID_IContextMenu3
            ??????????? oldWndProc = (WNDPROC) SetWindowLongPtr(GWL_WNDPROC, (LONG) HookWndProc);
            ??????????? if (menuType == 2) ...{
            ??????????????? g_pIContext2 = (LPCONTEXTMENU2) pContextMenu;
            ??????????? }
            ??????????? else ...{
            ??????????????? g_pIContext3 = (LPCONTEXTMENU3) pContextMenu;
            ??????????? }
            ??????? }
            ??????? else ...{
            ??????????? oldWndProc = NULL;
            ??????? }

            ??????? int cmd = ::TrackPopupMenu(
            ??????????????? hMenu,
            ??????????????? TPM_LEFTALIGN | TPM_BOTTOMALIGN | TPM_RETURNCMD | TPM_LEFTBUTTON,
            ??????????????? pt.x,
            ??????????????? pt.y,
            ??????????????? 0,
            ??????????????? hwnd,
            ??????????????? 0);

            ??????? // unsubclass
            ??????? if (oldWndProc) ...{
            ??????????? SetWindowLongPtr(GWL_WNDPROC, (LONG) oldWndProc);
            ??????? }

            #ifndef _WIN64
            ??? #pragma warning(default : 4244 4311)
            #endif
            ??????? if (cmd != 0) ...{
            ??????????? CMINVOKECOMMANDINFO ci = ...{ 0};
            ??????????? ci.cbSize = sizeof(CMINVOKECOMMANDINFO);
            ??????????? ci.hwnd = hwnd;
            ??????????? ci.lpVerb = (LPCSTR) MAKEINTRESOURCE(cmd - 1);
            ??????????? ci.nShow = SW_SHOWNORMAL;

            ??????????? pContextMenu->InvokeCommand(&ci);
            ??????? }

            ??????? pContextMenu->Release();
            ??????? g_pIContext2 = NULL;
            ??????? g_pIContext3 = NULL;
            ??????? ::DestroyMenu(hMenu);
            ??? }

            ??? static LRESULT CALLBACK HookWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
            ??? ...{
            ??????? switch (message) ...{
            ??????? case WM_MENUCHAR:??? // only supported by IContextMenu3
            ??????????? if (g_pIContext3) ...{
            ??????????????? LRESULT lResult = 0;
            ??????????????? g_pIContext3->HandleMenuMsg2(message, wParam, lParam, &lResult);
            ??????????????? return(lResult);
            ??????????? }
            ??????????? break;
            ??????? case WM_DRAWITEM:
            ??????? case WM_MEASUREITEM:
            ??????????? if (wParam) ...{
            ??????????????? break;??? // if wParam != 0 then the message is not menu-related
            ??????????? }

            ??????? case WM_INITMENUPOPUP:
            ??????????? if (g_pIContext2) ...{
            ??????????????? g_pIContext2->HandleMenuMsg(message, wParam, lParam);
            ??????????? }
            ??????????? else ...{
            ??????????????? g_pIContext3->HandleMenuMsg(message, wParam, lParam);
            ??????????? }

            ??????????? return(message == WM_INITMENUPOPUP ? 0 : TRUE);
            ??????????? break;
            ??????? default:
            ??????????? break;
            ??????? }

            ??????? return ::CallWindowProc((WNDPROC) GetProp(hWnd, TEXT("oldWndProc")), hWnd, message, wParam, lParam);
            ??? }?

            本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/lzxxteam/archive/2008/03/04/2147500.aspx

            狠狠综合久久AV一区二区三区| 国内精品久久久久久中文字幕 | 久久精品一区二区三区AV| 亚洲国产精品久久久久婷婷软件 | 一本色道久久HEZYO无码| 色综合久久天天综线观看| 久久精品国产一区二区 | 久久综合狠狠综合久久| 亚洲综合伊人久久综合| 午夜天堂精品久久久久| 99精品久久精品| 亚洲综合久久综合激情久久| 久久99免费视频| 久久WWW免费人成—看片| 久久亚洲国产精品123区| 久久婷婷午色综合夜啪| 亚洲人成精品久久久久| 精品国产一区二区三区久久久狼 | 国内精品久久久久影院免费| 国产亚洲欧美成人久久片| 99久久国产综合精品五月天喷水 | 国色天香久久久久久久小说| 久久久国产精品亚洲一区| 国产精品久久久久久久| 久久黄色视频| 久久精品卫校国产小美女| 久久香蕉一级毛片| 亚州日韩精品专区久久久| 午夜不卡久久精品无码免费| 久久香蕉一级毛片| 狠狠色丁香久久婷婷综合_中| 热re99久久精品国99热| 国产一区二区精品久久凹凸| 大香伊人久久精品一区二区| 久久天堂电影网| 亚洲AV日韩精品久久久久久久| 91久久香蕉国产熟女线看| 亚洲AV无码久久精品狠狠爱浪潮 | 精品99久久aaa一级毛片| 亚洲女久久久噜噜噜熟女| 国产精品美女久久久久av爽|