学习ATL的一个习作 : )

原创 2002年12月02日 09:26:00

#include "stdafx.h"

template<typename ObjectType>
class Delegate
{
// Type Definitions
public:
 typedef LRESULT (ObjectType::*CallType)(HWND, UINT, WPARAM, LPARAM);

// Constructor
public:
 Delegate(ObjectType* pObject, CallType pCallee) : m_pObject(pObject), m_pCallee(pCallee)
 {
 }

// Destrcutor
public:
 ~Delegate()
 {
 }

// Thunk Structure
public:
 /* Adjust pack size */
 #pragma pack(push,1)
 struct Thunk
 {
  /* push ebp */
  BYTE m_pushebp;
  /* mov ebp, esp */
  BYTE m_movebp;
  BYTE m_esp;

  /* mov eax, dword ptr [ebp + 8] */
  BYTE m_moveax1;
  BYTE m_ebpplus1;
  BYTE m_offset1;
  
  /* push eax */
  BYTE m_pusheax1;

  /* mov eax, dword ptr [ebp + 12] */
  BYTE m_moveax2;
  BYTE m_ebpplus2;
  BYTE m_offset2;
  
  /* push eax */
  BYTE m_pusheax2;

  /* mov eax, dword ptr [ebp + 16] */
  BYTE m_moveax3;
  BYTE m_ebpplus3;
  BYTE m_offset3;
  
  /* push eax */
  BYTE m_pusheax3;

  /* mov eax, dword ptr [ebp + 20] */
  BYTE m_moveax4;
  BYTE m_ebpplus4;
  BYTE m_offset4;
  
  /* push eax */
  BYTE m_pusheax4;

  /* mov eax, this*/
  BYTE m_moveax5;
  void* m_this;

  /* push eax */
  BYTE m_pusheax5;

  /* mov eax, helper*/
  BYTE m_moveax6;
  void* m_helper;

  /* call eax */
  BYTE m_call;
  BYTE m_calleax;

  /* pop ebp */
  BYTE m_popebp;
  /* ret 10h */
   BYTE m_ret;
  DWORD m_10h;
 };
 /* Reset pack size */
 #pragma pack(pop)

// Properties
protected:
 Thunk  m_Thunk;
 ObjectType* m_pObject;
 CallType m_pCallee;

// Methods
public:
 operator WNDPROC(void)
 {
  void*  pf;

  __asm
  {
   mov  eax, Delegate<ObjectType>::Helper
   mov  pf, eax
  }

  /* push ebp */
  m_Thunk.m_pushebp = 0x55;
  
  /* mov ebp, esp */
  m_Thunk.m_movebp = 0x8B;
  m_Thunk.m_esp  = 0xEC;
  
  /* mov eax dword ptr [ebp + 20] */
  m_Thunk.m_moveax1 = 0x8B;
  m_Thunk.m_ebpplus1 = 0x45;
  m_Thunk.m_offset1 = 20;

  /* push eax */
  m_Thunk.m_pusheax1 = 0x50;

  /* mov eax dword ptr [ebp + 16] */
  m_Thunk.m_moveax2 = 0x8B;
  m_Thunk.m_ebpplus2 = 0x45;
  m_Thunk.m_offset2 = 16;

  /* push eax */
  m_Thunk.m_pusheax2 = 0x50;

  /* mov eax dword ptr [ebp + 12] */
  m_Thunk.m_moveax3 = 0x8B;
  m_Thunk.m_ebpplus3 = 0x45;
  m_Thunk.m_offset3 = 12;

  /* push eax */
  m_Thunk.m_pusheax3 = 0x50;

  /* mov eax dword ptr [ebp + 8] */
  m_Thunk.m_moveax4 = 0x8B;
  m_Thunk.m_ebpplus4 = 0x45;
  m_Thunk.m_offset4 = 8;

  /* push eax */
  m_Thunk.m_pusheax4 = 0x50;

  /* mov eax, this */
  m_Thunk.m_moveax5 = 0xB8;
  m_Thunk.m_this  = this;

  /* push eax */
  m_Thunk.m_pusheax5 = 0x50;

  /* mov eax, Delegate::Helper */
  m_Thunk.m_moveax6 = 0xB8;
  m_Thunk.m_helper = pf;
  
  /*call eax*/
  m_Thunk.m_call  = 0xFF;
  m_Thunk.m_calleax = 0xD0;

  /* pop ebp */
  m_Thunk.m_popebp = 0x5D;
  
  /* ret 10h */
  m_Thunk.m_ret  = 0xC2;
  m_Thunk.m_10h  = 0x10;

  return (LRESULT(CALLBACK*)(HWND, UINT, WPARAM, LPARAM))&m_Thunk;
 }

 HRESULT CALLBACK Helper(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
 {
  return (m_pObject->*m_pCallee)(hWnd, uMessage, wParam, lParam);
 }
};

class CWindow
{
public:
 virtual LRESULT WndProc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
 {
  if(uMessage==WM_DESTROY)
  {
   ::PostQuitMessage(0);
  }

  return ::DefWindowProc(hWnd, uMessage, wParam, lParam);
 }
};

class CMyWindow : public CWindow
{
public:
 virtual LRESULT WndProc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
 {
  if(uMessage==WM_LBUTTONDOWN)
  {
   ::MessageBox(hWnd, "ok", "ok", MB_OK);
  }

  return CWindow::WndProc(hWnd, uMessage, wParam, lParam);
 }
};

int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
 CMyWindow theWindow;

 CWindow* pWindow = &theWindow;

 Delegate<CWindow> theDelegate(pWindow, CWindow::WndProc);

 WNDCLASSEX wcex;

 wcex.cbSize   = sizeof(WNDCLASSEX);
 wcex.cbClsExtra  = 0;
 wcex.cbWndExtra  = 0;
 wcex.hbrBackground = (HBRUSH)::GetStockObject(WHITE_BRUSH);
 wcex.hCursor  = ::LoadCursor(NULL, IDC_ARROW);
 wcex.hIcon   = ::LoadIcon(NULL, IDI_APPLICATION);
 wcex.hIconSm  = wcex.hIcon;
 wcex.hInstance  = ::GetModuleHandle(NULL);

 // Replaced with a member function delegation
 wcex.lpfnWndProc = theDelegate;

 wcex.lpszClassName = "TestClass";
 wcex.lpszMenuName = NULL;
 wcex.style   = CS_VREDRAW | CS_HREDRAW;

 ::RegisterClassEx(&wcex);


 HWND hWnd = ::CreateWindow("TestClass",
          "TestWindow",
          WS_OVERLAPPEDWINDOW | WS_VISIBLE,
          0, 0,
          320, 240,
          NULL, NULL,
          ::GetModuleHandle(NULL), NULL);

 ::UpdateWindow(hWnd);


 MSG msg;

 while(::GetMessage(&msg, NULL, 0, 0))
 {
  ::TranslateMessage(&msg);
  ::DispatchMessage(&msg);
 }

 ::ExitProcess(0);
}

VC++ ATL 学习总结

ATL (一种微软程序库) ATL,Active Template Library活动模板库,是一种微软程序库,支持利用C++语言编写ASP代码以及其它ActiveX程序。通过活动模板 库,可以建...
  • bcbobo21cn
  • bcbobo21cn
  • 2017年04月04日 10:09
  • 628

ATL入门:利用ATL编写简单的COM组件

序论       第一步:运行ATL COM Wizard         运行Visual C++ 并创建一个新的工程,选择“ATL COM AppWizard”,项目名称为”Simple_ATL”...
  • zhwang_1999
  • zhwang_1999
  • 2008年03月26日 23:35
  • 5801

使用ATL创建简单ActiveX控件(一) —— 创建ATL项目

创建过程以VS2010为例,分三篇(创建ATL项目、添加方法/属性和枚举、添加连接点)演示。本篇演示创建ATL项目。...
  • mrxyz098
  • mrxyz098
  • 2015年09月17日 22:37
  • 2543

VS2013编写嵌入网页的ATL控件2-给ATL控件添加鼠标响应

给ATL控件添加鼠标控件。和MFC添加鼠标控件基本相同,就是VS的向导把信息映射的位置添加错误了。需要手动改回来。其他都相同。 下面记录了入门的具体步骤。 “以管理员身份运行”VS2013,再打开项...
  • jean7155
  • jean7155
  • 2015年12月15日 18:01
  • 1089

使用ATL创建简单ActiveX控件(二) —— 添加方法/属性和枚举

创建过程以VS2010为例,分三篇(创建ATL项目、添加方法/属性和枚举、添加连接点)演示。本篇演示添加方法以及枚举,添加的属性的步骤和添加方法类同,不再演示。...
  • mrxyz098
  • mrxyz098
  • 2015年09月19日 19:00
  • 2250

C++ STL,ATL,WTL之间的联系和区别

STL即 Standard Template Library (标准模板库) STL是惠普实验室开发的一系列软件的统称。它是由Alexander Stepanov、Meng Lee和Davi...
  • xdrt81y
  • xdrt81y
  • 2013年12月05日 16:09
  • 11417

ATL编程初级教程(图文事例)(VC6)

http://blog.csdn.net/titilima/archive/2004/07/18/44273.aspx介绍  本教程的目的是告诉你如何使用ATL创建一个COM服务器,并使用Visual...
  • ice197983
  • ice197983
  • 2007年03月26日 11:25
  • 3001

在用ATL创建组件时,如何在一个接口的实现中创建另一个已经实现了的接口的对象?

在用ATL创建组件时,我已经创建并实现了一个接口A,而当我在另一个接口B的实现中创建接口A的对象后,编译时,编译器提示接口A是个抽象类,不能创建。请问各位大侠是怎么回事?谢谢!...
  • programloveme
  • programloveme
  • 2005年05月27日 17:53
  • 1491

VS2010 ATL服务程序编写全攻略(一) - 建立ATL服务

网上有很多关于编写ATL服务程序的代码和文章,但多数仍使用Visual C++ 6.0的ATL服务程序框架。对于XP系统,Visual C++ 6.0提供的框架能够正常工作,但对于Vista、Wind...
  • sonsie007
  • sonsie007
  • 2013年04月22日 15:06
  • 7378

如何用ATL的CRegKey类来操作注册表

如何用ATL的CRegKey类来操作注册表
  • cay22
  • cay22
  • 2010年07月23日 14:13
  • 2235
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:学习ATL的一个习作 : )
举报原因:
原因补充:

(最多只允许输入30个字)