| 
				 摘 要  设计摘文快车(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++环境下,网页摘文中复制—〉粘贴—〉保存—〉重命名过程。读者在本程序的基础上可添加更多的功能,实现功能更加完善的摘文快车。			
				 |