学习ATL的一个习作 : )

#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);
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
YOLO高分设计资源源码,详情请查看资源内容中使用说明 YOLO高分设计资源源码,详情请查看资源内容中使用说明 YOLO高分设计资源源码,详情请查看资源内容中使用说明 YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明
这个错误是因为 CImage::Save 函数没有重载接受 4 个参数的版本。CImage::Save 函数只有两个重载版本,它们分别接受一个文件名和一个 IStream 对象作为参数。因此,您需要修改您的代码,将第四个参数 pal 改为一个 IStream 对象,或者使用另一个函数来保存图片。 如果您想要使用 IStream 对象来保存图片,可以使用 CImage::Save 函数的第二个重载版本,它接受一个 IStream 对象作为参数。示例代码如下: ``` IStream* pStream = SHCreateMemStream(NULL, 0); if (pStream != NULL) { // 将图像保存为 BMP 格式到内存流中 bmp.Save(pStream, Gdiplus::ImageFormatBMP); // 将内存流中的数据保存到文件中 HGLOBAL hMem = NULL; GetHGlobalFromStream(pStream, &hMem); LPVOID pData = GlobalLock(hMem); DWORD dwSize = GlobalSize(hMem); HANDLE hFile = CreateFile(_T("sun.bmp"), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); DWORD dwBytesWritten = 0; WriteFile(hFile, pData, dwSize, &dwBytesWritten, NULL); CloseHandle(hFile); GlobalUnlock(hMem); pStream->Release(); } ``` 如果您想要使用另一个函数来保存图片,可以使用 Gdiplus::Bitmap::Save 函数,它接受一个文件名、一个 ImageCodecInfo 对象和一个 EncoderParameters 对象作为参数。示例代码如下: ``` CLSID clsid; GetEncoderClsid(_T("image/bmp"), &clsid); EncoderParameters encoderParams; encoderParams.Count = 0; bmp.Save(_T("sun.bmp"), &clsid, &encoderParams); ``` 其中,GetEncoderClsid 函数用来获取 BMP 格式的编码器的 CLSID,示例代码如下: ``` int GetEncoderClsid(const WCHAR* format, CLSID* pClsid) { UINT num = 0, size = 0; GetImageEncodersSize(&num, &size); if (size == 0) return -1; ImageCodecInfo* pImageCodecInfo = (ImageCodecInfo*)(malloc(size)); if (pImageCodecInfo == NULL) return -1; GetImageEncoders(num, size, pImageCodecInfo); for (UINT i = 0; i < num; ++i) { if (wcscmp(pImageCodecInfo[i].MimeType, format) == 0) { *pClsid = pImageCodecInfo[i].Clsid; free(pImageCodecInfo); return i; } } free(pImageCodecInfo); return -1; } ``` 请注意,以上示例代码仅供参考,您需要根据自己的具体情况进行修改。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值