📄 start.cpp
字号:
{
LPMENUSTRUCT lpms;
int iItemID = 1;
// These globals are a reminder that the menu drawing is starting now
g_bAlreadyDrawn = FALSE; // Not already drawn
g_bFirstTime = TRUE; // First time we enter
// Creates an empty menu
HMENU hmenu = CreatePopupMenu();
// Filter string for *.lnk
TCHAR szDir[MAX_PATH] = {0};
lstrcpy(szDir, szPath);
if(szDir[lstrlen(szDir) - 1] != '\\')
lstrcat(szDir, __TEXT("\\"));
TCHAR szBuf[MAX_PATH] = {0};
wsprintf(szBuf, __TEXT("%s*.lnk"), szDir);
// Search for .lnk files
WIN32_FIND_DATA wfd;
HANDLE h = FindFirstFile(szBuf, &wfd);
while(h != INVALID_HANDLE_VALUE)
{
// Resolve the shortcut
SHORTCUTSTRUCT ss;
ZeroMemory(&ss, sizeof(SHORTCUTSTRUCT));
wsprintf(szBuf, __TEXT("%s\\%s"), szDir, wfd.cFileName);
SHResolveShortcut(szBuf, &ss);
// Prepare per-item data using ID, description and target file
lpms = reinterpret_cast<LPMENUSTRUCT>(GlobalAllocPtr(GHND, sizeof(MENUSTRUCT)));
lpms->iItemID = iItemID;
if(!lstrlen(ss.pszDesc))
lstrcpy(lpms->szText, wfd.cFileName);
else
lstrcpy(lpms->szText, ss.pszDesc);
lstrcpy(lpms->szFile, ss.pszTarget);
// Add the item
AppendMenu(hmenu, MF_OWNERDRAW, iItemID++, reinterpret_cast<LPTSTR>(lpms));
// Next file
if(!FindNextFile(h, &wfd))
{
FindClose(h);
break;
}
}
// Add the separator and the 'Restore' item
AppendMenu(hmenu, MF_OWNERDRAW | MF_SEPARATOR, 0, NULL);
lpms = reinterpret_cast<LPMENUSTRUCT>(GlobalAllocPtr(GHND, sizeof(MENUSTRUCT)));
lpms->iItemID = ID_FILE_EXIT;
lstrcpy(lpms->szText, __TEXT("Restore Previous Settings"));
lstrcpy(lpms->szFile, "");
AppendMenu(hmenu, MF_OWNERDRAW, ID_FILE_EXIT, reinterpret_cast<LPTSTR>(lpms));
return hmenu;
}
HRESULT SHResolveShortcut(LPCTSTR szLnkFile, LPSHORTCUTSTRUCT lpss)
{
WCHAR wszLnkFile[MAX_PATH] = {0};
IShellLink* pShellLink = NULL;
IPersistFile* pPF = NULL;
// Create the appropriate COM server
HRESULT hr = CoCreateInstance(CLSID_ShellLink, NULL,
CLSCTX_INPROC_SERVER, IID_IShellLink,
reinterpret_cast<LPVOID*>(&pShellLink));
if(FAILED(hr))
return hr;
// Get the IPersistFile interface to load the LNK file
hr = pShellLink->QueryInterface(IID_IPersistFile, reinterpret_cast<LPVOID*>(&pPF));
if(FAILED(hr))
{
pShellLink->Release();
return hr;
}
// Load the shortcut (Unicode name)
MultiByteToWideChar(CP_ACP, 0, szLnkFile, -1, wszLnkFile, MAX_PATH);
hr = pPF->Load(wszLnkFile, STGM_READ);
if(FAILED(hr))
{
pPF->Release();
pShellLink->Release();
return hr;
}
// Resolve the link
hr = pShellLink->Resolve(NULL, SLR_ANY_MATCH);
if(FAILED(hr))
{
pPF->Release();
pShellLink->Release();
return hr;
}
// Extract the information to fill lpss
if(lpss != NULL)
{
TCHAR szPath[MAX_PATH] = {0};
TCHAR szDesc[MAX_PATH] = {0};
TCHAR szIcon[MAX_PATH] = {0};
WORD w = 0;
WORD wIcon = 0;
WIN32_FIND_DATA wfd;
pShellLink->GetPath(szPath, MAX_PATH, &wfd, SLGP_SHORTPATH);
pShellLink->GetDescription(szDesc, MAX_PATH);
pShellLink->GetHotkey(&w);
pShellLink->GetIconLocation(szIcon, MAX_PATH, reinterpret_cast<int*>(&wIcon));
lpss->pszTarget = szPath;
lpss->pszDesc = szDesc;
lpss->pszIconPath = szIcon;
lpss->wHotKey = w;
lpss->wIconIndex = wIcon;
}
pPF->Release();
pShellLink->Release();
return hr;
}
void MeasureItem(HWND hwnd, LPMEASUREITEMSTRUCT lpmis)
{
SIZE size;
int iItemID = lpmis->itemID;
LPMENUSTRUCT lpms = reinterpret_cast<LPMENUSTRUCT>(lpmis->itemData);
// Calculate the size of the item string
HDC hdc = GetDC(hwnd);
GetTextExtentPoint32(hdc, lpms->szText, lstrlen(lpms->szText), &size);
ReleaseDC(hwnd, hdc);
// Set width and height for the item
lpmis->itemWidth = DEFBITMAPSIZE + DEFBANDSIZE + size.cx;
// A separator has a zero ID
if(iItemID)
lpmis->itemHeight = DEFBITMAPSIZE;
else
lpmis->itemHeight = DEFSEPSIZE;
}
/*---------------------------------------------------------------*/
// DrawItem
// Handle the WM_DRAWITEM message on per-item basis
/*---------------------------------------------------------------*/
void DrawItem(LPDRAWITEMSTRUCT lpdis)
{
TCHAR szItem[ITEMSIZE] = {0};
TCHAR szFile[MAX_PATH] = {0};
COLORREF crText, crBack;
HICON hIcon = NULL;
LPMENUSTRUCT lpms = reinterpret_cast<LPMENUSTRUCT>(lpdis->itemData);
int iItemID = lpdis->itemID;
int iTopEdge = 0;
// Save the item text and target file
if(lpms)
{
lstrcpy(szItem, lpms->szText);
lstrcpy(szFile, lpms->szFile);
}
// Manage how to draw
if(lpdis->itemAction & (ODA_DRAWENTIRE | ODA_SELECT))
{
COLORREF clr;
RECT rtBand, rtBmp, rtText, rtItem, rt;
SIZE size;
// Defines rectangles for further use:
// lpdis->rcItem is the menu item rectangle
// rtBand: portion of the menu item area for vertical band
// rtBmp: portion of the menu item area for item icon
// rtText: portion of the menu item area for item text
CopyRect(&rt, &(lpdis->rcItem));
CopyRect(&rtBand, &rt);
rtBand.right = rtBand.left + DEFBANDSIZE;
CopyRect(&rtBmp, &rt);
rtBmp.left = rtBand.right + DEFBORDERSIZE;
rtBmp.right = rtBmp.left + DEFBITMAPSIZE;
CopyRect(&rtText, &rt);
rtText.left = rtBmp.right + 2 * DEFBORDERSIZE;
CopyRect(&rtItem, &rt);
rtItem.left += DEFBANDSIZE + DEFBORDERSIZE;
// If it is the first item, store the y-coordinate
if(g_bFirstTime)
{
iTopEdge = rtBand.top;
g_bFirstTime = FALSE;
}
// Draw the band rectangle and the vertical bitmap
if(!g_bAlreadyDrawn)
{
// Draw the band area in blue
clr = SetBkColor(lpdis->hDC, RGB(0, 0, 255));
ExtTextOut(lpdis->hDC, 0, 0, ETO_CLIPPED | ETO_OPAQUE, &rtBand, NULL, 0, NULL);
SetBkColor(lpdis->hDC, clr);
// If it is the last item, determine the menu height,load the bitmap, and draw
if(iItemID == ID_FILE_EXIT)
{
int iMenuHeight = rtBand.bottom - iTopEdge;
HBITMAP hbm = LoadBitmap(g_hInstance, MAKEINTRESOURCE(IDB_LOGO));
DrawBitmap(lpdis->hDC, 0, iMenuHeight, hbm);
DeleteObject(hbm);
g_bAlreadyDrawn = TRUE;
}
}
// Everything done so far is unaffected by seletion state.
// Now need to draw icon and text with respect to
// the selection state and hence the background color
if(lpdis->itemState & ODS_SELECTED)
{
crText = SetTextColor(lpdis->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
crBack = SetBkColor(lpdis->hDC, GetSysColor(COLOR_HIGHLIGHT));
}
// Clear the area with the correct background color
ExtTextOut(lpdis->hDC, rtText.left, rtText.left,
ETO_CLIPPED | ETO_OPAQUE, &rtItem, NULL, 0, NULL);
// Get the icon to draw. Load it from our resource if it is
// the last item. Otherwise, determine the system icon
// for the shortcut's target file
if(iItemID==ID_FILE_EXIT)
hIcon = LoadIcon(g_hInstance, MAKEINTRESOURCE(iItemID));
else
{
SHFILEINFO sfi;
ZeroMemory(&sfi, sizeof(SHFILEINFO));
SHGetFileInfo(szFile, 0, &sfi, sizeof(SHFILEINFO), SHGFI_ICON);
hIcon = sfi.hIcon;
}
// Draw the icon (transparence is automatic)
if(hIcon)
{
DrawIcon(lpdis->hDC, rtBmp.left, rtBmp.top, hIcon);
DestroyIcon(hIcon);
}
// Draw the text (one line centered vertically)
if(!iItemID)
{
// It's a separator
rt.top++;
rt.bottom = rt.top + DEFBORDERSIZE;
rt.left = rt.left + DEFBANDSIZE + DEFBORDERSIZE;
DrawEdge(lpdis->hDC, &rt, EDGE_ETCHED, BF_RECT);
}
else
{
// Get the size of the text according to the font
GetTextExtentPoint32(lpdis->hDC, szItem, lstrlen(szItem), &size);
// Center it vertically
int iy = ((lpdis->rcItem.bottom - lpdis->rcItem.top) - size.cy) / 2;
iy = lpdis->rcItem.top + (iy >= 0 ? iy : 0);
rtText.top = iy;
DrawText(lpdis->hDC, szItem, lstrlen(szItem), &rtText, DT_LEFT | DT_EXPANDTABS);
}
}
}
/*---------------------------------------------------------------*/
// DrawBitmap
// Draw the bitmap with the vertical logo
/*---------------------------------------------------------------*/
void DrawBitmap(HDC hdc, int x, int iHeight, HBITMAP hbm)
{
// This function calculates the y-coordinate based on the height
// of the area to cover. The bitmap will be aligned with the bottom
BITMAP bm;
// Creates a memory device context and selects the bitmap in it
HDC hdcMem = CreateCompatibleDC(hdc);
HBITMAP hOldBm = static_cast<HBITMAP>(SelectObject(hdcMem, hbm));
// Obtains information about the bitmap
GetObject(hbm, sizeof(BITMAP), &bm);
// Determine the y-coordinate
int y = iHeight - bm.bmHeight;
y = (y < 0 ? 0 : y);
// Transfer the bitmap from memory DC to the menu DC
BitBlt(hdc, x, y, bm.bmWidth, bm.bmHeight, hdcMem, 0, 0, SRCCOPY);
// Free the memory DC
SelectObject(hdcMem, hOldBm);
DeleteDC(hdcMem);
}
/*-------------------------------------------------------*/
// HandleResults
// Run the program the user clicked
/*-------------------------------------------------------*/
void HandleResults(HMENU hmenu, int iCmd)
{
MENUITEMINFO mii;
LPMENUSTRUCT lpms;
if(iCmd <= 0)
return;
if(iCmd == ID_FILE_EXIT)
{
UninstallHandler();
return;
}
mii.cbSize = sizeof(MENUITEMINFO);
mii.fMask = MIIM_DATA;
GetMenuItemInfo(hmenu, iCmd, FALSE, &mii);
lpms = reinterpret_cast<LPMENUSTRUCT>(mii.dwItemData);
ShellExecute(NULL, __TEXT("open"), lpms->szFile, NULL, NULL, SW_SHOW);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -