jiangsheng

http://www.csdn.net/develop/author/netauthor/jiangsheng/
随笔 - 142, 评论 - 629, 引用 - 27

导航

关于

 
这下要维护3个BLOG了,faint 其他的地址:

所有的文章版权归原文作者所有,任何人需要转载文章,必须征得原文作者授权。
我的MVP配置

标签

每月存档

最新留言

广告

集成桌面搜索,模拟器

微软的桌面搜索API推出也有一段时间了,但是网上可以找到的相关技术资料还不多。官方的资料在http://addins.msn.com/devguide.aspx可以看到,而且网页上有SDK和一个C#的示例供下载。
使用搜索API非常的简单,首先创建一个桌面搜索对象
BOOL CWDSSampleView::PreCreateWindow(CREATESTRUCT& cs)
{
 // TODO: Modify the Window class or styles here by modifying
 //  the CREATESTRUCT cs
 if(m_pSearchDesktop.CreateInstance(CLSID_SearchDesktop))
 {
  AfxMessageBox(IDS_FAILED_TO_CREATE_SEARCH_ENGINE);
  return FALSE;
 }

……
之后就可以开始执行搜索了。桌面搜索对象有两个方法,ExecuteSQLQuery和ExecuteQuery,都返回一个ADO记录集对象。ExecuteQuery是对用户比较友好的版本,参数虽然比较多,但是不需要自己构建SQL;而ExecuteSQLQuery是底层版本,只有一个参数——需要自己构造的SQL。相信我,你不会渴望自己来创建SQL的。传递给ExecuteQuery的参数就已经够长的了。字符串表中IDS_COLUMNS_GENERAL的内容是:
DocTitle,DocFormat,Url,DocAuthor,PrimaryDate,FileName, FileExt,IsAttachment,Characterization,Rank,PerceivedType, HasAttach,DocTitlePrefix,FileExtDesc,DisplayFolder, DocKeywords,DocComments,ConversationID,Size, Create,Write。

void CWDSSampleView::Search(LPCTSTR lpszQuery,LPCTSTR lpszSort)
{
 CString strQuery(lpszQuery);if(strQuery.IsEmpty())return;
 CString strSort(lpszSort);
 USES_CONVERSION;
 HRESULT hr=S_OK;
 GetListCtrl().SetItemCount(0);
 ClearCache();
 try{
  CString strColumns;
  VERIFY(strColumns.LoadString(IDS_COLUMNS_GENERAL));
  if(strSort.IsEmpty())
   m_pRecordset=m_pSearchDesktop->ExecuteQuery(T2OLE(strQuery),
    T2OLE(strColumns),NULL,NULL);
  else
   m_pRecordset=m_pSearchDesktop->ExecuteQuery(T2OLE(strQuery),
    T2OLE(strColumns),T2OLE(strSort),NULL);
  int nItemCount=m_pRecordset->GetRecordCount();
  GetListCtrl().SetItemCount(nItemCount);
  
 }
 catch(_com_error&e)
 {
  ……
 }
}

Windows Desktop Search Example(VC/MFC)
但是,访问返回的记录集的速度比访问数据库要慢。我不得不用虚列表和缓存来提高性能。在搜索结果很多(例如关键字选择"Microsoft")时程序有假死现象——当然也不排除我选择的字段过多的原因。

最近在写一个14位CPU的模拟器,CPU指令长度是固定的——13字节,十分的不吉利^_^b,而且CPU指令集中一些特定指令会根据上下文判断是否跳过下一个指令。但是在Intel系统上没有这样的指令,而且指令长度是可变的,所以无法知道下一个指令的长度来跳过它。我现在是在内存中设置一个标志,在执行每个指令之前检查这个标志来判断前一个指令是否指明跳过当前指令——低效,但是可以正常工作。

现在我知道一些模拟器为什么慢得像乌龟爬了……

posted on 2005-07-19 01:58:00 by jiangsheng  评论(3) 阅读(4386)

在使用浏览器控件的程序中判断HTTP错误

在自动化浏览器控件提交表单之后,浏览器控件可能会在浏览超时时重定向到一个错误页面。有时需要用代码控制页面返回之后重新提交表单。

IE6.0之前的版本浏览器控件没有获得HTTP状态代码的接口。一个很依赖于网站设置的方法是,捕获TitleChange事件,在页面标题包含"找不到页面"或者"Page Not Found"之类的字符串时,认为浏览失败。使用这种方法基本只对特定语言的网站有效,也可能受在浏览时使用的代理服务器影响而造成判断不准确。另一个方法是假定短时间内两次连接的结果相同,通过捕获浏览器的BeforeNavigate2事件,在事件处理代码中用winhttp api单独和服务器连接来测试服务器的回应。连接之后可以使用HttpQueryInfo来查询信息,相应参数是HTTP_QUERY_STATUS_CODE。在这之前,可能要在打开URL时用INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTP | INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTPS标志来防止服务器的重定向。这种方法会造成每个页面被下载两次,一次由手动测试连接代码发起,一次由浏览器控件发起。根据网络和服务器的状况,两次下载也可能有不同的结果,所以这种方法也未必准确。

IE6.0版本的浏览器控件可以触发DWebBrowserEvents2::NavigateError事件来通知浏览错误及提供错误代码。但是,这个事件只在使用代码触发了浏览错误之后触发一次。在用户点击链接触发浏览错误时不会触发这个事件。

HTML文档对象不支持使用IBindStatusCallback接口自定义URL Moniker绑定过程,因此获得IWinInetHttpInfo接口之后查询信息的方法不能用。InternetGetLastResponseInfo在浏览失败时可能仍然成功,因为服务器可能自定义访问错误的页面。

参考

http://www.microsoft.com/mind/0796/protocol/protocol.asp

DWebBrowserEvents2::NavigateError

http://www.microsoft.com/mind/0396/sweeper/sweeper.asp

http://www.microsoft.com/mind/1096/activex/activex.asp

http://msdn.microsoft.com/workshop/networking/moniker/overview/overview.asp

posted on 2005-04-08 21:58:00 by jiangsheng  评论(0) 阅读(4651)

覆盖剪贴板的数据

由于BSTR经常会当OLESTR用,有时候就把它们的区别搞忘记了

今天查一个Debug通过Release崩溃的问题查了半天,最后发现是把OLESTR当BSTR用了

 CComPtr pRecvDocument;
 if(!m_wndRecv.GetDHtmlDocument(&pRecvDocument))return;
 if(pRecvDocument==NULL)return;

//pRecvDocument->createElement(L"p",&pNewElement);这行出错
  pRecvDocument->createElement(CComBSTR("p"),&pNewElement);//这行通过
以后要当心。

P.S.按理说Debug和Release方式下IHTMLDocument2的createElement行为应该相同才是,但是事实是不同……

posted on 2004-03-18 18:50:00 by jiangsheng  评论(0) 阅读(2594)

加速浏览器控件的创建

我们知道,应用程序中浏览器控件的第一个实例的创建过程比其他的实例创建过程慢得多。为了加速浏览器控件的创建,在应用程序的开始,可以创建一个隐藏的浏览器对象,使得应用程序中随时都至少有一个浏览器控件的实例

在主窗口类中声明 CComPtr<IOleObject> m_spOleObjectPreloadBrowser;
在主窗口类的初始化函数中

 HRESULT hr = CoCreateInstance(CLSID_WebBrowser, NULL, CLSCTX_INPROC,
        IID_IOleObject, (void**)&m_spOleObjectPreloadBrowser);
 if (FAILED(hr)){
  TRACE(_T("Can not create WebBrowser\r\n"));
  return FALSE;
 }
 CComQIPtr<IWebBrowser2> pWebBrowser(m_spOleObjectPreloadBrowser);
 if(pWebBrowser){
  CComBSTR bstrURL = _T("about:blank");
  COleSafeArray vPostData;
  pWebBrowser->Navigate(bstrURL,
   COleVariant((long) 0, VT_I4),
   COleVariant(_T(""), VT_BSTR),
   vPostData,
   COleVariant(_T(""), VT_BSTR));
 }
然后在退出时释放

 m_spOleObjectPreloadBrowser=NULL;

这样可以大大加快程序中浏览器控件的创建速度。因为IE的动态库都是共享的,所以除了第一个示例之外,多开一个实例多占用的内存并不大。

QQ的广告窗口明显就没有用这个方法来加速……打开的时候慢得要死……

posted on 2004-02-27 18:29:00 by jiangsheng  评论(8) 阅读(4122)

写篇文章真累

http://www.csdn.net/develop/read_article.asp?id=21702

最近这篇文章长长短短,写了两个礼拜吧。
写这篇文章的主要原因是想把网页分析做得更加灵活。这篇文章的基础是我以前为一个EBS游戏写的外挂,可以自动修改网页内容(主要是表单)和定时submit表单(有的网站的submit有时间限制)。以前的代码是用VC来写的,和网页的修改同步很不方便。很多功能,例如表单的自动填写和递交依赖于表单的结构,网页结构一变的话,就需要重新编译代码。所以这次重写的时候(那个EBS又改版了),想考虑做成类似于Outlook的邮件规则。但是在编写的时候,发现这样的规则编写起来实在是太繁琐了。其实这些规则用VB来写脚本的话,可能就几句话,例如判断浏览完成之后判断URL,自动填写和递交表单。

这是我使用VBS的原因。在程序中集成脚本解释器之后,网站改版的时候改脚本就可以了,虽然使用门槛要高些(要会编写脚本)。

主要碰见的技术问题是
脚本中的浏览器的事件处理代码不能执行(CHtmlView捕获了事件,所以要在CHtmlView里面转发事件)
移植MFCIE的代码到MDI的时候的菜单出现很多问题,主要是MDI的菜单替换,以及插入MDI系统菜单之后收藏夹的位置变化

移植部分MFC7的代码到MFC6,中间还结合了一大堆修复MFC6BUG的代码,真是faint
无法直接创建支持事件的CCmdTaget类(ActiveX好像可以……)
MFC的类向导不支持自动化中的默认参数
上面两个问题使得我不得不手动改ODL文件,结果造成无数问题……ODL还是能不改就不改吧
关闭窗口时出现非法操作(最后捕获了WindowClosing事件,Cancel掉了系统的处理之后自己关闭)
调用IE的表单的自动完成的时候,没做成功。好像和隐藏方法IShellUIHelper::AutoCompleteAttatch有关。
编辑网页源代码时文档结构的刷新有问题,被编辑的节点的Child集合在SetOutHTML之后长度变成0了,最后是刷新整个文档结构树才解决。IE的BUG?

posted on 2003-10-23 20:00:00 by jiangsheng  评论(4) 阅读(5316)

Powered by: Joycode.MVC引擎 0.5.2.0