TC官方合作论坛

 找回密码
 立即注册
查看: 3399|回复: 9

TC5.0 Win32 api一日一例 气泡示例解析(2)

[复制链接]
发表于 2015-3-31 01:22:00 | 显示全部楼层 |阅读模式

马上加入TC

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
    由于最近有点其他事情没抽出时间,耽误了大家几天时间    我们来继续探索示例的气泡演示代码,今天探索的是由老鬼大神所写的代码 <<控件上显示气泡>>
    老规矩,先上源代码,然后讲解

  1. //-----------------------------全局变量声明-----------------------------
  2. var 区_气泡句柄                                                = 0
  3. var 区_实例句柄                                                = 0
  4. var 区_跟随鼠标                                                = false
  5. //-----------------------------风格常量声明---------------------------------
  6. var TTS_ALWAYSTIP                                        = #1
  7. var TTS_NOPREFIX                                        = #2
  8. var TTS_NOANIMATE                                        = #10
  9. var TTS_NOFADE                                                = #20
  10. var TTS_BALLOON                                                = #40
  11. //-----------------------------选项常量声明---------------------------------
  12. var TTF_CENTERTIP                                        = #2
  13. var TTF_SUBCLASS                                        = #10
  14. //-----------------------------消息常量声明---------------------------------
  15. var WS_EX_TOPMOST                                        = #8
  16. var TTM_ADDTOOLW                                        = #432
  17. var TTM_SETMAXTIPWIDTH                                = #418
  18. //-----------------------------声明结构函数-----------------------------
  19. //MSDN上的 RECT 结构体声明
  20. //typedef struct _RECT {
  21. //  LONG left;
  22. //  LONG top;
  23. //  LONG right;
  24. //  LONG bottom;
  25. //} RECT, *PRECT;

  26. function Struct_RECT()
  27.     var 局_RECT = array()
  28.     局_RECT["left"]                                        = array("long"=1,"value"=0)
  29.     局_RECT["top"]                                        = array("long"=1,"value"=0)
  30.     局_RECT["right"]                                = array("long"=1,"value"=0)
  31.     局_RECT["bottom"]                                = array("long"=1,"value"=0)
  32.     return 局_RECT
  33. end


  34. //MSDN上的 TOOLINFO 结构体声明
  35. //typedef struct {
  36. //  UINT      cbSize;
  37. //  UINT      uFlags;
  38. //  HWND      hwnd;
  39. //  UINT_PTR  uId;
  40. //  RECT      rect;
  41. //  HINSTANCE hinst;
  42. //  LPTSTR    lpszText;
  43. //#if (_WIN32_IE >= 0x0300)
  44. //  LPARAM    lParam;
  45. //#endif
  46. //#if (_WIN32_WINNT >= Ox0501)
  47. //  void      *lpReserved;
  48. //#endif
  49. //} TOOLINFO, *PTOOLINFO, *LPTOOLINFO;

  50. function Struct_TOOLINFO(uFlags=0,hwnd=0,rect=0,lpszText=0)
  51.     var 局_TOOLINFO = array()
  52.     if(rect == 0)
  53.         rect = Struct_RECT()
  54.     end
  55.     局_TOOLINFO["cbSize"]                        = array("int"=1,"value"=0)
  56.     局_TOOLINFO["uFlags"]                        = array("int"=1,"value"=uFlags)
  57.     局_TOOLINFO["hwnd"]                                = array("int"=1,"value"=hwnd)
  58.     局_TOOLINFO["uId"]                                = array("int"=1,"value"=0)
  59.     局_TOOLINFO["rect"]                                = array("struct"=1,"value"=rect)
  60.     局_TOOLINFO["hinst"]                        = array("int"=1,"value"=区_实例句柄)
  61.     局_TOOLINFO["lpszText"]                        = array("int"=1,"value"=lpszText)
  62.     局_TOOLINFO["lParam"]                        = array("int"=1,"value"=0)
  63.     //得到自己结构体的大小
  64.     局_TOOLINFO["cbSize"]["value"]        = structlen(局_TOOLINFO)
  65.     return 局_TOOLINFO
  66. end

  67. //-----------------------------气泡实现函数-----------------------------

  68. function 气泡_创建(参_最大宽度=-1,参_跟随鼠标=false,参_气泡型=false)
  69.     var 局_风格 = TTS_ALWAYSTIP
  70.     if(区_实例句柄 == 0)
  71.         区_实例句柄 = GetModuleHandle()                                                                                                                        //此处不论 气泡_创建 调用几次都仅处理一次
  72.     end
  73.    
  74.     if(区_气泡句柄 == 0)
  75.         if(参_气泡型)
  76.             局_风格 = 局_风格 + TTS_BALLOON                                                                                                                                
  77.         end
  78.         区_跟随鼠标 = 参_跟随鼠标
  79.         区_气泡句柄 = CreateWindowEx(WS_EX_TOPMOST,"tooltips_class32",0,局_风格,0,0,0,0,0,0,区_实例句柄,0)
  80.         if(区_气泡句柄 != 0)
  81.             return SendMessage_int(区_气泡句柄,TTM_SETMAXTIPWIDTH,0,参_最大宽度) != 0
  82.         end
  83.     end
  84.     return false
  85. end

  86. function 气泡_销毁()
  87.     if(windowiswindow(区_气泡句柄))
  88.         if(windowclose(区_气泡句柄))
  89.             区_气泡句柄 = 0
  90.             return true
  91.         end
  92.     end
  93.     return false
  94. end

  95. function 气泡_添加(参_控件名,参_提示文本="",参_父名称="")
  96.     var 局_参数=TTF_SUBCLASS,局_矩形=0,局_提示,局_句柄,局_结构
  97.     if(windowiswindow(区_气泡句柄))
  98.         局_句柄 = controlgethandle(参_控件名,参_父名称)
  99.         局_矩形 = GetClientRect(局_句柄)
  100.         局_提示 = varaddress(参_提示文本)
  101.         if(!区_跟随鼠标)
  102.             局_参数 = 局_参数 + TTF_CENTERTIP
  103.         end
  104.         局_结构 = Struct_TOOLINFO(局_参数,局_句柄,局_矩形,局_提示)
  105.         return SendMessage_Struct(区_气泡句柄,TTM_ADDTOOLW,0,局_结构) != 0
  106.     end
  107.     return false
  108. end

  109. //-----------------------------声明系统函数-----------------------------

  110. function SendMessage_int(hWnd,Msg,wParam,lParam)
  111.     return dllcall("User32.dll","int","SendMessageW","int",hWnd,"int",Msg,"int",wParam,"int",lParam)
  112. end

  113. function SendMessage_Struct(hWnd,Msg,wParam,lParam)
  114.     return dllcall("User32.dll","int","SendMessageW","int",hWnd,"int",Msg,"int",wParam,"struct",lParam)
  115. end

  116. function CreateWindowEx(dwExStyle,lpClassName,lpWindowName,dwStyle,x,y,nWidth,nHeight,hWndParent,hMenu,hInstance,lpParam)
  117.     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)
  118. end

  119. function GetModuleHandle()
  120.     return dllcall("Kernel32.dll","int","GetModuleHandleW","int",0)
  121. end

  122. function GetClientRect(hWnd)
  123.     var lpRect = Struct_RECT()
  124.     if(dllcall("User32.dll","int","GetClientRect","int",hWnd,"struct",lpRect) != 0)
  125.         return lpRect
  126.     end
  127.     return 0
  128. end
复制代码
接下来我们从源码头部讲起,

18行之前 都是常量的声明,这点想必大家都明白, 至于常量的查询,大家可以使用msdn

19-70行之间 这一段代码是结构体的声明,在控件气泡提示函数中,我们使用的时候结构体是有两层的,我们平常的说法就是嵌套,dllcall经常多次优化现在已经最新版本已经支持三层结构的嵌套,
当然我们接下来 还是关心我们的结构体嵌套如实现,注意到这行下面这行代码
  1. 局_TOOLINFO["rect"]        = array("struct"=1,"value"=rect)
复制代码
大家可以看到, 老鬼大神,把不同的结构体是分开封装的,这样子就可以做到不用结构体之间的复用,而不需要每次都创建新的结构体,大家在写代码的过程中也可以多学习这种技巧,一些比较通用的函数可以做到一次定义多次使用,这样同时也可以减少代码量

我们在看结构体定义的同时还要注意到一个问题 关于字符串的定义,在结构体中字符串的定义有两种方式,一种直接结构的指定大小的空间,就例如我们之前讲的拖盘气泡,另外一种就是只需要他的字符串的首地址就可以了
我们看下面代码,msdn上的声明与TC声明对照一下,对于新手来讲这个地方可能会有点迷糊,后期的讲解中,我们会陆续遇到这种情况的,大家熟悉一段时间之后就明白怎么回事了
  1. // LPTSTR lpszText;
复制代码
结构声明在这里我们就看完了,接下来我们开始进入功能实现部分,
简单看了下,老鬼大神为控件气泡的提示,总共封装了三个函数,与清风大神对于拖盘气泡封装的函数结构差不多.
下面我将一一讲解 每个函数中 每个api的的功能
1、气泡_创建(
  1. function 气泡_创建(参_最大宽度=-1,参_跟随鼠标=false,参_气泡型=false)
  2. var 局_风格 = TTS_ALWAYSTIP
  3. if(区_实例句柄 == 0)
  4. 区_实例句柄 = GetModuleHandle()        //此处不论 气泡_创建 调用几次都仅处理一次
  5. end

  6. if(区_气泡句柄 == 0)
  7. if(参_气泡型)
  8. 局_风格 = 局_风格 + TTS_BALLOON        
  9. end
  10. 区_跟随鼠标 = 参_跟随鼠标
  11. 区_气泡句柄 = CreateWindowEx(WS_EX_TOPMOST,"tooltips_class32",0,局_风格,0,0,0,0,0,0,区_实例句柄,0)
  12. if(区_气泡句柄 != 0)
  13. return SendMessage_int(区_气泡句柄,TTM_SETMAXTIPWIDTH,0,参_最大宽度) != 0
  14. end
  15. end
  16. return false
  17. end
复制代码

首先我们要创建一个承载气泡内容的窗口,于是就有了我们的 气泡_创建函数,
在这个窗口中,我们最没有使用到结构体,只是创建了一个 类名为 "tooltips_class32"窗口,同学们可能会问,为什么要类名一定要为它呢,这个解释起来,历史悠久长久,简单说吧就是微软的win窗口程序里面专门用于气泡类显示的窗口,创建窗口的时候,记得要为窗口设置好对应的属性(TTS_BALLOON),否则窗口可能会不显示哦
当我们窗口创建成功后,我们需要向它发送一个消息,让它支持多行文本显示,这个消息就是 TTM_SETMAXTIPWIDTH


2、气泡_添加
  1. function 气泡_添加(参_控件名,参_提示文本="",参_父名称="")
  2.     var 局_参数=TTF_SUBCLASS,局_矩形=0,局_提示,局_句柄,局_结构
  3.     if(windowiswindow(区_气泡句柄))
  4.         局_句柄 = controlgethandle(参_控件名,参_父名称)
  5.         局_矩形 = GetClientRect(局_句柄)
  6.         局_提示 = varaddress(参_提示文本)
  7.         if(!区_跟随鼠标)
复制代码
添加气泡,大家应该比较好理解就是在给指定的控件上,显示对应的气泡描述信息,在这个地方,老鬼大神 定义了一系列比较多的自定的函数,其作用也就为了让代码看起来更加简洁易用
在这我们需要注意的 有两处
其一,字符串的传入,需要使用地址,这个之前 跟大家讲解过了,大家区别字符串是需要地址,还是需要字符源串做为参数很简单,看msdn上的定义 有没[]这样的方括号,如果有的话,那就就是使用的字符源码,否则就需要使用地址
其二,SendMessage_Struct 此函数是整个功能的命脉所有,所有信息设置完以后都是通过此函数,通知,并设置提示框里面的文本


3、气泡_销毁
  1. function 气泡_销毁()
  2. if(windowiswindow(区_气泡句柄))
  3. if(windowclose(区_气泡句柄))
  4. 区_气泡句柄 = 0
  5. return true
  6. end
  7. end
  8. return false
  9. end
复制代码
我们在退出程序的时候,对相应的资源做出释放,所以,我在们程序退出之前 一定要注意关闭我们的气泡窗口

相信通过部分代码的解析,对于大部分同学对dllcall中的结构体的使用有了更深一步的了解,接下来的日子里,只要有时间 我会陆续为大家推出一系列win32 api的使用教程贴
熟悉win32开发的同学可以与我一起,同大家分享win32 的使用心得


评分

参与人数 1威望 +10 收起 理由
sam7894604 + 10 淡定

查看全部评分

回复

使用道具 举报

发表于 2015-3-31 01:38:36 | 显示全部楼层
杀花~~~~~~
回复

使用道具 举报

发表于 2015-3-31 05:36:07 | 显示全部楼层
都被你讲老了...{:soso_e148:}
清风事务繁忙,有问题进群问
我出没 52595974  96067839

会尽可能抽空回应~
回复 支持 反对

使用道具 举报

发表于 2015-3-31 08:13:04 | 显示全部楼层
杀花~~~~~~
回复

使用道具 举报

 楼主| 发表于 2015-3-31 09:32:33 | 显示全部楼层
sam7894604 发表于 2015-3-31 05:36
都被你讲老了...
清风事务繁忙,有问题进群问
我出没 52595974  96067839

回复 支持 反对

使用道具 举报

发表于 2015-3-31 11:51:18 | 显示全部楼层
写个气泡就牛屄啊
回复 支持 反对

使用道具 举报

发表于 2015-3-31 12:14:39 | 显示全部楼层
积极回帖,认真学习,提高知名度
回复 支持 反对

使用道具 举报

发表于 2015-4-1 00:42:30 | 显示全部楼层
我也顶一个
回复 支持 反对

使用道具 举报

发表于 2015-4-1 04:11:29 来自手机 | 显示全部楼层
z不懂的
回复

使用道具 举报

发表于 2015-4-1 04:11:31 来自手机 | 显示全部楼层
z不懂的
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关闭

推荐上一条 /2 下一条

关闭

小黑屋|TC官方合作论坛 (苏ICP备18045623号)

GMT+8, 2024-5-17 18:20 , Processed in 0.041536 second(s), 23 queries .

Powered by 海安简单软件服务部

© 2008-2019 版权所有 保留所有权利

快速回复 返回顶部 返回列表