SetWindowLong设置‘自定义消息处理函数’问题

yjy1001 2003-12-25 12:08:28
我想 Panle 能处理 WM_RBUTTONDBLCLK 消息(鼠标右键双击),
使用SetWindowLong修改Panel的窗体消息处理函数为‘自定义消息处理函数’。

修改是修改成功了,可惜 —— 我捕获不到 …… 大侠们帮帮忙,谢谢先!!!

程序原代码如下:
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
void *OldProc; // 保存旧的消息处理函数地址入口

//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::SaveOldWinProc(HWND hWnd)
{
//获取 旧的消息处理函数的地址入 OldProc 中
//窗体虚构(解构)前还原
OldProc = (void*)::GetWindowLong(hWnd,GWL_WNDPROC);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::SetNewWinProc(HWND hWnd)
{
//得到自定义消息函数的内存地址
void *ObjectInst=::MakeObjectInstance(NewProc);

//设置 对象的消息处理函数为自定义消息处理函数
::SetWindowLong(hWnd,GWL_WNDPROC,(long)ObjectInst);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::SetOldWinProc(HWND hwnd)
{
//还原消息处理函数,利用全局变量 OldProc
if(OldProc != NULL)
{
::SetWindowLong(hwnd,GWL_WNDPROC,(long)OldProc);
}
}

void __fastcall TForm1::Button1Click(TObject *Sender)
{
//保存 Panel1 的消息处理函数地址
SaveOldWinProc(Panel1->Handle);

//设置 Panel1 的消息处理函数地址为 自定义函数
SetNewWinProc(Panel1->Handle);
}
//-------------------------------------------------------------
void __fastcall TForm1::NewProc(TMessage &Msg)
{
//自定义消息处理函数
switch (Msg.Msg)
{
case WM_LBUTTONDOWN://左击
ShowMessage("my left btn down");
break;
case WM_RBUTTONDBLCLK://右键双击
ShowMessage("my right btn db_clk");
break;
case WM_LBUTTONDBLCLK://双击
ShowMessage("my left btn db_clk");
break;
case WM_MOUSEMOVE:
ShowMessage("Mouse Move");
break;
default:
ShowMessage("......");//总是在这里~! 晕倒
}
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
SetOldWinProc(Panel1->Handle);//还原 消息处理函数
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormDestroy(TObject *Sender)
{
SetOldWinProc(Panel1->Handle);//还原消息处理函数,否则虚构(解构)不成功
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Panel1Click(TObject *Sender)
{
ShowMessage("Panel1 OnClick");//Panel1 的OnClick 事件
}
//---------------------------------------------------------------------------

我估计是 自己定义消息处理(NewProc 函数)的时候,switch 写得不对,
但不知道该怎么写,才能捕获 WM_RBUTTONDBLCLK 消息
...全文
307 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
huoniao1976 2003-12-25
  • 打赏
  • 举报
回复

LRESULT Proc(HWND hWnd, UINT message, WPARAM wparam , LPARAM lParam);
WNDPROC old;

void __fastcall TForm1::Button1Click(TObject *Sender)
{
old =(WNDPROC) GetWindowLong(Panel1->Handle, GWL_WNDPROC);
::SetWindowLong(Panel1->Handle, GWL_WNDPROC, (long)Proc);
}
//---------------------------------------------------------------------------


LRESULT Proc(HWND hWnd , UINT message , WPARAM wParam , LPARAM lParam)
{
if (message == WM_RBUTTONDBLCLK )
{
ShowMessage("aaa");
}
::CallWindowProc((int ( __stdcall *)())old , hWnd, message , wParam , lParam);
}
可以的
yjy1001 2003-12-25
  • 打赏
  • 举报
回复
为什么提交不了FQA?!!

晕!
yjy1001 2003-12-25
  • 打赏
  • 举报
回复
感谢你的解答……问题已经解决,如老妖所加,只需要加

TForm::Dispatch(&Msg);
就OK!了

在加50分给老妖~!

筑老妖圣诞快乐!!!

yjy1001 2003-12-25
  • 打赏
  • 举报
回复
TForm::Dispatch(&Msg);
加一句就够了?!

我看看 —— 谢谢 老妖~! 解决后立刻揭贴!
ccrun.com 2003-12-25
  • 打赏
  • 举报
回复
// 为了效果更好,在Form上加个Label,然后:

void __fastcall TForm1::NewProc(TMessage &Msg)
{
TForm::Dispatch(&Msg);
//自定义消息处理函数
switch (Msg.Msg)
{
case WM_LBUTTONDOWN://左击
Label1->Caption = "my left btn down";
break;
case WM_RBUTTONDBLCLK://右键双击
Label1->Caption = "my right btn db_clk";
break;
case WM_LBUTTONDBLCLK://双击
Label1->Caption = "my left btn db_clk";
break;
case WM_MOUSEMOVE:
Label1->Caption = "Mouse Move";
break;
default:
break;
//ShowMessage("......");//总是在这里~! 晕倒
}
}
yjy1001 2003-12-25
  • 打赏
  • 举报
回复
自己up一下~! 高手们 ---- 帮帮忙!
第一课: Windows程序运行原理及程序编写流程,窗口产生过程,句柄原理,消息队列,回调函数,窗口关闭与应用程序退出的工作关系,使用VC++的若干小技巧,stdcall与cdecl调用规范的比较,初学者常犯错误及注意事项。我们通常不必要知晓每一个函数和消息。但另一方面,也不得不记住其中的一部分,否则很难将VC++运用自如。到底该记住哪些,这在我们的课程中都会涉及到。 第二课: C++经典语法与应用,类的编写与应用,构造与析构函数,函数的重载,类的继承,函数覆盖,基类与派生类的构造函数、析构函数先后调用顺序,如何在派生类构造函数中向基类的构造函数传递参数,this成员变量,类型转换的内幕,虚拟函数与奇妙多态性。VC工程的编译原理与过程,将工程中不同的类拆分到不同的原文件中,每一个类由一个.h和.cpp文件共同完成,然后解决头文件重复定义问题,培养了学员良好的编程习惯,也为以后分析MFC Appwizard生成的工程奠定了良好基础。 第三课: 讲述MFC AppWizard的原理与MFC程序框架的剖析。AppWizard是一个原代码生成工具,是计算机辅助程序设计软件,Winmain在MFC程序中是如何从源程序中被隐藏的,theApp全局变量是如何被分配的,MFC框架中的几个类的作用与相互关系,MFC框架窗口是如何产生和销毁的,对窗口类的PreCreateWidow和OnCreate两个函数的着重分析,Windows窗口与C++中的CWnd类的关系。 第四课: 讲述如何运用ClassWizard及对MFC消息响应函数机制的分析,理解发送给窗口的消息是如何被MFC框架通过窗口句柄映射表和消息映射表来用窗口类的函数进行响应的。掌握设备描述表及其封装类CDC的使用,CDC是如何与具体的设备发生关联的,融合具体的画图程序进行分析。如何设置封闭图形的填充刷子(位图画刷与透明画刷的使用)。 第五课: 掌握CDC的文字处理程序的编写,如何产生自定义字体和自定义插入符,熟悉对CString类的使用。通过对kala ok程序的编写,讲解定时器的使用和DrawText函数的巧妙运用。讲解如何使用CDC的裁减功能。 第六课: 菜单的工作原理及编写应用,菜单命令消息在MFC框架程序的几个类中的传递顺序和处理过程。标记菜单的实现原理、图形菜单的实现及常犯错误的分析,GetSystemMetrics的应用,快捷弹出菜单的实现方式及其命令响应函数有效范围(与弹出菜单时所指定的父窗口有密切的关系,最底层的子窗口具有最优先的处理机会)。 第七课.: 动态菜单的编写,如何让程序在运行时产生新的菜单项及如何手工为这些新产生的菜单命令安排处理函数,如何在顶层窗口中截获对菜单命令的处理,更进一步掌握CString类的应用。 第八课.: 对话框用户界面程序的编写,如何向对话框控件联接数据成员及其实现机理,如何向对话框控关联控件类,如何利用对话框类的成员函数向控件发送消息和获取对话框控件的类指针,如何直接利用对话框控件类操纵对话框控件(发送消息和直接调用成员函数)。如何在程序运行时产生和销毁控件。对话框控件的几种操作方式的优劣比较分析。 第九课: 如何让对话框上的文本框在程序启动后立即获得焦点,如何利用SetWindowLong改变窗口的回调函数,通过改变文本框的默认回车处理方式进行演示。实现多个输入文本框间通过回车逐一向下传递焦点的另一种巧妙方法(用缺省按钮来处理)。利用SetWindowLong和定时器轮回改变窗口的图标。如何实现对话框的部分收缩和展开。如何在主对话框程序启动时立即隐藏对话框的巧妙实现方式与精妙思想(不能直接在OnInitDialog处理。包括自定义消息的实现) 第十课: 如何制作属性页对话框和向导对话框,融合讲解组合框(如何调整组合框的大小)、列表框、单选按钮、复选按钮 等常用对话框控件的多种使用方法。如何限制用户在不满足设定的条件时切换到其他属性页和向导页。 第十一课: 如何修改MFC AppWizard向导生成的框架程序的外观,包括修改标题栏的多种方式及原理,修改图标、光标、背景的两种方法。如何给应用程序增加工具栏和删除工具栏按钮。定制状态栏,在CView中获取状态栏对象的几种方式,在状态栏中添加时钟显示(掌握CTime类和静态成员变量和函数的用法),鼠标坐标显示,进度条(主窗口产生后立即产生进度条的巧妙思想,不能在OnCreate函数中直接处理,要用到自定义消息的方法)。如何为窗口添加背景位图。 第十二课: 如何使用自定义画笔(颜色,线宽,线形),画刷(形状,颜色)。如何为程序中添加选项菜单和选项设置对话框,如何使用标准颜色对话框,窗口重绘原理,在选项对话框中实现预览功能。实现选项对话框和窗口类中的数据交换。 第十三课: 如何让CDC上输出的文字、图形具有保持功能,元文件设备描述表的使用,CpaintDC与CClientDC的区别与应用,OnPaint与Ondraw在CView中的关系及实现内幕,集合类CObArray的使用,滚动窗口的实现,设备坐标与逻辑坐标的转换。 第十四课: 文件读写,CFileDialog,CFile,fstream,CArchive类的使用与比较。在应用中讲解const char *与char * const的区别,字符串的使用原理,如何使用CString的内存缓冲区。注册表与win.ini文件的读写方式及相关知识点。 第十五课: 如何利用CDocument类的串行化存储功能及MFC框架程序提供的文件打开与保存功能的实现原理。如何实现类对串行化的支持,CObArray的串行化实现内幕。MFC框架程序的几个主要类之间如何获得相互的指针引用。 第十六课: 网络程序的编写,Socket是连接应用程序与网络驱动程序的桥梁,Socket在应用程序中创建,通过bind与驱动程序建立关系。此后,应用程序送给Socket的数据,由Socket交给驱动程序向网络上发送出去。计算机从网络上收到与该Socket绑定的IP+Port相关的数据后,由驱动程序交给Socket,应用程序便可从该Socket中提取接收到的数据。网络应用程序就是这样通过socket进行数据的发送与接收的。UDP与TCP的工作原理与编写过程,包含如何在程序中连接库文件,telnet工具软件在编写网络程序中的用途 第十七课: 多线程程序的编写,如何通过互斥来保证多线程的安全。如何利用命名互斥保证只有一份程序实例被运行,结合多线程,网络编程,自定义消息,数据类型转换,如何改变文本框对回车的默认处理方式等技术编写网络聊天程序。 第十八课: 动态连接库程序的编写,库函数的两种输出方式。调用程序对动态连接库的静态连接与动态连接方式,如何利用工具查看动态连接库里的函数,C/C++连接规范中的命名转变问题分析,如何获得动态连接库里的函数 的指针,如何用typedef声明指向函数的指针类型。如何调试动态连接库。 第十九课: ActiveX控件的应用与工作原理,ActiveX控件的编写,如何为控件安排属性,方法,事件,属性页,持久性存储。如何注册控件与取消控件注册。如何测试与调试控件。 第二十课: 综合答疑与一些高深主题的介绍,包括如何安装系统钩子函数,dll连接库里的全局变量数据共享问题分析,ADO数据库编程,如何将数据库记录显示在Clistview网格中。 以上内容为作者对课件的初步整理,还有很多课堂上要讲到,但在本大纲中还没有被撰稿的内容,以后将逐渐完善本大大纲。
消息,就是指Windows发出的一个通知,告诉应用程序某个事情发生了。例如,单击鼠标、改变窗口尺寸、按下键盘上的一个键都会使Windows发送一个消息给应用程序。 消息本身是作为一个记录传递给应用程序的,这个记录中包含了消息的类型以及其他信息。例如,对于单击鼠标所产生的消息来说,这个记录中包含了单击鼠标时的坐标。这个记录类型叫做TMsg,它在Windows单元中是这样声明的: type TMsg = packed record hwnd: HWND; //窗口句柄 message: UINT;//消息常量标识符 wParam: WPARAM ;// 32位消息的特定附加信息 lParam: LPARAM ;// 32位消息的特定附加信息 time: DWORD;//消息创建时的时间 pt: TPoint; //消息创建时的鼠标位置 end ; 消息中有什么? 是否觉得一个消息记录中的信息像希腊语一样?如果是这样,那么看一看下面的解释:hwnd 32位的窗口句柄。窗口可以是任何类型的屏幕对象,因为Win32能够维护大多数可 视对象的句柄(窗口、对话框、按钮、编辑框等)。message 用于区别其他消息的常量值,这些常量可以是Windows单元中预定义的常量,也 可以是自定义的常量。 wParam 通常是一个与消息有关的常量值,也可能是窗口或控件的句柄。 lParam 通常是一个指向内存中数据的指针。由于WParam、lParam和Pointer都是32位的,因此,它们之间可以相互转换。 WM_NULL =$0000 // WM_CREATE =$0001 //应用程序创建一个窗口 WM_DESTROY = $0002 //一个窗口被销毁 WM_MOVE = $0003 //移动一个窗口 WM_SIZE= $0005 //改变一个窗口的大小 WM_ACTIVATE= $0006 //一个窗口被激活或失去激活状态; WM_SETFOCUS= $0007 //获得焦点后 WM_KILLFOCUS= $0008 //失去焦点 WM_ENABLE= $000A //改变enable状态 WM_SETREDRAW= $000B //设置窗口是否能重画 WM_SETTEXT= $000C //应用程序发送此消息设置一个窗口的文本 WM_GETTEXT = $000D //应用程序发送此消息来复制对应窗口的文本到缓冲区 WM_GETTEXTLENGTH = $000E //得到与一个窗口有关的文本的长度(不包含空字符) WM_PAINT = $000F //要求一个窗口重画自己 WM_CLOSE = $0010 //当一个窗口或应用程序要关闭时发送一个信号 WM_QUERYENDSESSION= $0011 //当用户选择结束对话框或程序自己调用ExitWindows函数 WM_QUIT= $0012 //用来结束程序运行或当程序调用postquitmessage函数 WM_QUERYOPEN = $0013 //当用户窗口恢复以前的大小位置时,把此消息发送给某个图标 WM_ERASEBKGND = $0014 //当窗口背景必须被擦除时(例在窗口改变大小时) WM_SYSCOLORCHANGE = $0015 //当系统颜色改变时,发送此消息给所有顶级窗口 WM_ENDSESSION = $0016 // 当系统进程发出WM_QUERYENDSESSION消息后,此消息发送给应用程序,通知它对话是否结束 WM_SYSTEMERROR = $0017 // WM_SHOWWINDOW= $0018 //当隐藏或显示窗口是发送此消息给这个窗口 WM_ACTIVATEAPP = $001C //发此消息给应用程序哪个窗口是激活的,哪个是非激活的; WM_FONTCHANGE= $001D //当系统的字体资源库变化时发送此消息给所有顶级窗口 WM_TIMECHANGE= $001E //当系统的时间变化时发送此消息给所有顶级窗口 WM_CANCELMODE= $001F //发送此消息来取消某种正在进行的摸态(操作) WM_SETCURSOR = $0020 //如果鼠标引起光标在某个窗口中移动且鼠标输入没有被捕获时,就发消息给某个窗口 WM_MOUSEACTIVATE = $0021 //当光标在某个非激活的窗口中而用户正按着鼠标的某个键发送此消息给当前窗口 WM_CHILDACTIVATE = $0022 //发送此消息给MDI子窗口当用户点击此窗口的标题栏,或当窗口被激活,移动,改变大小 WM_QUEUESYNC= $0023 //此消息由基

1,221

社区成员

发帖
与我相关
我的任务
社区描述
C++ Builder Windows SDK/API
社区管理员
  • Windows SDK/API社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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