MFC制作便签整体思路

大体思路
1.系统化托盘图标。先搞一个父窗口,把最小化图标做出来,做一个MENU绑到托盘菜单添加消息相应
2.便签的主体。再搞一个窗口,由父窗口新建或读取配置时调用弹出,运行程序时根据配置文件设置窗口
3.配置文件的读写
4.整合为完整程序

1.系统化托盘图标

(1)最小化图标
主要用到NOTIFYICONDATA和Shell_NotifyIcon。
先搞一个NOTIFYICONDATA指针,把cbSize(按字节计算的结构体)hWnd(接收通知区域消息的窗口句柄)。hIcon(将要添加/修改/删除的图标句柄)szTip(一个标准提示字符串)。uCallbackMessage 当点击图标,对图标操作时向指定窗口发送消息,等成员赋值
然后用Shell_NotifyIcon系统化托盘图标BOOL Shell_NotifyIcon(
DWORD dwMessage,
PNOTIFYICONDATA lpdata
);
dwMessage:[输入参数] 说明要执行的动作。比如:NIM_ADD 增加一个图标到托盘区
lpdata:[输入参数] 一个指向NOTIFYICONDATA结构的指针。
代码:

NOTIFYICONDATA minicon;

    minicon.cbSize=sizeof(NOTIFYICONDATA);
	minicon.hIcon=m_hIcon;
	minicon.hWnd=m_hWnd;
	lstrcpy(minicon.szTip,_T("便利贴"));
	minicon.uCallbackMessage = NOTIFY1;
	minicon.uFlags=NIF_ICON | NIF_MESSAGE | NIF_TIP;//
	Shell_NotifyIcon(NIM_ADD,&minicon);

(2)主窗口隐藏ShowWindow(SW_HIDE);
(3)托盘添加消息响应
先在资源文件中添加一个MENU,写上自己的功能菜单名
添加消息响应函数afx_msg LRESULT CMyDlg::OnIconNotify(WPARAM wParam, LPARAM lParam)
把MENU添加进去
代码

        CMenu menu;
		menu.LoadMenu(IDR_MENU1);  
		CPoint point;
		GetCursorPos(&point);
		SetForegroundWindow();
		menu.GetSubMenu(0)->TrackPopupMenu(
			TPM_LEFTBUTTON|TPM_RIGHTBUTTON,
			point.x, point.y, this, NULL);

后面添加MENU方法都一样
到此第一步已经完成,效果就是运行程序后只有系统托盘图标,点击会弹出自己画的菜单。
在这里插入图片描述
菜单中的功能应为要有便利贴参与,所以在做好便利贴主体后再实现。其中退出可以先给MENU添加事件PostQuitMessage(0);

2.便签主体

(更改背景,字体颜色,设置标题,删除、隐藏便签)
新建一个dialog(模态对话框)控件只有一个编辑框,放大到dialog一样。给对话框添加一个类
类比1再搞个MENU,绑在新的dialog上,并给各个菜单选项添加事件
(1)新建dialog初始化背景字体颜色,字体大小。
定义一个CBRUSH cb(画刷) CFONT cf(字体),自己先给定初始化值,编辑框添加控件变量(不是VALUE)
COLORREF backcolor;//背景颜色
COLORREF fontcolor;//字体颜色
代码

    backcolor=RGB(255,255,0);
	fontcolor=RGB(0,0,255);
	cb.CreateSolidBrush(backcolor);
	cf.CreatePointFont(200,_T("黑体"));
	eedit.SetFont(&cf);

添加OnCtlColor消息,添加方法:右键点击dialog->类向导->消息,找到OnCtlColor添加消息
代码

HBRUSH dialog1::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
	HBRUSH hbr = CDialogEx::OnCtlColor(pDC, pWnd, nCtlColor);
	// TODO:  在此更改 DC 的任何特性
	if ( pWnd->GetDlgCtrlID() == IDC_EDIT1){
		pDC->SetTextColor(fontcolor);
		pDC->SetBkColor(backcolor);
		pDC->SelectObject(&cb);
		hbr = (HBRUSH)cb;
	}
	// TODO:  如果默认的不是所需画笔,则返回另一个画笔
	return hbr;
}

此时新建dialog时,弹出的对话框就是已经有背景颜色且字体类型颜色也被更改。
(2)调用选色板更改背景颜色,字体颜色更改类似。主要用到MFC自带的CColorDialog
先定义变量CColorDialog myDlg1,然后GetColor()获取选择的颜色,删除画刷指向的对象,再新建画刷
代码

CColorDialog myDlg1;
	if(IDOK == myDlg1.DoModal()){
		backcolor = myDlg1.GetColor();
		cb.DeleteObject();
		cb.CreateSolidBrush(backcolor);
	}

字体颜色更改类似
(2)更改标题
先画一个dialog用来填写标题名在这里插入图片描述
dialog添加类,给编辑框添加VALUE变量,确定按钮双击添加处理程序。点击菜单弹出此对话框过程不再赘述。
在点击确定后,UpdateData()将控件值给变量,再通过GetParent()找到父窗口更改父窗口的值,同时SendMessage(WM_CLOSE)关闭本窗口。
代码

    UpdateData(true);
	this->GetParent()->SetWindowTextW(newtitle);
	this->SendMessage(WM_CLOSE);

同时父窗口要把新值给标题变量。
删除和隐藏较简单,等配置文件读取做好后一起做。

3.配置文件的读写

读写主要涉及两个函数GetPrivateProfileString和WritePrivateProfileString
主要是CString类型也可以读int型

DWORD GetPrivateProfileString(
  LPCTSTR lpAppName,        // INI文件中的一个字段名[节名]可以有很多个节名
  LPCTSTR lpKeyName,        // lpAppName 下的一个键名,也就是里面具体的变量名
  LPCTSTR lpDefault,        // 如果lpReturnedString为空,则把个变量赋给lpReturnedString
  LPTSTR lpReturnedString,  // 存放键值的指针变量,用于接收INI文件中键值(数据)的接收缓冲区
  DWORD nSize,            // lpReturnedString的缓冲区大小
  LPCTSTR lpFileName        // INI文件的路径
);
UINT GetPrivateProfileInt(
  LPCTSTR lpAppName,  // INI文件中的一个字段名[节名]可以有很多个节名
  LPCTSTR lpKeyName,  // lpAppName 下的一个键名,也就是里面具体的变量名
  INT nDefault,       // 如果没有找到指定的数据返回,则把个变量值赋给返回值
  LPCTSTR lpFileName  // INI文件的路径
);

其中字段名、键名、存放键值的指针、缓冲区大小都是自己设置的。获取文件路径可能存在疑问。可以再对话框初始化时就先获取ini配置文件位置,DWORD GetModuleFileName(
  HMODULE hModule,//装载程序实例句柄,可以通过AfxGetInstanceHandle()获取
  LPTSTR lpFilename,//返回相应的路径
  DWORD nSize
  );

BOOL WritePrivateProfileString(
  LPCTSTR lpAppName,  // INI文件中的一个字段名[节名]可以有很多个节名
  LPCTSTR lpKeyName,  // lpAppName 下的一个键名,也就是里面具体的变量名
  LPCTSTR lpString,   // 键值,也就是数据
  LPCTSTR lpFileName  // INI文件的路径
)

例如保存标题(curtitle)

WritePrivateProfileString(tit,_T("标题"),curtitle,path);

tit字段名(如便签1、便签2等),curtitle标题变量,path路径
颜色的保存要先把RGB三个值分别取出来,然后format转为CString再保存

temp.Format(_T("%d %d %d"),GetRValue(backcolor),GetGValue(backcolor),GetBValue(backcolor));
WritePrivateProfileString(tit,_T("背景颜色"),temp,path);

读取是也是一样要RGB一个个读:

wchar_t *str=NULL;
str = new wchar_t[len];
GetPrivateProfileString(tit,_T("字体颜色"),_T(""),str,len,path);
temp=str;
str1=getString(temp);
a= _wtoi(str1);//CString转int
str1=getString(temp);
b=_wtoi(str1);
str1=getString(temp);
c=_wtoi(str1);
fontcolor=RGB(a,b,c);

因为读取颜色时得到的是存在空格的一串CString,自己写一个getstring()方法取得RGB三个值。
在这里插入图片描述

String dialog1::getString(CString &str){
	CString ss=_T("");
	str.Trim();//去掉两端空白字符
	str+=_T(" ");
	int t=str.Find(' ');//找空格,t返回第一个空格位置,没有找到返回-1
	if(t!=-1){
		ss=str.Left(t);//取空格左边数
		str=str.Mid(t+1);//str从第二个数开始
	}
	return ss;
}

配置文件读取大概内容就这些,主要就两个函数,可以先另外新建一个程序来熟悉配置文件读写,没问题再迁移到本程序中。

4.整合为完整程序

(1)(完整思路)我们可以把一个个便利贴放进数组,vector<dialog1*> notelist;//搞个dialog类型的动态数组,notelist[i]就代表第i个便利贴。运行程序时,先读取配置文件,如果配置文件中已经有便利贴,读取便利贴数量n,接着循环新建dialog,读取配置中的信息,将dialog中变量更新,如:

int len=notelist.size();//数组长度代表便利贴数量
for(int i =0;i<len;i++){
		dialog1 *p = new dialog1();
		notelist.push_back(p);
		p->Create(IDD_DIALOG1,NULL);//先创建窗口
		p->fetch(i,str);//读便利贴配置
		p->setnote();//更新窗口
	}

如果配置文件为空,点击新建窗口后,会新建一个指针p*,先push_back进数组,然后
list->Create(dialog,this)新建一个便利贴窗口。
至于程序运行过程中进行各种操作,改变的值不会立即写入配置文件,而是在退出时用DeleteFile()先删除原先的配置文件,然后,循环保存各个便签,就是上边讲的将每个便签的各种变量值写入配置文件。
隐藏便签功能的实现,搞个变量i在新建便签时,给i赋一个默认值,在隐藏便签的处理程序中,改变i的值,然后SW_HIDE隐藏此便签,下次打开程序时。
删除便签功能的实现,调用父窗口中的删除方法,通过迭代找到数组中当前便签,然后CloseWindow(),erase(),注意每次erase都可能使迭代器失效,要在失效前指向下一个位置,代码

for (vector<dialog1*>::iterator iter=notelist.begin();iter!=notelist.end();){
		if((*iter)==p){
			p->CloseWindow();
			delete p;
			notelist.erase(iter);
			break;
		}
		else
			iter++;
	} 

系统托盘上的显示所有菜单功能的实现,主要就是找到隐藏变量i不是默认值的便签,方法就是循环读取每个便签i的值,如果不是默认值将它改为默认值,然后SW_SHOW显示此便签。
系统托盘上的删除所有便签,在该菜单的处理程序中,循环用WM_CLOSE关闭所有的便签,然后直接notelist.clear()清空数组即可。

设定弹出时间功能还没想好

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值