摘 要 设计摘文快车(SuperGet),实现网页快速摘文,提高用户上网摘文的效率。
关键词 VC++6.0,MFC,网页,摘文
一、概述
浏览网页时,当看到一篇有用或有趣的文字,想把它“当”下来时,有的朋友选择将网页直接“另存为”保存,而有些朋友则选择:选中文本—〉复制—〉新建记事本—〉粘贴—〉保存—〉重命名,殊不知这样做无形中浪费了上网时间,积而累之,浪费的就不只是一点点琐碎的时间了。
设计本程序的目的就是为了方便用户,提高用户上网摘文得效率,节约宝贵的时间。VC是Microsoft的一个非常好用的C++编程工具,现在已经出到Microsoft Visual Studio 2008,大多数的C++程序员都喜欢用VC,不但开发环境友好,而且有功能强大的MFC(微软基础类库,Microsoft Foundation Class)支持。然而,MFC在.NET平台下没有太多的改进。因此,大部分的VC程序员都喜欢用VC++6.0开发MFC应用程序。
二、程序设计
首先,创建一个基于MFC的对话框界面的应用程序,命名为SuperGet。
1.皮肤设计
俗话说:“人靠衣装,马靠鞍”。软件同样应该具备一个友好、美观的用户界面。然而,VC的界面设计和时间处理方法非常复杂,无法在有限的时间内设计出美观、用户熟悉的操作界面。
于是在这里使用USkin来设计皮肤。
USkin的特性:
l 支持20多种Windows标准控件。
l 支持文件、颜色、打印、字体等标准对话框。
l 支持第三方/自定义控件。
l 支持所见即所得的皮肤文件编辑。
l 支持MDI/SDI/Dialog风格的应用程序。
l 支持WindowsBlind皮肤文件导入,多达万个现成皮肤供您使用。
l 支持颜色主题,一套皮肤可以演变成多种皮肤。
l 支持多种编程语言 。
l 支持多线程 。
l 支持动态换肤 。
l 支持所有弹出菜单,包括Edit控件右键弹出菜单。
l 只需三行代码即可实现换肤。
l 支持ListView/TreeView等控件滚动条换肤。
l 皮肤资源文件所占空间小。
(1)包含uskin.lib和USkin.h头文件。首先,将USkin.lib和USkin.h文件拷贝到工程目录下,然后工程—〉设置—〉Link—〉L对象/库模块中,添加USkin.lib,接着在SuperGetDlg.h文件中#include "USkin.h"。
(2)加载皮肤文件。首先,将皮肤文件(这里以ToMorning.u3为例)拷贝到工程目录下(编译后将ToMorning.u3和USkin.dll放到Debug文件夹中),然后在SuperGet.cpp添加如下代码:
BOOL CSuperGetApp::InitInstance()
{
AfxEnableControlContainer();
SetRegistryKey(_T("应用程序向导生成的本地应用程序"));
USkinInit(NULL,NULL,_T("ToMorning.u3")); //加载u3皮肤文件
CSuperGetDlg dlg;
m_pMainWnd = &dlg;
INT_PTR nResponse = dlg.DoModal();
if (nResponse == IDOK)
{
// TODO: 在此放置处理何时用“确定”来关闭
//对话框的代码
}
else if (nResponse == IDCANCEL)
{
// TODO: 在此放置处理何时用“取消”来关闭
//对话框的代码
}
USkinExit(); //USkin退出
由此,编译—〉构建—〉生成,一个漂亮的对话框界面就生成了。
2.绘制界面。(如图1所示)
图1:界面
3.程序代码
(1)主要的函数
void PerFormCtrlC(); 模拟ctrl+c按键
BOOL GetCopy(); 获得复制到剪贴板中的文本内容
void File_Save(); 将得到的文本内容保存到指定位置
void CutBlank(); 消除文本中的空格
LRESULT OnHotKey(WPARAM wp,LPARAM lp); 注册热键
void Release Focus(); 释放本程序的焦点
(2)函数说明
1)模拟ctrl+c按键
void CSuperGetDlg::PerFormCtrlC()
{
EmptyClipboard(); //清空剪贴板
Sleep(1000); //延时1s
//模仿键盘击键Ctrl+C
keybd_event(VK_CONTROL,MapVirtualKey(VK_CONTROL,0),0,0); //按住Ctrl,不放开
keybd_event(0x43,MapVirtualKey(0x43,0),0,0); //按住C键,不放开
keybd_event(0x43,MapVirtualKey(0x43,0), KEYEVENTF_KEYUP,0); //放开C键
keybd_event(VK_CONTROL,MapVirtualKey(VK_CONTROL,0),
KEYEVENTF_KEYUP,0); //放开Ctrl
}
2)从剪贴板中获得复制文本
BOOL CSuperGetDlg::GetCopy()
{
BOOL m_bcopy=TRUE; //设置copy为成功
//打开系统剪贴版
if(!OpenClipboard())
{
AfxMessageBox("无法打开剪贴版");
m_bcopy=FALSE; //copy失败
}
//判断剪贴版上的数据是否是制定的数据格式
if(IsClipboardFormatAvailable(CF_TEXT)||IsClipboardFormatAvailable(CF_OEMTEXT))
{
//从剪贴版上获取数据
HANDLE hClipboardData=GetClipboardData(CF_TEXT);
//通过给内存句柄加锁,获得指向指定格式数据的指针
char * pchData=(char *)GlobalLock(hClipboardData);
//本地变量获得数据
strClipBoard=pchData;
//给内存句柄解锁
GlobalUnlock(hClipboardData);
if(!m_Blank)
strData=LPCTSTR(strClipBoard);
//关闭剪贴版
CloseClipboard();
}
else
{
AfxMessageBox("剪贴版中无文本数据");
m_bcopy=FALSE; //copy失败
}
return m_bcopy;
}
3)添加消除空行的函数
void CSuperGetDlg::CutBlank()
{
//处理文本中的空行、空格
CStringArray arr; //定义CStringArray数组
CString strtemp;
TCHAR * pszBuf=NULL; //Tchar类型指针
pszBuf=(TCHAR *)LPCTSTR(strClipBoard); //pszBuf指向文本
char * p;
for (p=strtok(pszBuf,"\r\n");p!=NULL;p=strtok(NULL,"\r\n")) /*分解pszBuf字符串为一组标记串。pszBuf为要分解的字符串,\r\n为分隔符字符串。返回指向下一个标记串,当没有标记串时则返回空字符NULL。*/
{
arr.Add(p); //将得到的字符串添加到arr数组中
}
//删除空行
for (int i=0;i<arr.GetSize();i++)
{
strtemp=arr[i]; //将每一个字符串赋给strtemp
if(strtemp.IsEmpty()) //如果strtemp为空
{
arr.RemoveAt(i); //移除此项
i--; //i自减
continue;
}
//删除空格
int j=1;
while(j>0)
{
strtemp.TrimLeft(); //没有参数,从左删除字符空格
strtemp.TrimRight(); //没有参数,从右删除字符空格
j = strtemp.Replace(" ",""); //用无替换字符串中间的空格
}
strData+=strtemp+"\r\n"; //将无空行、空格的文本传给strData
}
}
4)将文本保存在指定位置
void CSuperGetDlg::File_Save()
{
CStdioFile File; //CStdioFile类型变量File
NameFile(m_Namenumber); //给文件命名
CString FileName=m_SavePlace+"//"+strName+".txt"; //FileName得到文件全路径
if (!File.Open(FileName,CFile::modeWrite|CFile::typeText)) //创建文本文件
{
if (!SetCurrentDirectory(m_SavePlace)) //检测是否有此目录
{
CreateDirectory(m_SavePlace, NULL); //如果没有则创建
}
if(!File.Open(FileName,CFile::modeCreate|CFile::modeWrite| CFile::typeText)) //如果不能打开打开
{
MessageBox(m_SavePlace+strName+".txt"+"不能被创建",
"信息提示",MB_OK); //显示错误提示
}
else
{
File.SeekToEnd(); //先定位到文件尾部
File.Write(strData,strData.GetLength()+1); //将内容写入文件中
File.Close(); //关闭文件
}
}
}
5)注册快捷键
LRESULT CSuperGetDlg::OnHotKey(WPARAM wp,LPARAM lp)
{
if(HIWORD(lp)==90&&LOWORD(lp)==MOD_ALT|MOD_CONTROL) //响应Ctrl+Alt+Z
{
ReleaseFocus(); //释放本程序焦点
PerFormCtrlC(); //模拟ctrl+c按键
UpdateData(TRUE); //更新数据
strData.Empty(); //清空strData
BOOL bCopy=GetCopy(); //拷贝剪贴板中的文本内容
if(m_Blank)
CutBlank(); //清除空行
if(bCopy)
{
if(!m_SavePlace.IsEmpty())
File_Save();
else
AfxMessageBox("请选择保存路径");
}
}
else if(HIWORD(lp)==88&&LOWORD(lp)==MOD_ALT) //响应Alt+X
{
ReNameFile(); //重命名文件名字
}
return 0;
}
6)激活当前程序
BOOL CSuperGetDlg::PreTranslateMessage(MSG* pMsg)
{
HWND wnd = ::GetForegroundWindow();
if(IsWindow(wnd))
{
//如果当前激活窗口不是本程序的窗口
if(wnd != this->m_hWnd)
{
//激活窗口发生了改变
if(gFocus != wnd)
{
if(IsWindow(gFocus))
{
//释放本进程和gFocus线程的联系
AttachThreadInput(
GetWindowThreadProcessId(m_hWnd,NULL),
GetWindowThreadProcessId(gFocus,NULL),
FALSE);
}
gFocus = wnd;
//使本进程和激活窗口的进程联系起来,接收本进程的按键消息
AttachThreadInput(
GetWindowThreadProcessId(m_hWnd,NULL),
GetWindowThreadProcessId(gFocus,NULL),
TRUE);
}
}
}
return CDialog::PreTranslateMessage(pMsg);
}
//释放本程序的窗口激活状态
void CSuperGetDlg::ReleaseFocus()
{
if(IsWindow(gFocus))
{
HWND wnd = ::GetForegroundWindow();
if(IsWindow(wnd))
{
if(wnd == gFocus)
{
return;
}
}
//设置保存的焦点窗口处于激活状态
::SetForegroundWindow(gFocus);
::SetFocus(gFocus);
}
}
由于篇幅所限,本程序的具体功能就不一一介绍了,有兴趣的朋友可以阅览本程序的源代码。本摘文快车(SuperGet)在VC++6.0,Windows XP环境下调试通过,编译并运行本程序,摘文快车的界面效果如图2 所示:
图2 程序界面效果
三、结语 本文详细的介绍了在VC++环境下,网页摘文中复制—〉粘贴—〉保存—〉重命名过程。读者在本程序的基础上可添加更多的功能,实现功能更加完善的摘文快车。
|