回调的问题

kun_c_com 2005-09-29 03:46:32
BOOL CALLBACK EnumChildProc(HWND hwnd,LPARAM lParam)
{
CRect rtCtrl,rtWnd;
if(hwnd)
{
::GetWindowRect(hwnd,&rtCtrl);
::GetWindowRect(GetParent(hwnd),&rtWnd);
rtCtrl.OffsetRect(-rtWnd.left-3,-rtWnd.top-29);

float temp;
temp= (float)rtCtrl.left*m_WidthScale;
rtCtrl.left = (int)temp;
temp= (float)rtCtrl.top*m_HeightScale;
rtCtrl.top = (int)temp;
temp = (float)rtCtrl.right*m_WidthScale;
rtCtrl.right = (int)temp;
temp =(float)rtCtrl.bottom*m_HeightScale;
rtCtrl.bottom = (int)temp;

::MoveWindow(hwnd,rtCtrl.left,rtCtrl.top,
rtCtrl.Width(),
rtCtrl.Height(),
TRUE);
return TRUE;
}
else
{
return FALSE;
}

}
void CTitleBarDlg::OnSize(UINT nType, int cx, int cy)
{
CDialog::OnSize(nType, cx, cy);
if(m_ReSizeFlag)
{
if(nType!=SIZE_MINIMIZED)
{
CRect rtWnd;
GetWindowRect(&rtWnd);
// new/Old
m_WidthScale = (float)rtWnd.Width()/(float)m_OldWidth;
m_HeightScale = (float)rtWnd.Height()/(float)m_OldHeight;
m_OldWidth = rtWnd.Width(); //保存新的Size;
m_OldHeight = rtWnd.Height();
HWND hWnd;
hWnd = GetSafeHwnd();
EnumChildWindows(hWnd,(WNDENUMPROC)EnumChildProc,0);
}
}
}

我对回调没什么概念,请大家指教
这是我正在看的程序,请问CALLBACK的原理是什么?
这两个函数的执行过程是怎样的?
谢谢!
...全文
235 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
ss3295 2005-09-30
  • 打赏
  • 举报
回复
xuexi
kun_c_com 2005-09-30
  • 打赏
  • 举报
回复
谢谢happy__888([顾问团]寻开心) 和大家的回答
现在已经有所明白了,剩下的就靠自己了

谢谢!
寻开心 2005-09-30
  • 打赏
  • 举报
回复
1 自己写的函数的参数和返回数值类型都必须和EnumChildProc的定义完全一致,只有名字可以不同。

2 可以这样理解
举个关于回调函数使用的例子吧
假如:你有一个自己定义的树类型的数据结构,你想遍历这颗树做两个不同的操作,一次是计算树有多少叶子,一次是计算树有多高。
那么你可能把树结构封装成为一个类,CMyTree
对于上面的两个需求,你可能写成内部的两个函数,这个没有问题
但是随着时间的推移,你想要再增加一个功能——计算叶子节点上的数据的和,怎么办?
要么修改自己的类的数据结构增加一个新的成员函数,要么把这个成员函数的功能在类的外部用另外一个函数来实现。
那么当需求不断增加的时候,你的类要继续修改下去吗?
其实完全不必,只要利用回调函数的机制就可以解决这个问题
你可以看到,前面的需求,其实都一个公共的遍历树的过程,只是在最终到达的叶子节点上操作不同而已, 所以你完全可以写一个独立的遍历函数,这个函数接收一个函数指针,当遍历到特定的节点的时候,调用这个函数指针来执行特定的操作。这个函数指针实际上也是回调函数。
有了这个机制,你的类就无需因为这些不断增加的需求而改变了
只要根据不同的需求写出不同的回调函数,然后调用树的遍历方法,把这些函数传递进去就可以了。
这只是回调函数的一种例子
kun_c_com 2005-09-30
  • 打赏
  • 举报
回复
谢谢!
经过大家的讲解我有些明白了,在结帖前还点不 清楚请大家指教。
请大家看看我说的对不对

请问 happy__888([顾问团]寻开心),那我自己写的这个函数如aaa()的参数必须是HWND hwnd,LPARAM lParam,不能随便写是吗?
还有就是所谓回调就只有在程序里调用了如EnumChildWindows之类的系统函数,它是要求有个用户写的回调函数的,这种情况才有所谓的回调是吗?
hundlom 2005-09-29
  • 打赏
  • 举报
回复
查些函数指针的文章就明白了。
hundlom 2005-09-29
  • 打赏
  • 举报
回复
回调函数也叫函数指针
在c语言中主要用来实现动态调用
在此的用意是按找用户(你自己)的函数去做事情!
最直接的就是settimer()中的事件,你自己写函数指针,当事件发生后,系统调用你定义的函数
zxyjyzxyjy 2005-09-29
  • 打赏
  • 举报
回复
是楼上说。
对于你在MSDN中查到的那个函数,注意它仅在Declared in Winuser.h; include Windows.h中,并没有实现,根据MSDN,它仅是对开发者提供一种函数的说明而也。注意看对它的说明吧。
寻开心 2005-09-29
  • 打赏
  • 举报
回复
可以写成 aaa(....)
只要你在
EnumChildWindows是系统的函数,每次发现一个child window就调用EnumChildProc函数
你可以用 aaa(....)替换EnumChildProc
只要在调用EnumChildWindows(hWnd,(WNDENUMPROC)aaa,0) 即可
kun_c_com 2005-09-29
  • 打赏
  • 举报
回复
谢谢大家
我这么理解你们看对不对

EnumChildWindows是Windows的函数,我在程序调用它时它去执行自己的代码,执行完后它又去调用了EnumChildProc这个函数

如果是这样,我还有点不明白的是EnumChildProc函数是自己写的,是吗?可是我查了一下MSDN里有这个函数,它的参数和这个一样,他们有关系吗?如果没有,这个函数我自己写成
aaaa(HWND hwnd,LPARAM lParam,INT i)等之类的,这样是不对的吧,为什么?
请大家指教!
寻开心 2005-09-29
  • 打赏
  • 举报
回复
CALLBACK 的基本原理就是要解决在你的程序当中如何运行别人的代码

实际上就是调用一个函数,把别人的函数的指针传递给你,你来必要的时候来调用这个函数

EnumChildWindows这个函数调用的时候,每当遇到一个子窗口就调用一次EnumChildProc函数,并且把子窗口的信息作为参数传递给EnumChildProc来使用
AleTiff 2005-09-29
  • 打赏
  • 举报
回复
CALLBACK意思是不是我插的,是给别人插的。

程序里,会先运行EnumChildWindows(),这个过程是MS写在系统里的,也就意味着你调用了MS程序员写的代码了,当MS程序员的代码获得了一些信息想要回来告诉你,他就调用你写好的CALLBACK的那个函数
EnumChildProc,这样MS程序员就完成了插入你的代码的工作。
Featured 2005-09-29
  • 打赏
  • 举报
回复
回调,你就当作函数指针好了。
Igj1012 2005-09-29
  • 打赏
  • 举报
回复
调用EnumChildWindows时传入函数指针,EnumChildWindows在适当的时候调用那个函数指针,就是回调啦

15,979

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 界面
社区管理员
  • 界面
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧