MFC小功能(只运行一个程序,托盘小图标闪烁等)
1.只运行一个程序
BOOL CClientApp::InitInstance()
{
// 创建互斥
HANDLE hMutex = ::CreateMutex(NULL, TRUE, "MyProjectRunFlag ");
if (GetLastError() == ERROR_ALREADY_EXISTS)
{
// 如果实例已经运行
HWND hWin = ::FindWindow(NULL, "MyClient"); //MyClient:窗口名称,可在资源文件.rc中查看
if (hWin)
{
if (!IsWindowVisible(hWin))
{
// 如果最小化状态就将窗体恢复
PostMessage(hWin, WM_SYSCOMMAND, SC_RESTORE, 0);
}
// 窗体置前
SetForegroundWindow(hWin);
BringWindowToTop(hWin);
}
if (hMutex)
CloseHandle(hMutex);
return 0;
}
......
}
2.添加托盘,有消息托盘图标闪烁
//CClientDlg.h--------------------------------------------------------------------------------
#define WM_SHOWTASK WM_USER+8 //托盘图标双击,右键等消息号
#define ID_UPDATE_IOFO_TIME WM_USER+9 //添加定时器消息号,定时器触发图标闪烁
class CClientDlg: public CDialogEx
{
......
public:
void InitSalver(); //初始托盘函数
afx_msg void OnTimer(UINT_PTR nIDEvent); //定时器实现消息闪烁
LRESULT OnShowTask(WPARAM wParam, LPARAM lParam); //双击弹出对话框停止闪烁,右键退出程序
virtual BOOL DestroyWindow(); //程序退出,删除托盘图标
afx_msg void OnClose(); //对话框关闭最小化到托盘
afx_msg void OnSize(UINT nType, int cx, int cy); //对话框最小化标题栏仍然显示图标
private:
NOTIFYICONDATA m_nid; //托盘变量
bool m_bShowPicture{ true }; //是否显示状态标识,用于消息闪烁
};
/
//CClientDlg.cpp---------------------------------------------------------------------------
//初始化托盘图标
void CClientDlg::InitSalver()
{
/*
更换程序图标
1)导入ICon资源.ico文件,删掉原来的IDR_MAINFRAME,将导入的文件id改成IDR_MAINFRAME
2).rc指定文件路径:IDR_MAINFRAME ICON "./res/XX.ico"
*/
m_nid.cbSize = (DWORD)sizeof(NOTIFYICONDATA);
m_nid.hWnd = this->m_hWnd;
m_nid.uID = IDR_MAINFRAME;
m_nid.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
m_nid.uCallbackMessage = WM_SHOWTASK; // 自定义的消息名称
m_nid.hIcon = LoadIcon(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDR_MAINFRAME));
strcpy(m_nid.szTip, "我的小程序"); // 信息提示条为"我的小程序",VS2008 UNICODE编码用wcscpy_s()函数
Shell_NotifyIcon(NIM_ADD, &m_nid); // 在托盘区添加图标
}
//定时器函数实现消息闪烁-----------------------------------------------------------------
BEGIN_MESSAGE_MAP(CClientDlg, CDialogEx)
.........
ON_WM_TIMER()
END_MESSAGE_MAP()
//触发定时函数,在需要触发的地方判断窗口最小化闪烁提示
/*
if (this->IsIconic())
{
SetTimer(ID_UPDATE_IOFO_TIME, 500, NULL);
}
*/
void CClientDlg::OnTimer(UINT_PTR nIDEvent)
{
switch (nIDEvent)
{
case ID_UPDATE_IOFO_TIME:
{
if (m_bShowPicture)
{
m_bShowPicture = false;
Shell_NotifyIcon(NIM_DELETE, &m_nid);
m_nid.hIcon = LoadIcon(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDI_ICON2));
Shell_NotifyIcon(NIM_ADD, &m_nid);
}
else
{
m_bShowPicture = true;
Shell_NotifyIcon(NIM_DELETE, &m_nid);
m_nid.hIcon = LoadIcon(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDR_MAINFRAME));
Shell_NotifyIcon(NIM_ADD, &m_nid);
}
}break;
default:
break;
}
CDialogEx::OnTimer(nIDEvent);
}
//实现双击弹出对话框关闭闪烁,右键退出程序------------------------------------------------------------
BEGIN_MESSAGE_MAP(CClientDlg, CDialogEx)
.........
ON_MESSAGE(WM_SHOWTASK, OnShowTask)
END_MESSAGE_MAP()
LRESULT CClientDlg::OnShowTask(WPARAM wParam, LPARAM lParam)
{
if (wParam != IDR_MAINFRAME)
return 1;
switch (lParam)
{
case WM_RBUTTONUP: // 右键起来时弹出菜单
{
LPPOINT lpoint = new tagPOINT;
::GetCursorPos(lpoint); // 得到鼠标位置
CMenu menu;
menu.CreatePopupMenu(); // 声明一个弹出式菜单
menu.AppendMenu(MF_STRING, WM_DESTROY, "关闭");
menu.TrackPopupMenu(TPM_LEFTALIGN, lpoint->x, lpoint->y, this);
HMENU hmenu = menu.Detach();
menu.DestroyMenu();
delete lpoint;
}
break;
case WM_LBUTTONDBLCLK: // 双击左键的处理
{
this->ShowWindow(SW_SHOWNORMAL); // 显示主窗口
this->SetForegroundWindow();
this->SetFocus();
KillTimer(ID_UPDATE_LIST_TIME);
if (!m_bShowPicture)
{
m_bShowPicture = true;
Shell_NotifyIcon(NIM_DELETE, &m_nid);
m_nid.hIcon = LoadIcon(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDR_MAINFRAME));
Shell_NotifyIcon(NIM_ADD, &m_nid);
}
}
break;
}
return 0;
}
//程序退出删除图标-----------------------------------------------------------------------
BOOL CClientDlg::DestroyWindow()
{
Shell_NotifyIcon(NIM_DELETE, &m_nid);
return CDialogEx::DestroyWindow();
}
//关闭对话框最小化到托盘------------------------------------------------------------------
BEGIN_MESSAGE_MAP(CClientDlg, CDialogEx)
......
ON_WM_CLOSE()
END_MESSAGE_MAP()
void CClientDlg::OnClose()
{
ShowWindow(SW_HIDE); // 当最小化市,隐藏主窗口
}
//对话框最小化标题栏仍然显示图标----------------------------------------------------------
BEGIN_MESSAGE_MAP(CClientDlg, CDialogEx)
......
ON_WM_SIZE()
END_MESSAGE_MAP()
void CClientDlg::OnSize(UINT nType, int cx, int cy)
{
CDialogEx::OnSize(nType, cx, cy);
}
3.屏蔽回车按钮
class CClientDlg: public CDialogEx
{
// 构造
public:
virtual BOOL PreTranslateMessage(MSG* pMsg);
}
BOOL CClientDlg::PreTranslateMessage(MSG* pMsg)
{
// TODO: 在此添加专用代码和/或调用基类
if (pMsg->message == WM_KEYDOWN)
{
switch (pMsg->wParam)
{
case VK_RETURN://屏蔽回车
// OnKeyDown(VK_SPACE, LOWORD(pMsg ->lParam), HIWORD(pMsg->lParam));
return TRUE;
case VK_ESCAPE://屏蔽Esc
return TRUE;
}
}
return CDialogEx::PreTranslateMessage(pMsg);
}
4.禁止对话框拖动改变大小
ModifyStyle(WS_THICKFRAME, 0, SWP_FRAMECHANGED) //在OnInitDialog()添加
5.去掉小图标运行拖动改变大小
//.rc 添加
STYLE DS_SETFONT | DS_MODALFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX| WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME
6.防止窗口闪烁
1)在模态对话框类中,CDialog::OnCancel()闪烁处理
// 1)在模态对话框类中
void CMyDlg::OnCancel()
{
// 清理工作...
EndDialog(IDCANCEL); // 关闭模态对话框,不要直接调用DestroyWindow
}
2)DoModal时父对话框闪缩
//CMyParentDlg.h
afx_msg BOOL OnEraseBkgnd(CDC* pDC);
//CMyParentDlg.cpp
BEGIN_MESSAGE_MAP(CMyParentDlg, CDialog)
ON_WM_ERASEBKGND()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
BOOL CMyParentDlg::OnEraseBkgnd(CDC* pDC)
{
return TRUE;
}
7.按钮添加图片
在资源中把它的Owner Draw属性设为true.
//CMyDlg.h
CBitmapButton m_bitmapBtn;
//CMyDlg.cpp
//把DDX_Control(pDX, IDC_BUTTON1, m_bitmapBtn);这一行注释掉
m_bitmapBtn.AutoLoad(IDC_BUTTON1,this);
m_bitmapBtn.LoadBitmaps(IDB_BITMAP2,IDB_BITMAP1,IDB_BITMAP1);