准备资源:
1 VS,本人用的是2010。
2 一个TXT,用来存放要背的单词、例句,内容随意(小说也行哦),因为一次显示一行,所以一行内容不要太多。
制作过程:
首先建立以对话框为基类的工程,在资源视图,把对话框的长宽,调成喜欢的大小。
增加edit控件,ID为"IDC_EDIT1"。
增加两个按钮,caption分别为"stop"、"exit"。
文件的操作需要如下头文件:
#include
#include
using namespace std;
以下头文件用于TRACE命令,debug时可以在output中输出LOG
#include
定义三个全局静态变量
static bool flag = true;//控制时间间隔的flag
static bool flag_time = true;//控制暂停的flag
static DWORD o = 0;//存储上一次文件读到哪里
由于CStdioFile对unicode的支持不好,需要把读出的字符串进行转化
进行unicode的转化函数的声明:
void ReadStringCharToUnicode(CString &str);
初始化函数中,定义两个timer,设置窗体的初始透明度
BOOL CJPWordDlg::OnInitDialog()
{
......
// TODO: Add extra initialization here
SetTimer(1, 5000, NULL);
SetTimer(2, 200, NULL);
// 初始透明度
const int INIT_TRANSPARENT = 100;
// 设置分层属性
SetWindowLong(this->GetSafeHwnd(), GWL_EXSTYLE, GetWindowLong(this->GetSafeHwnd(), GWL_EXSTYLE) | WS_EX_LAYERED);
// 设置透明度 0 - completely transparent 255 - opaque
SetLayeredWindowAttributes( 0, INIT_TRANSPARENT, LWA_ALPHA);
return TRUE; // return TRUE unless you set the focus to a control
}
在onPaint函数中,进行文件的读,读一行,显示在edit控件上
void CJPWordDlg::OnPaint()
{
......
CStdioFile file(_T("n1.txt"), CFile::modeRead);
CString line;
file.Seek(o,0);//接着上回读
while(file.ReadString(line) && flag && flag_time)
{
flag = false;
ReadStringCharToUnicode(line);
GetDlgItem( IDC_EDIT1 )->SetWindowText(line);
o = file.GetPosition();//记录上次的结果(读到哪了)
}
}
对unicode的转换函数:
void ReadStringCharToUnicode(CString &str)
{
char *szBuf = new char[str.GetLength() + 1];//注意“+1”,char字符要求结束符,而CString没有
memset(szBuf, '\0',str.GetLength());
int i;
for ( i = 0 ; i < str.GetLength(); i++)
{
szBuf[i] = (char)str.GetAt(i);
}
szBuf[i] = '\0';//结束符。否则会在末尾产生乱码。
int nLen;
WCHAR *ptch;
CString strOut;
if(szBuf == NULL)
{
return ;
}
nLen = MultiByteToWideChar(CP_ACP, 0, szBuf, -1, NULL, 0);//获得需要的宽字符字节数
ptch = new WCHAR[nLen];
memset(ptch, '\0', nLen);
MultiByteToWideChar(CP_ACP, 0, szBuf, -1, ptch, nLen);
str.Format(_T("%s"), ptch);
if(NULL != ptch)
delete [] ptch;
ptch = NULL;
if(NULL != szBuf)
delete []szBuf;
szBuf = NULL;
return ;
}
timer回调函数OnTimer()
timer1用来控制每一段时间出一条文件内容;
timer2用来每200毫秒监控一次鼠标位置,如果在窗体上,窗体变为不透明;如果不在窗体上,即离开窗体,窗体变为半透明。
void CJPWordDlg::OnTimer(UINT_PTR nIDEvent)
{
// TODO: Add your message handler code here and/or call default
CPoint pntCursor;
switch (nIDEvent)
{
case 1:
flag = true;
OnPaint();
break;
case 2:
if ( GetCursorPos( &pntCursor ))
{
CRect rc;
this->GetWindowRect( &rc );
if( rc.PtInRect(pntCursor))
{
SetLayeredWindowAttributes( 0, 500, LWA_ALPHA);
}
else
{
SetLayeredWindowAttributes( 0, 100, LWA_ALPHA);
}
}
OnPaint();
break;
default:
break;
}
CDialogEx::OnTimer(nIDEvent);
}
按钮"stop"的消息响应函数,由前面定义的flag来控制是否暂停
void CJPWordDlg::OnClickedstop()
{
if(true == flag_time)
{
flag_time = false;
GetDlgItem(IDC_BUTTON1)->SetWindowText(_T("start"));
}
else
{
flag_time = true;
GetDlgItem(IDC_BUTTON1)->SetWindowText(_T("stop"));
}
// TODO: Add your control notification handler code here
}
CJPWordDlg::OnCtlColor函数用来设置窗体的外观,如字体颜色等
HBRUSH CJPWordDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
HBRUSH hbr = CDialogEx::OnCtlColor(pDC, pWnd, nCtlColor);
// TODO: Change any attributes of the DC here
// TODO: Return a different brush if the default is not desired
CBrush m_Brush;
m_Brush.CreateSolidBrush(RGB(255,0,0));
if (pWnd->GetDlgCtrlID() == IDC_EDIT1) //第一个编辑框
{
pDC->SetBkColor(RGB(255,0,0)); // 输入文本的的底色
pDC->SetTextColor(RGB(255,0,0)); // 输入文本的颜色
hbr = (HBRUSH) m_Brush; // 编辑框控件的填充色
}
return hbr;
}
LRESULT CJPWordDlg::OnNcHitTest(CPoint point)
{
// TODO: Add your message handler code here and/or call default
UINT nHitTest = CDialogEx::OnNcHitTest (point);
CRect rc;
GetClientRect(&rc);
ClientToScreen(&rc);
return rc.PtInRect(point) ? HTCAPTION : CDialog::OnNcHitTest(point);
}
效果图:未在窗体上移动时,显示半透明效果