Option Explicit
'接收消息的队列,要求模块级变量
Dim m_RevQueue As MSMQQueue
'接收事件接口
Dim WithEvents m_RevEvent As MSMQEvent
Private Sub Form_Load()
'创建消息队列
Dim QueueInfo As New MSMQQueueInfo
QueueInfo.PathName = ".\Private$\MyQueue"
QueueInfo.Label = "MyQueue"
'QueueInfo.Delete
QueueInfo.Create
'设置接收事件接口
Set m_RevEvent = New MSMQEvent
Set m_RevQueue = QueueInfo.Open(MQACCESS.MQ_RECEIVE_ACCESS, MQSHARE.MQ_DENY_NONE) '接收权限
m_RevQueue.EnableNotification m_RevEvent
End Sub
Private Sub cmdSend_Click()
Dim QueueInfo As New MSMQQueueInfo
QueueInfo.PathName = ".\Private$\MyQueue"
QueueInfo.Label = "MyQueue"
'打开队列,发送消息
Dim MsgQueue As MSMQQueue
Set MsgQueue = QueueInfo.Open(MQACCESS.MQ_SEND_ACCESS, MQSHARE.MQ_DENY_NONE) '发送权限
If (MsgQueue.IsOpen()) Then
Dim Msg As New MSMQMessage
Msg.Label = "MSMQ消息"
Msg.Body = "可以是任何变量,只要支持Idispatch接口和持续化接口!"
Msg.Send MsgQueue
MsgQueue.Close
End If
End Sub
Private Sub m_RevEvent_Arrived(ByVal Queue As Object, ByVal Cursor As Long)
'消息到来
Dim theQueue As MSMQQueue
Set theQueue = Queue
Dim Msg As MSMQMessage
Set Msg = theQueue.Receive() '得到消息
theQueue.EnableNotification m_RevEvent '接收下一个消息
MsgBox Msg.Body, vbInformation, Msg.Label
End Sub
posted @
2011-01-25 13:33 张志松 阅读(1753) |
评论 (0) |
编辑 收藏
头文件:
#pragma once
namespace VBScript_RegExp_55
{
class CMatch2 : protected COleDispatchDriver
{
friend class CMatchCollection2;
CMatch2(LPDISPATCH pDispatch);
public:
CString GetValue();
LONG GetFirstIndex();
LONG GetLength();
};
class CMatchCollection2 : protected COleDispatchDriver
{
friend class CRegExp2;
CMatchCollection2(LPDISPATCH pDispatch);
public:
CMatch2 GetItem(LONG index);
LONG GetCount();
};
// CRegExp2 包装类
class CRegExp2 : public COleDispatchDriver
{
public:
CRegExp2(); // 调用 COleDispatchDriver 默认构造函数
~CRegExp2();
BOOL CreateByReg();
private:
CRegExp2(const CRegExp2 &rhs);
CRegExp2 &operator=(const CRegExp2 &rhs);
// IRegExp2 方法
public:
CString GetPattern();
void SetPattern(LPCTSTR newValue);
BOOL IsIgnoreCase();
void SetIgnoreCase(BOOL newValue = TRUE);
BOOL IsGlobal();
void SetGlobal(BOOL newValue = TRUE);
BOOL IsMultiline();
void SetMultiline(BOOL newValue = TRUE);
CMatchCollection2 Execute(LPCTSTR sourceString);
BOOL Test(LPCTSTR sourceString);
CString Replace(LPCTSTR sourceString, LPCTSTR replaceString);
};
}
实现文件:
#include "stdafx.h"
#include "RegExp.h"
using namespace VBScript_RegExp_55;
//******************************************************************************
CMatch2::CMatch2(LPDISPATCH pDispatch)
: COleDispatchDriver(pDispatch)
{
}
CString CMatch2::GetValue()
{
CString result;
InvokeHelper(0x0, DISPATCH_PROPERTYGET, VT_BSTR, (void*)&result, NULL);
return result;
}
LONG CMatch2::GetFirstIndex()
{
LONG result;
InvokeHelper(0x2711, DISPATCH_PROPERTYGET, VT_I4, (void*)&result, NULL);
return result;
}
LONG CMatch2::GetLength()
{
LONG result;
InvokeHelper(0x2712, DISPATCH_PROPERTYGET, VT_I4, (void*)&result, NULL);
return result;
}
//******************************************************************************
CMatchCollection2::CMatchCollection2(LPDISPATCH pDispatch)
: COleDispatchDriver(pDispatch)
{
TRACE("CMatchCollection2::CMatchCollection2\r\n");
}
CMatch2 CMatchCollection2::GetItem(LONG index)
{
LPDISPATCH result = NULL;
static BYTE parms[] = VTS_I4 ;
InvokeHelper(0x0, DISPATCH_PROPERTYGET, VT_DISPATCH, (void*)&result, parms, index);
return CMatch2(result);
}
LONG CMatchCollection2::GetCount()
{
LONG result = 0;
InvokeHelper(0x1, DISPATCH_PROPERTYGET, VT_I4, (void*)&result, NULL);
return result;
}
//******************************************************************************
CRegExp2::CRegExp2()
{
}
CRegExp2::~CRegExp2()
{
ReleaseDispatch();
}
BOOL CRegExp2::CreateByReg()
{
return CreateDispatch(_T("VBScript.RegExp"));
}
CString CRegExp2::GetPattern()
{
CString result;
InvokeHelper(0x2711, DISPATCH_PROPERTYGET, VT_BSTR, (void*)&result, NULL);
return result;
}
void CRegExp2::SetPattern(LPCTSTR newValue)
{
static BYTE parms[] = VTS_BSTR ;
InvokeHelper(0x2711, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms, newValue);
}
BOOL CRegExp2::IsIgnoreCase()
{
BOOL result = FALSE;
InvokeHelper(0x2712, DISPATCH_PROPERTYGET, VT_BOOL, (void*)&result, NULL);
return result;
}
void CRegExp2::SetIgnoreCase(BOOL newValue)
{
static BYTE parms[] = VTS_BOOL ;
InvokeHelper(0x2712, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms, newValue);
}
BOOL CRegExp2::IsGlobal()
{
BOOL result = FALSE;
InvokeHelper(0x2713, DISPATCH_PROPERTYGET, VT_BOOL, (void*)&result, NULL);
return result;
}
void CRegExp2::SetGlobal(BOOL newValue)
{
static BYTE parms[] = VTS_BOOL ;
InvokeHelper(0x2713, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms, newValue);
}
BOOL CRegExp2::IsMultiline()
{
BOOL result = FALSE;
InvokeHelper(0x2717, DISPATCH_PROPERTYGET, VT_BOOL, (void*)&result, NULL);
return result;
}
void CRegExp2::SetMultiline(BOOL newValue)
{
static BYTE parms[] = VTS_BOOL ;
InvokeHelper(0x2717, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms, newValue);
}
CMatchCollection2 CRegExp2::Execute(LPCTSTR sourceString)
{
LPDISPATCH result = NULL;
static BYTE parms[] = VTS_BSTR ;
InvokeHelper(0x2714, DISPATCH_METHOD, VT_DISPATCH, (void*)&result, parms, sourceString);
return CMatchCollection2(result);
}
BOOL CRegExp2::Test(LPCTSTR sourceString)
{
BOOL result = FALSE;
static BYTE parms[] = VTS_BSTR ;
InvokeHelper(0x2715, DISPATCH_METHOD, VT_BOOL, (void*)&result, parms, sourceString);
return result;
}
CString CRegExp2::Replace(LPCTSTR sourceString, LPCTSTR replaceString)
{
CString result;
static BYTE parms[] = VTS_BSTR VTS_BSTR ;
InvokeHelper(0x2716, DISPATCH_METHOD, VT_BSTR, (void*)&result, parms, sourceString, replaceString);
return result;
}
具体使用:
记得 CoInitialize(NULL);
VBScript_RegExp_55::CRegExp2 RegExp;
RegExp.CreateByReg();
RegExp.SetPattern("((2[0-4]\\d|25[0-5]|[01]?\\d\\d?)\\.){3}(2[0-4]\\d|25[0-5]|[01]?\\d\\d?)");//IP地址
VBScript_RegExp_55::CMatchCollection2 myc = RegExp.Execute("sdffdgfd192.168.101.23w2r4tfghtyj");
AfxMessageBox(myc.GetItem(0).GetValue());
posted @
2011-01-09 14:04 张志松 阅读(727) |
评论 (0) |
编辑 收藏
头文件:
#pragma once
//事件回调接口,可以是接口也可以是类
//如果是接口就要在调用者类里面实现所有的事件
//有时我们只需要实现一两个事件,所以这里用类来实现事件回调接口
//把所有的事件都放在这个里面
class CWebBrowserEventHandler
{
protected:
friend class CWebBrowser; //让事件源可以调用事件回调函数
CWebBrowserEventHandler(){}; //保护构造函数,只能继承,不能实例化
//具体的事件回调函数
//第一个参数为事件源,只要是为了区分具体的事件源
virtual void WebBrowser_TitleChange(CWebBrowser& Sender, LPCTSTR lpszText){}
virtual void WebBrowser_DocumentComplete(CWebBrowser& Sender, LPCTSTR lpszURL){}
};
class CWebBrowser : public CHtmlView
{
DECLARE_DYNCREATE(CWebBrowser)
DECLARE_MESSAGE_MAP()
public:
CWebBrowser();
virtual ~CWebBrowser();
//设置或者取消事件回调接口
void SetEventHandler(CWebBrowserEventHandler* lpEventHandler = NULL);
BOOL IsContextMenuEnabled() const { return m_bContextMenuEnabled; }
void EnableContextMenu(BOOL newVal = TRUE) { m_bContextMenuEnabled = newVal; }
protected:
virtual void PostNcDestroy();
virtual BOOL PreTranslateMessage(MSG* pMsg);
afx_msg int OnMouseActivate(CWnd* pDesktopWnd, UINT nHitTest, UINT message);
afx_msg void OnDestroy();
protected:
//CHtmlView已经用虚函数实现事件的响应
//具体是如何实现事件的响应可以查看CHtmlView的源码
//作为例子,这里实现两个简单的事件
virtual void OnTitleChange(LPCTSTR lpszText);
virtual void OnDocumentComplete(LPCTSTR lpszURL);
protected:
BOOL m_bContextMenuEnabled;
//这里只有一个事件回调接口(其实可以用数组或链表来保存多个事件回调接口)
//但大都情况下一个事件回调接口就已经足够了
CWebBrowserEventHandler* m_lpEventHandler;
};
实现文件:
// WebBrowser.cpp : 实现文件
//
#include "stdafx.h"
#include ".\WebBrowser.h"
// CWebBrowser
IMPLEMENT_DYNCREATE(CWebBrowser, CHtmlView)
CWebBrowser::CWebBrowser()
: m_lpEventHandler(NULL)
, m_bContextMenuEnabled(TRUE)
{
}
CWebBrowser::~CWebBrowser()
{
}
BEGIN_MESSAGE_MAP(CWebBrowser, CHtmlView)
ON_WM_DESTROY()
ON_WM_MOUSEACTIVATE()
END_MESSAGE_MAP()
void CWebBrowser::SetEventHandler(CWebBrowserEventHandler* lpEventHandler /*= NULL*/)
{
m_lpEventHandler = lpEventHandler;
}
// CWebBrowser 消息处理程序
void CWebBrowser::OnTitleChange(LPCTSTR lpszText)
{
if (m_lpEventHandler != NULL)
{
m_lpEventHandler->WebBrowser_TitleChange(*this, lpszText);
}
CHtmlView::OnTitleChange(lpszText);
}
void CWebBrowser::OnDocumentComplete(LPCTSTR lpszURL)
{
if (m_lpEventHandler != NULL)
{
m_lpEventHandler->WebBrowser_DocumentComplete(*this, lpszURL);
}
CHtmlView::OnDocumentComplete(lpszURL);
}
void CWebBrowser::OnDestroy()
{
m_pBrowserApp.Release();
m_wndBrowser.DestroyWindow();
CWnd::OnDestroy();
}
int CWebBrowser::OnMouseActivate(CWnd* pDesktopWnd, UINT nHitTest, UINT message)
{
return CWnd::OnMouseActivate(pDesktopWnd, nHitTest, message);
}
void CWebBrowser::PostNcDestroy()
{
//防止自删除
//CHtmlView::PostNcDestroy();
}
BOOL CWebBrowser::PreTranslateMessage(MSG* pMsg)
{
if (WM_RBUTTONUP == pMsg->message || WM_CONTEXTMENU == pMsg->message)
{
if (!IsContextMenuEnabled()) //屏蔽右键菜单和键盘菜单键
{
return TRUE;
}
}
return CHtmlView::PreTranslateMessage(pMsg);
}
具体使用:
1.让调用者实现事件回调接口。
class CTestWebBrowserDlg : public CDialog, public CWebBrowserEventHandler
2.设置事件回调接口。
m_WebBrowser.SetEventHandler(this);
3.重写响应的事件回调函数。
void CTestWebBrowserDlg::WebBrowser_TitleChange(CWebBrowser& Sender, LPCTSTR lpszText)
{
SetWindowText(lpszText);
}
在VS2003+XP下测试通过。
posted @
2011-01-09 13:50 张志松 阅读(1196) |
评论 (0) |
编辑 收藏
Lzma(7-zip) 使用:
在C目录中有算法文件,进入Util\LzmaLib目录,编译生成LIB库,导出了以下两函数,LzmaCompress 为压缩函数,LzmaUncompress 为解压缩函数。
MY_STDAPI LzmaCompress(unsigned char *dest, size_t *destLen, const unsigned char *src, size_t srcLen,
unsigned char *outProps, size_t *outPropsSize,
int level,
unsigned dictSize,
int lc,
int lp,
int pb,
int fb,
int numThreads
);
MY_STDAPI LzmaUncompress(unsigned char *dest, size_t *destLen, const unsigned char *src, SizeT *srcLen,
const unsigned char *props, size_t propsSize);
导入Types.h 和 Lzmalib.h 到工程中。
代码如下:
#include "stdafx.h"
#include "LzmaLib.h"
#pragma comment(lib,"lzma.lib")
int _tmain(int argc, _TCHAR* argv[])
{
FILE* pFile = _tfopen(_T("file.dat"), _T("rb"));
if (pFile == NULL)
{
_ftprintf(stderr, _T("Error to Open the file!"));
return - 1;
}
fseek(pFile, 0, SEEK_END);
size_t srcLen = ftell(pFile);
rewind(pFile);
size_t destLen = srcLen * 2;
unsigned char* psrcRead = new unsigned char[srcLen]; //原始文件数据
unsigned char* pDecomress = new unsigned char[srcLen]; //存放解压缩数据
unsigned char* pLzma = new unsigned char[destLen]; //存放压缩数据
fread(psrcRead, sizeof(char), srcLen, pFile);
unsigned char prop[5] =
{
0
};
size_t sizeProp = 5;
if (SZ_OK != LzmaCompress(pLzma, &destLen, psrcRead, srcLen, prop,
&sizeProp, 9, (1 << 24), 3, 0, 2, 32, 2))
{
//出错了
_ftprintf(stderr, _T("压缩时出错!"));
delete [] psrcRead;
delete [] pDecomress;
delete [] pLzma;
fclose(pFile);
return - 1;
}
FILE* pCompressFile = _tfopen(_T("compress.dat"), _T("wb"));
//写入压缩后的数据
if (pCompressFile == NULL)
{
_ftprintf(stderr, _T("创建文件出错!"));
delete [] psrcRead;
delete [] pDecomress;
delete [] pLzma;
fclose(pFile);
return - 1;
}
fwrite(pLzma, sizeof(char), destLen, pCompressFile);
fclose(pCompressFile);
FILE* pDecompressFile = _tfopen(_T("decompress.dat"), _T("wb"));
//写入解压缩数据
if (pDecompressFile == NULL)
{
_ftprintf(stderr, _T("写入数据出错!"));
delete [] psrcRead;
delete [] pDecomress;
delete [] pLzma;
fclose(pFile);
return - 1;
}
//注意:解压缩时props参数要使用压缩时生成的outProps,这样才能正常解压缩
if (SZ_OK != LzmaUncompress(pDecomress, &srcLen, pLzma, &destLen, prop, 5))
{
delete [] psrcRead;
delete [] pDecomress;
delete [] pLzma;
fclose(pDecompressFile);
fclose(pFile);
return - 1;
}
fwrite(pDecomress, sizeof(char), srcLen, pDecompressFile);
delete [] psrcRead;
delete [] pDecomress;
delete [] pLzma;
fclose(pDecompressFile);
fclose(pFile);
return 0;
}
zlib使用:
zlib 是通用的压缩库,提供了一套 in-memory 压缩和解压函数,并能检测解压出来的数据的完整性(integrity)。下面介绍两个最有用的函数——compress 和 uncompress。
int compress(Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen);
compress函数将 source 缓冲区中的内容压缩到 dest 缓冲区。 sourceLen 表示source 缓冲区的大小(以字节计)。注意函数的第二个参数 destLen 是传址调用。当调用函数时,destLen表示 dest 缓冲区的大小,destLen > (sourceLen + 12)*100.1%。当函数退出后,destLen 表示压缩后缓冲区的实际大小。此时 destLen / sourceLen 正好是压缩率。
compress 若成功,则返回 Z_OK;若没有足够内存,则返回 Z_MEM_ERROR;若输出缓冲区不够大,则返回 Z_BUF_ERROR。
int uncompress(Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen);
uncompress 函数将 source 缓冲区的内容解压缩到 dest 缓冲区。sourceLen 是 source 缓冲区的大小(以字节计)。注意函数的第二个参数 destLen 是传址调用。当调用函数时,destLen 表示 dest 缓冲区的大小, dest 缓冲区要足以容下解压后的数据。在进行解压缩时,需要提前知道被压缩的数据解压出来会有多大。这就要求在进行压缩之前,保存原始数据的大小(也就是解压后的数据的大小)。这不是 zlib 函数库的功能,需要我们做额外的工作。当函数退出后, destLen 是解压出来的数据的实际大小。
uncompress 若成功,则返回 Z_OK ;若没有足够内存,则返回 Z_MEM_ERROR;若输出缓冲区不够大,则返回 Z_BUF_ERROR。若输入数据有误,则返回 Z_DATA_ERROR。
代码如下:
#include "stdafx.h"
#include <cstring>
#include <cstdlib>
#include <iostream>
#include "zlib.h"
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
int err = 0;
Byte compr[200] = {0}, uncompr[200] = {0}; // big enough
uLong comprLen = 0, uncomprLen = 0;
const char* hello = "12345678901234567890123456789012345678901234567890";
uLong len = strlen(hello) + 1;
comprLen = sizeof(compr) / sizeof(compr[0]);
err = compress(compr, &comprLen, (const Bytef*)hello, len);
if (err != Z_OK)
{
cerr << "compess error: " << err << '\n';
exit(1);
}
cout << "orignal size: " << len
<< " , compressed size : " << comprLen << '\n';
strcpy((char*)uncompr, "garbage");
err = uncompress(uncompr, &uncomprLen, compr, comprLen);
if (err != Z_OK)
{
cerr << "uncompess error: " << err << '\n';
exit(1);
}
cout << "orignal size: " << len
<< " , uncompressed size : " << uncomprLen << '\n';
if (strcmp((char*)uncompr, hello))
{
cerr << "BAD uncompress!!!\n";
exit(1);
}
else
{
cout << "uncompress() succeed: \n" << (char*)uncompr;
}
}
posted @
2011-01-02 15:12 张志松 阅读(7479) |
评论 (1) |
编辑 收藏
BOOL PutTextToClipboard(LPCTSTR pTxtData)
{
BOOL bRet = FALSE;
if (OpenClipboard(AfxGetMainWnd()->GetSafeHwnd()))
{
EmptyClipboard();
HGLOBAL hData = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, (lstrlen(pTxtData) + 1) * sizeof(TCHAR));
if (hData != NULL)
{
LPTSTR pszData = (LPTSTR)::GlobalLock(hData);
lstrcpy(pszData, pTxtData);
GlobalUnlock(hData);
#ifdef _UNICODE
bRet = (SetClipboardData(CF_UNICODETEXT, hData) != NULL);
#else
bRet = (SetClipboardData(CF_TEXT, hData) != NULL);
#endif // _UNICODE
}
CloseClipboard();
}
return bRet;
}
posted @
2010-12-28 13:02 张志松 阅读(734) |
评论 (0) |
编辑 收藏
VS2003
头文件
#pragma once
#include <afxhtml.h>
class CWebBrowser : public CHtmlView
{
DECLARE_DYNCREATE(CWebBrowser)
DECLARE_MESSAGE_MAP()
public:
CWebBrowser();
virtual ~CWebBrowser();
BOOL IsContextMenuEnabled() const { return m_bContextMenuEnabled; }
void EnableContextMenu(BOOL newVal = TRUE) { m_bContextMenuEnabled = newVal; }
protected:
virtual void PostNcDestroy();
virtual BOOL PreTranslateMessage(MSG* pMsg);
afx_msg int OnMouseActivate(CWnd* pDesktopWnd, UINT nHitTest, UINT message);
afx_msg void OnDestroy();
protected:
virtual void OnTitleChange(LPCTSTR lpszText);
virtual void OnDocumentComplete(LPCTSTR lpszURL);
protected:
BOOL m_bContextMenuEnabled;
};
实现文件
#include "stdafx.h"
#include ".\WebBrowser.h"
// CWebBrowser
IMPLEMENT_DYNCREATE(CWebBrowser, CHtmlView)
CWebBrowser::CWebBrowser()
: m_bContextMenuEnabled(TRUE)
{
}
CWebBrowser::~CWebBrowser()
{
}
BEGIN_MESSAGE_MAP(CWebBrowser, CHtmlView)
ON_WM_DESTROY()
ON_WM_MOUSEACTIVATE()
END_MESSAGE_MAP()
// CWebBrowser 消息处理程序
void CWebBrowser::OnTitleChange(LPCTSTR lpszText)
{
// TODO: 在此添加专用代码和/或调用基类
CHtmlView::OnTitleChange(lpszText);
}
void CWebBrowser::OnDocumentComplete(LPCTSTR lpszURL)
{
// TODO: 在此添加专用代码和/或调用基类
CHtmlView::OnDocumentComplete(lpszURL);
}
void CWebBrowser::OnDestroy()
{
m_pBrowserApp.Release();
m_wndBrowser.DestroyWindow();
CWnd::OnDestroy();
}
int CWebBrowser::OnMouseActivate(CWnd* pDesktopWnd, UINT nHitTest, UINT message)
{
return CWnd::OnMouseActivate(pDesktopWnd, nHitTest, message);
}
void CWebBrowser::PostNcDestroy()
{
//防止自删除
//CHtmlView::PostNcDestroy();
}
BOOL CWebBrowser::PreTranslateMessage(MSG* pMsg)
{
if (WM_RBUTTONUP == pMsg->message || WM_CONTEXTMENU == pMsg->message)
{
if (!IsContextMenuEnabled()) //屏蔽右键菜单和键盘菜单键
{
return TRUE;
}
}
return CHtmlView::PreTranslateMessage(pMsg);
}
posted @
2010-12-28 12:59 张志松 阅读(2929) |
评论 (0) |
编辑 收藏
CWnd::GetOwner 这个函数获得窗口的拥有者的指针。如果窗口没有拥有者,则缺省地返回父窗口对象的指针。注意在拥有者和被拥有者之间的关系与父子关系在几个重要方面的差别。例如,具有父窗口的窗口被限制在父窗口的客户区内,但是被拥有的窗口可以被画在桌面上的任何位置。 CWnd::GetParent 如果这个成员函数执行成功,则返回父窗口指针;否则返回值为NULL,表明发生了错误或没有父窗口。调用这个函数以获得子窗口的父窗口(如果有)的指针。GetParent函数返回直接父窗口的指针。 要知道一个窗口有一个父窗口(他是父窗口的child),就是用GetParent得到,一个child窗口只能在父窗口的客户区移动。 而对于对话框来说,他的父窗口永远是最顶层的窗口,但是可以用GetOwner得到他的逻辑意义上的“父窗口”(因为对话框可以在屏幕中到处移动,而child不是的。)
posted @
2010-12-24 10:50 张志松 阅读(3661) |
评论 (0) |
编辑 收藏
以 MSScriptControl.ScriptControl.1 为例
CScriptControl是MSScriptControl.ScriptControl.1是MFC包装类,并做了一点改动。
CScriptControl* m_lpScriptControl;
1.定义类的接口映视。
DECLARE_INTERFACE_MAP()
BEGIN_INTERFACE_MAP(CMyDlg, CDialog)
INTERFACE_PART(CMyDlg, DIID_DScriptControlSource, Dispatch)
END_INTERFACE_MAP()
2. 关联事件到自定义函数。
每个事件的名称,DISPID,参数都是不一样的。
DECLARE_DISPATCH_MAP()
BEGIN_DISPATCH_MAP(CMyDlg, CDialog)
DISP_FUNCTION_ID(CMyDlg, "Error", 0xBB8, OnError, VT_EMPTY, VTS_NONE)
END_DISPATCH_MAP()
3.在OnInitDialog()中创建ScriptControl实例并连接。
EnableAutomation();
m_lpScriptControl = new CScriptControl;
m_lpScriptControl->CreateByReg();
DWORD dwCookie = 0;
LPUNKNOWN pUnkSink = GetIDispatch(FALSE);
AfxConnectionAdvise(m_lpScriptControl->m_lpDispatch, DIID_DScriptControlSource, pUnkSink, FALSE, &dwCookie);
4.测试一下,调用m_lpScriptControl执行一段错误的脚本。
比如:m_lpScriptControl->ExecuteStatement("msgbox1 1")
看看OnError被执行了没有?
这种方法只对继承IDispatch的事件源有效,对继承IUnknow的事件源无效,和VBS一样!
posted @
2010-12-11 15:10 张志松 阅读(1230) |
评论 (0) |
编辑 收藏
如果您正在从 C 或 C++ 客户端调用该方法,则需要做更多工作才能打包调用。 如果您正在从 MFC 客户端应用程序调用该函数,并且使用了 ClassWizard 来为包含 MyFunc1 的自动功能对象生成参数包装类,那么,ClassWizard 将不会对 MyFunc1 或其它任何采用可变长参数列表的函数生成一个 wrapper (包装) 函数。 这是因为 MFC 实现 ColeDispatchDriver 时, 它并不知道如何对 SAFEARRAY 类型进行打包。这不是 Bug,而只是 MFC 的局限。 因此,如果使用 ClassWizard 来生成参数包装类用于自动对象,该自动对象包含带有变长参数列表的方法,那么,您必须编写参数包装程序才能调用该函数。
下面的 Visual C++ 函数显示了如何调用 MyFunc1 自动功能方法:
CString _Class1::InvokeMyFunc1(long p1,VARIANT *pVar,int cElems)
{
//pVar is an array of variants.
//cElems is the number of variants in pVar.
//p1 is a required long parameter.
HRESULT hr;
VARIANT returnval;
EXCEPINFO Excepinfo;
unsigned int uArgErr;
DISPPARAMS dp;
VariantInit(&returnval);
//Create the rgvarg member of the DISPPARAMS struct.
//Make it big enough to hold the number of VARIANTS in the
//pVar array + an extra variant to hold the required parameter.
dp.rgvarg = new VARIANTARG[cElems+1];
//Because the variable length parameter list is the last argument
//to the function, it gets copied to dp.rgvarg first.
memcpy(dp.rgvarg,pVar,sizeof(VARIANT)*cElems);
//Add the required parameter (p1) to the array.
dp.rgvarg[cElems].vt = VT_I4;
dp.rgvarg[cElems].lVal = p1;
//Set cArgs to the total number of arguments passed.
dp.cArgs = cElems+1;
dp.cNamedArgs = 0;
//Make the call.
hr = m_lpDispatch->Invoke(0x6003001C,
IID_NULL,
LOCALE_SYSTEM_DEFAULT,
DISPATCH_METHOD,
&dp,
&returnval,
&Excepinfo,&uArgErr);
//Delete the memory you allocated above for dp.rgvarg.
delete[] dp.rgvarg;
//Return the string as a Cstring.
CString strRet(returnval.bstrVal);
VariantClear(&returnval);
return strRet;
}
尽管 MyFunc1 函数的类型信息指定要将 SAFEARRAY* 传入,但调用者没有创建 SAFEARRAY 并将其传递给调用。 调用者在 DISPARAMS 结构中传递变量数组以及一个必需参数和全部参数的总数。 在服务器中实现该调用时,将创建 SAFEARRAY,并将传入的变量数组打包到 SAFEARRAY 中,然后将 SAFEARRAY 的指针传递给服务器的方法。 这样,创建 SAFEARRAY 以便传递 MyFunc1 的责任不再由调用者承担。 调用者需要将它希望传递的全部额外参数打包到一个简单数组中(该数组包含在 DISPARAMS 结构中),然后调用该方法。
还可以参考MFC源码:COleDispatchDriver::InvokeHelper和COleDispatchDriver::InvokeHelperV。
posted @
2010-12-11 14:34 张志松 阅读(435) |
评论 (0) |
编辑 收藏
今天用VC2003编译zlib-1.2.5,由于zlib-1.2.5不再提供VC2003的工程文件,所以直接用VC2003打开VC6的zlib.dsp后进行编译。
在工程属性的预处理器中加入ZLIB_WINAPI,居然不生效?但是直接在头文件中加入ZLIB_WINAPI定义就可以。一时觉得很奇怪。
后来用记事本打开转换过来zlib.vcproj才发现,原来是每个C文件都单独设置了预处理器而且不继承工程的设置,从而导致之前设置的预处理器无效。
posted @
2010-12-04 14:25 张志松 阅读(281) |
评论 (0) |
编辑 收藏