TC官方合作论坛
标题:
TC5.0 Win32 api一日一例 气泡示例解析(2)
[打印本页]
作者:
kevinqq
时间:
2015-3-31 01:22
标题:
TC5.0 Win32 api一日一例 气泡示例解析(2)
由于最近有点其他事情没抽出时间,耽误了大家几天时间 我们来继续探索示例的气泡演示代码,今天探索的是由老鬼大神所写的代码 <<控件上显示气泡>>
老规矩,先上源代码,然后讲解
//-----------------------------全局变量声明-----------------------------
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声明对照一下,对于新手来讲这个地方可能会有点迷糊,后期的讲解中,我们会陆续遇到这种情况的,大家熟悉一段时间之后就明白怎么回事了
// LPTSTR lpszText;
复制代码
结构声明在这里我们就看完了,接下来我们开始进入功能实现部分,
简单看了下,老鬼大神为控件气泡的提示,总共封装了三个函数,与清风大神对于拖盘气泡封装的函数结构差不多.
下面我将一一讲解 每个函数中 每个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 的使用心得
作者:
dear
时间:
2015-3-31 01:38
杀花~~~~~~
作者:
sam7894604
时间:
2015-3-31 05:36
都被你讲老了...
清风事务繁忙,有问题进群问
我出没 52595974 96067839
会尽可能抽空回应~
作者:
a8012602
时间:
2015-3-31 08:13
杀花~~~~~~
作者:
kevinqq
时间:
2015-3-31 09:32
sam7894604 发表于 2015-3-31 05:36
都被你讲老了...
清风事务繁忙,有问题进群问
我出没 52595974 96067839
作者:
99365
时间:
2015-3-31 11:51
写个气泡就牛屄啊
作者:
shanshan
时间:
2015-3-31 12:14
积极回帖,认真学习,提高知名度
作者:
ez345
时间:
2015-4-1 00:42
我也顶一个
作者:
tc306
时间:
2015-4-1 04:11
z不懂的
作者:
tc306
时间:
2015-4-1 04:11
z不懂的
欢迎光临 TC官方合作论坛 (http://bbs.52tc.co/)
Powered by Discuz! X3.1