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

            羅朝輝(飄飄白云)

            關注嵌入式操作系統,移動平臺,圖形開發。-->加微博 ^_^

              C++博客 :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
              85 隨筆 :: 0 文章 :: 169 評論 :: 0 Trackbacks

            正在開發中的游戲有個全屏功能--可以在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(
            0000));

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

                    SolidBrush br_t(Color(
            255255255));
                    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, 00);
                        GdiFlush();

                        HGDIOBJ old 
            = SelectObject(memDC, hBmp);

                        
            // ImageList_Draw WindowsXP
                        ImageList_SetBkColor(hImgList, 0x0);
                        ImageList_Draw(hImgList, stSHFileInfo.iIcon, memDC, 
            00, 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(00, _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, 010x7fff, 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);
                }


            posted on 2008-02-23 14:28 羅朝輝 閱讀(4609) 評論(7)  編輯 收藏 引用 所屬分類: Windows

            評論

            # re: 模擬window桌面實現 2008-02-23 18:32 Simulator
            漂亮  回復  更多評論
              

            # re: 模擬window桌面實現 2008-02-24 23:06 魔域私服
            不錯不錯,學習了  回復  更多評論
              

            # re: 模擬window桌面實現 2008-02-25 09:45 Enoch
            lz很強大,很暴力。  回復  更多評論
              

            # re: 模擬window桌面實現 2008-02-26 11:46 大膽地
            很好  回復  更多評論
              

            # re: 模擬window桌面實現 2008-03-05 22:16 #Ant
            不錯的東西,很好很強大!  回復  更多評論
              

            # re: 模擬window桌面實現 2008-05-30 23:06 hoodlum1980
            windows的圖標,是一個ListView窗口。  回復  更多評論
              

            # re: 模擬window桌面實現 2009-03-09 17:18 飄飄白云
            對右鍵彈出shell item菜單的改進:

            新添加一個變量:
            ATL::CComPtr<IContextMenu3> m_pContextMenu;

            // 新右鍵菜單
            void RightMenu(ITEMIDLIST* pIID)
            {
            if (m_pFolder == 0){
            return;
            }

            HWND hwnd = *this;

            ATL::CComPtr<IContextMenu> cm;
            HRESULT hRslt = m_pFolder->GetUIObjectOf(
            hwnd,
            1,
            (LPCITEMIDLIST*) &(pIID),
            IID_IContextMenu,
            0,
            (void**) &cm);
            if (FAILED(hRslt)) {
            return;
            }

            HMENU hMenu = ::CreatePopupMenu();

            hRslt = cm->QueryContextMenu(hMenu, 0, 1, 0x7fff, CMF_NORMAL);
            if (SUCCEEDED(hRslt)) {
            WTL::CPoint pt;
            ::GetCursorPos(&pt);

            m_pContextMenu.Release();
            cm->QueryInterface(&m_pContextMenu);

            SetForegroundWindow(hwnd);

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

            ::PostMessageW(hwnd, WM_NULL, 0, 0);

            m_pContextMenu.Release();

            if (cmd != 0) {
            CMINVOKECOMMANDINFO ci = { 0};
            ci.cbSize = sizeof(ci);
            ci.hwnd = hwnd;
            ci.lpVerb = (LPCSTR) MAKEINTRESOURCE(cmd - 1);
            ci.nShow = SW_SHOWNORMAL;

            cm->InvokeCommand(&ci);
            }
            }

            ::DestroyMenu(hMenu);
            }

            添加處理菜單消息的函數:
            MESSAGE_HANDLER(WM_INITMENUPOPUP, OnMenuHandler)
            MESSAGE_HANDLER(WM_DRAWITEM, OnMenuHandler)
            MESSAGE_HANDLER(WM_MENUCHAR, OnMenuHandler)
            MESSAGE_HANDLER(WM_MEASUREITEM, OnMenuHandler)

            LRESULT OnMenuHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
            {
            LRESULT lResult = 0;

            if (m_pContextMenu != 0) {
            m_pContextMenu->HandleMenuMsg2(uMsg, wParam, lParam, &lResult);
            }

            return lResult;
            }
              回復  更多評論
              

            区久久AAA片69亚洲| 囯产极品美女高潮无套久久久| 亚洲欧洲精品成人久久曰影片 | 久久夜色精品国产欧美乱| 精品熟女少妇aⅴ免费久久| 久久国产精品成人片免费| 久久精品国产亚洲AV蜜臀色欲 | 久久精品国产亚洲AV不卡| 久久国产精品一区二区| 精品无码久久久久久午夜| 久久久无码人妻精品无码| 亚洲中文字幕无码久久精品1| 久久天天躁狠狠躁夜夜avapp | 精品久久人人做人人爽综合| 91久久精品国产91性色也| 7国产欧美日韩综合天堂中文久久久久 | 精品伊人久久大线蕉色首页| 久久香综合精品久久伊人| 久久精品国产免费观看| 无码八A片人妻少妇久久| 久久久久亚洲精品日久生情| 久久伊人五月丁香狠狠色| 久久精品日日躁夜夜躁欧美| 亚洲狠狠婷婷综合久久久久 | 亚洲精品无码久久久久| 久久午夜无码鲁丝片| 久久91综合国产91久久精品| AAA级久久久精品无码区| 久久久免费观成人影院| 精品多毛少妇人妻AV免费久久| 伊人久久大香线焦AV综合影院| 99久久99这里只有免费费精品 | 日本久久久精品中文字幕| 久久精品国产黑森林| 日韩人妻无码一区二区三区久久99| 中文字幕日本人妻久久久免费 | 欧美日韩中文字幕久久久不卡| 中文字幕精品久久| 精品蜜臀久久久久99网站| 麻豆精品久久精品色综合| 亚洲精品97久久中文字幕无码|