|
马上加入TC
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
由于最近有点其他事情没抽出时间,耽误了大家几天时间 我们来继续探索示例的气泡演示代码,今天探索的是由老鬼大神所写的代码 <<控件上显示气泡>>
老规矩,先上源代码,然后讲解
- //-----------------------------全局变量声明-----------------------------
- var 区_气泡句柄 = 0
- var 区_实例句柄 = 0
- var 区_跟随鼠标 = false
- //-----------------------------风格常量声明---------------------------------
- var TTS_ALWAYSTIP = #1
- var TTS_NOPREFIX = #2
- var TTS_NOANIMATE = #10
- var TTS_NOFADE = #20
- var TTS_BALLOON = #40
- //-----------------------------选项常量声明---------------------------------
- var TTF_CENTERTIP = #2
- var TTF_SUBCLASS = #10
- //-----------------------------消息常量声明---------------------------------
- var WS_EX_TOPMOST = #8
- var TTM_ADDTOOLW = #432
- var TTM_SETMAXTIPWIDTH = #418
- //-----------------------------声明结构函数-----------------------------
- //MSDN上的 RECT 结构体声明
- //typedef struct _RECT {
- // LONG left;
- // LONG top;
- // LONG right;
- // LONG bottom;
- //} RECT, *PRECT;
- function Struct_RECT()
- var 局_RECT = array()
- 局_RECT["left"] = array("long"=1,"value"=0)
- 局_RECT["top"] = array("long"=1,"value"=0)
- 局_RECT["right"] = array("long"=1,"value"=0)
- 局_RECT["bottom"] = array("long"=1,"value"=0)
- return 局_RECT
- end
- //MSDN上的 TOOLINFO 结构体声明
- //typedef struct {
- // UINT cbSize;
- // UINT uFlags;
- // HWND hwnd;
- // UINT_PTR uId;
- // RECT rect;
- // HINSTANCE hinst;
- // LPTSTR lpszText;
- //#if (_WIN32_IE >= 0x0300)
- // LPARAM lParam;
- //#endif
- //#if (_WIN32_WINNT >= Ox0501)
- // void *lpReserved;
- //#endif
- //} TOOLINFO, *PTOOLINFO, *LPTOOLINFO;
- function Struct_TOOLINFO(uFlags=0,hwnd=0,rect=0,lpszText=0)
- var 局_TOOLINFO = array()
- if(rect == 0)
- rect = Struct_RECT()
- end
- 局_TOOLINFO["cbSize"] = array("int"=1,"value"=0)
- 局_TOOLINFO["uFlags"] = array("int"=1,"value"=uFlags)
- 局_TOOLINFO["hwnd"] = array("int"=1,"value"=hwnd)
- 局_TOOLINFO["uId"] = array("int"=1,"value"=0)
- 局_TOOLINFO["rect"] = array("struct"=1,"value"=rect)
- 局_TOOLINFO["hinst"] = array("int"=1,"value"=区_实例句柄)
- 局_TOOLINFO["lpszText"] = array("int"=1,"value"=lpszText)
- 局_TOOLINFO["lParam"] = array("int"=1,"value"=0)
- //得到自己结构体的大小
- 局_TOOLINFO["cbSize"]["value"] = structlen(局_TOOLINFO)
- return 局_TOOLINFO
- end
- //-----------------------------气泡实现函数-----------------------------
- function 气泡_创建(参_最大宽度=-1,参_跟随鼠标=false,参_气泡型=false)
- var 局_风格 = TTS_ALWAYSTIP
- if(区_实例句柄 == 0)
- 区_实例句柄 = GetModuleHandle() //此处不论 气泡_创建 调用几次都仅处理一次
- end
-
- if(区_气泡句柄 == 0)
- if(参_气泡型)
- 局_风格 = 局_风格 + TTS_BALLOON
- end
- 区_跟随鼠标 = 参_跟随鼠标
- 区_气泡句柄 = CreateWindowEx(WS_EX_TOPMOST,"tooltips_class32",0,局_风格,0,0,0,0,0,0,区_实例句柄,0)
- if(区_气泡句柄 != 0)
- return SendMessage_int(区_气泡句柄,TTM_SETMAXTIPWIDTH,0,参_最大宽度) != 0
- end
- end
- return false
- end
- function 气泡_销毁()
- if(windowiswindow(区_气泡句柄))
- if(windowclose(区_气泡句柄))
- 区_气泡句柄 = 0
- return true
- end
- end
- return false
- end
- function 气泡_添加(参_控件名,参_提示文本="",参_父名称="")
- var 局_参数=TTF_SUBCLASS,局_矩形=0,局_提示,局_句柄,局_结构
- if(windowiswindow(区_气泡句柄))
- 局_句柄 = controlgethandle(参_控件名,参_父名称)
- 局_矩形 = GetClientRect(局_句柄)
- 局_提示 = varaddress(参_提示文本)
- if(!区_跟随鼠标)
- 局_参数 = 局_参数 + TTF_CENTERTIP
- end
- 局_结构 = Struct_TOOLINFO(局_参数,局_句柄,局_矩形,局_提示)
- return SendMessage_Struct(区_气泡句柄,TTM_ADDTOOLW,0,局_结构) != 0
- end
- return false
- end
- //-----------------------------声明系统函数-----------------------------
- function SendMessage_int(hWnd,Msg,wParam,lParam)
- return dllcall("User32.dll","int","SendMessageW","int",hWnd,"int",Msg,"int",wParam,"int",lParam)
- end
- function SendMessage_Struct(hWnd,Msg,wParam,lParam)
- return dllcall("User32.dll","int","SendMessageW","int",hWnd,"int",Msg,"int",wParam,"struct",lParam)
- end
- function CreateWindowEx(dwExStyle,lpClassName,lpWindowName,dwStyle,x,y,nWidth,nHeight,hWndParent,hMenu,hInstance,lpParam)
- return dllcall("User32.dll","int","CreateWindowExW","int",dwExStyle,"wchar *",lpClassName,"wchar *",lpWindowName,"int",dwStyle,"int",x,"int",y,"int",nWidth,"int",nHeight,"int",hWndParent,"int",hMenu,"int",hInstance,"int",lpParam)
- end
- function GetModuleHandle()
- return dllcall("Kernel32.dll","int","GetModuleHandleW","int",0)
- end
- function GetClientRect(hWnd)
- var lpRect = Struct_RECT()
- if(dllcall("User32.dll","int","GetClientRect","int",hWnd,"struct",lpRect) != 0)
- return lpRect
- end
- return 0
- end
复制代码 接下来我们从源码头部讲起,
18行之前 都是常量的声明,这点想必大家都明白, 至于常量的查询,大家可以使用msdn
19-70行之间 这一段代码是结构体的声明,在控件气泡提示函数中,我们使用的时候结构体是有两层的,我们平常的说法就是嵌套,dllcall经常多次优化现在已经最新版本已经支持三层结构的嵌套,
当然我们接下来 还是关心我们的结构体嵌套如实现,注意到这行下面这行代码
- 局_TOOLINFO["rect"] = array("struct"=1,"value"=rect)
复制代码 大家可以看到, 老鬼大神,把不同的结构体是分开封装的,这样子就可以做到不用结构体之间的复用,而不需要每次都创建新的结构体,大家在写代码的过程中也可以多学习这种技巧,一些比较通用的函数可以做到一次定义多次使用,这样同时也可以减少代码量
我们在看结构体定义的同时还要注意到一个问题 关于字符串的定义,在结构体中字符串的定义有两种方式,一种直接结构的指定大小的空间,就例如我们之前讲的拖盘气泡,另外一种就是只需要他的字符串的首地址就可以了
我们看下面代码,msdn上的声明与TC声明对照一下,对于新手来讲这个地方可能会有点迷糊,后期的讲解中,我们会陆续遇到这种情况的,大家熟悉一段时间之后就明白怎么回事了
结构声明在这里我们就看完了,接下来我们开始进入功能实现部分,
简单看了下,老鬼大神为控件气泡的提示,总共封装了三个函数,与清风大神对于拖盘气泡封装的函数结构差不多.
下面我将一一讲解 每个函数中 每个api的的功能
1、气泡_创建(
- function 气泡_创建(参_最大宽度=-1,参_跟随鼠标=false,参_气泡型=false)
- var 局_风格 = TTS_ALWAYSTIP
- if(区_实例句柄 == 0)
- 区_实例句柄 = GetModuleHandle() //此处不论 气泡_创建 调用几次都仅处理一次
- end
- if(区_气泡句柄 == 0)
- if(参_气泡型)
- 局_风格 = 局_风格 + TTS_BALLOON
- end
- 区_跟随鼠标 = 参_跟随鼠标
- 区_气泡句柄 = CreateWindowEx(WS_EX_TOPMOST,"tooltips_class32",0,局_风格,0,0,0,0,0,0,区_实例句柄,0)
- if(区_气泡句柄 != 0)
- return SendMessage_int(区_气泡句柄,TTM_SETMAXTIPWIDTH,0,参_最大宽度) != 0
- end
- end
- return false
- end
复制代码
首先我们要创建一个承载气泡内容的窗口,于是就有了我们的 气泡_创建函数,
在这个窗口中,我们最没有使用到结构体,只是创建了一个 类名为 "tooltips_class32"窗口,同学们可能会问,为什么要类名一定要为它呢,这个解释起来,历史悠久长久,简单说吧就是微软的win窗口程序里面专门用于气泡类显示的窗口,创建窗口的时候,记得要为窗口设置好对应的属性(TTS_BALLOON),否则窗口可能会不显示哦
当我们窗口创建成功后,我们需要向它发送一个消息,让它支持多行文本显示,这个消息就是 TTM_SETMAXTIPWIDTH
2、气泡_添加
- function 气泡_添加(参_控件名,参_提示文本="",参_父名称="")
- var 局_参数=TTF_SUBCLASS,局_矩形=0,局_提示,局_句柄,局_结构
- if(windowiswindow(区_气泡句柄))
- 局_句柄 = controlgethandle(参_控件名,参_父名称)
- 局_矩形 = GetClientRect(局_句柄)
- 局_提示 = varaddress(参_提示文本)
- if(!区_跟随鼠标)
复制代码 添加气泡,大家应该比较好理解就是在给指定的控件上,显示对应的气泡描述信息,在这个地方,老鬼大神 定义了一系列比较多的自定的函数,其作用也就为了让代码看起来更加简洁易用
在这我们需要注意的 有两处
其一,字符串的传入,需要使用地址,这个之前 跟大家讲解过了,大家区别字符串是需要地址,还是需要字符源串做为参数很简单,看msdn上的定义 有没[]这样的方括号,如果有的话,那就就是使用的字符源码,否则就需要使用地址
其二,SendMessage_Struct 此函数是整个功能的命脉所有,所有信息设置完以后都是通过此函数,通知,并设置提示框里面的文本
3、气泡_销毁
- function 气泡_销毁()
- if(windowiswindow(区_气泡句柄))
- if(windowclose(区_气泡句柄))
- 区_气泡句柄 = 0
- return true
- end
- end
- return false
- end
复制代码 我们在退出程序的时候,对相应的资源做出释放,所以,我在们程序退出之前 一定要注意关闭我们的气泡窗口
相信通过部分代码的解析,对于大部分同学对dllcall中的结构体的使用有了更深一步的了解,接下来的日子里,只要有时间 我会陆续为大家推出一系列win32 api的使用教程贴
熟悉win32开发的同学可以与我一起,同大家分享win32 的使用心得
|
评分
-
查看全部评分
|