之前用win10自带的壁纸工具总感觉有些不方便,有些不喜欢的壁纸不能够删除,喜欢的也不能收藏,于是自己用mfc做了一个。
实现的功能如下:
1.开机自启动
2.自动缩小到系统托盘
3.快捷键实现壁纸切换,收藏和删除
其中还是有些知识点需要注意的
1)是开机自启动功能,这个地方有些问题的是我在OnInitDialog里做了读取文件的操作,但是当设置为自启动的时候程序的启动路径不是原来的了,导致文件读取失败,有类似读取配置文件的操作的时候需要特别注意
bool CBeautyDlg::autoRun(bool run)//自启动设置
{
HKEY hKey;
LPCTSTR lpRun = "Software\\Microsoft\\Windows\\CurrentVersion\\Run";
long lRet = RegOpenKeyEx(HKEY_CURRENT_USER, lpRun, 0, KEY_ALL_ACCESS, &hKey);
if (lRet == ERROR_SUCCESS)
{
if (run)
{
char pFileName[MAX_PATH] = { 0 };
//得到程序自身的全路径
DWORD dwRet = GetModuleFileName(NULL, pFileName, MAX_PATH);
//添加一个子Key,并设置值
lRet = RegSetValueEx(hKey, "Beauty", 0, REG_SZ, (BYTE*)pFileName, dwRet);
if (lRet != ERROR_SUCCESS)
AfxMessageBox("系统参数错误,不能随系统启动");
}
else
RegDeleteValue(hKey, "Beauty");
RegCloseKey(hKey);
}
else
{
RegCloseKey(hKey);
return false;
}
return true;
}
2)程序启动时需要自动隐藏显示并缩小到系统托盘,这个地方有个问题是一开始在OnInitDialog调用ShowWindow(SW_HIDE);是没有效果的,网上也有比较多的方法,我找到一种比较好的方法是在OnInitDialog增加以下代码
MoveWindow(0, 0, 0, 0);//将窗口移动看不见的地方
ShowWindow(SW_HIDE);//然后调用隐藏
ModifyStyleEx(WS_EX_APPWINDOW, WS_EX_TOOLWINDOW);
这样处理后,需要在点击托盘后重新恢复显示
MoveWindow(rect.top, rect.left, rect.Width(), rect.Height() * 1.1);
CenterWindow();
ModifyStyleEx(WS_EX_TOOLWINDOW, WS_EX_APPWINDOW);
this->ShowWindow(SW_SHOW);
这样程序开始的时候就不会出现界面了,而且也不会出现闪烁的情况
3)设置托盘的时候也要注意一点,在程序关闭的时候需要调用Shell_NotifyIcon(NIM_DELETE,&nid);//在托盘区删除图标,这句可以加在重载的destroywindow的函数里,不加的话会出现系统图标残留的情况
nid.cbSize = (DWORD)sizeof(NOTIFYICONDATA);
nid.hWnd = this->m_hWnd;
nid.uID = IDR_MAINFRAME;
nid.uFlags = NIF_ICON|NIF_MESSAGE|NIF_TIP ;
nid.uCallbackMessage = WM_SHOWMAIN;//自定义的消息名称
nid.hIcon = LoadIcon(AfxGetInstanceHandle(),MAKEINTRESOURCE(IDR_MAINFRAME));
strcpy(nid.szTip,"我的壁纸");//信息提示条为“我的壁纸”
Shell_NotifyIcon(NIM_ADD,&nid);//在托盘区添加图标
ShowWindow(SW_HIDE);//隐藏主窗口
m_bShow = false;
4)设置壁纸的操作,根据规定操作执行就行了
BOOL CBeautyDlg::SetWallPaper(CString strPath)
{
HRESULT hr;
IActiveDesktop* pIAD;
//Applications must initialize the COM library before they can call COM library functions
CoInitialize(NULL);
//创建接口的实例
hr = CoCreateInstance(CLSID_ActiveDesktop, NULL, CLSCTX_INPROC_SERVER,
IID_IActiveDesktop, (void**)&pIAD);
if (!SUCCEEDED(hr)) return FALSE;
//将文件名改为宽字符串,这是IActiveDesktop::SetWallpaper的要求
WCHAR wszWallpaper[MAX_PATH];
LPTSTR lpStr = strPath.GetBuffer(strPath.GetLength());
MultiByteToWideChar(CP_ACP, 0, lpStr, -1, wszWallpaper, MAX_PATH);
strPath.ReleaseBuffer();
//设置墙纸
hr = pIAD->SetWallpaper(wszWallpaper, 0);
if (!SUCCEEDED(hr)) return FALSE;
//设置墙纸的样式
WALLPAPEROPT wpo;
wpo.dwSize = sizeof(wpo);
wpo.dwStyle = WPSTYLE_CENTER;
hr = pIAD->SetWallpaperOptions(&wpo, 0);
if (!SUCCEEDED(hr)) return FALSE;
//应用墙纸的设置
hr = pIAD->ApplyChanges(AD_APPLY_ALL);
if (!SUCCEEDED(hr)) return FALSE;
//读取墙纸的文件名并打印在debug窗口内
hr = pIAD->GetWallpaper(wszWallpaper, MAX_PATH, 0);
CString strFile = wszWallpaper;
TRACE(strFile); //如果不用位图的话,这里有你意想不到的发现
//释放接口的实例
pIAD->Release();
CoUninitialize();
return TRUE;
}